这是python中单层神经网络的快速实现:
import numpy as np
# simulate data
np.random.seed(94106)
X = np.random.random((200, 3)) # 100 3d vectors
# first col is set to 1
X[:, 0] = 1
def simu_out(x):
return np.sum(np.power(x, 2))
y = np.apply_along_axis(simu_out, 1, X)
# code 1 if above average
y = (y > np.mean(y)).astype("float64")*2 - 1
# split into training and testing sets
Xtr = X[:100]
Xte = X[100:]
ytr = y[:100]
yte = y[100:]
w = np.random.random(3)
# 1 layer network. Final layer has one node
# initial weights,
def epoch():
err_sum = 0
global w
for i in range(len(ytr)):
learn_rate = .1
s_l1 = Xtr[i].T.dot(w) # signal at layer 1, pre-activation
x_l1 = np.tanh(s_l1) # output at layer 1, activation
err = x_l1 - ytr[i]
err_sum += err
# see here: https://youtu.be/Ih5Mr93E-2c?t=51m8s
delta_l1 = 2 * err * (1 - x_l1**2)
dw = Xtr[i] * delta_l1
w -= learn_rate * dw
print("Mean error: %f" % (err_sum / len(ytr)))
epoch()
for i in range(1000):
epoch()
def predict(X):
global w
return np.sign(np.tanh(X.dot(w)))
# > 80% accuracy!!
np.mean(predict(Xte) == yte)
使用随机梯度下降进行优化。我在想如何在这里应用小批量梯度下降?
答案 0 :(得分:2)
与“经典”SGD到小批量梯度下降的区别在于您使用多个样本(所谓的小批量)来计算w
的更新。这样做的好处是,当你遵循平滑的渐变时,你在解决方向上采取的步骤会减少噪音。
要做到这一点,您需要一个内部循环来计算更新dw
,您可以在其中迭代迷你批次。例如(快速脏代码):
def epoch():
err_sum = 0
learn_rate = 0.1
global w
for i in range(int(ceil(len(ytr) / batch_size))):
batch = Xtr[i:i+batch_size]
target = ytr[i:i+batch_size]
dw = np.zeros_like(w)
for j in range(batch_size):
s_l1 = batch[j].T.dot(w)
x_l1 = np.tanh(s_l1)
err = x_l1 - target[j]
err_sum += err
delta_l1 = 2 * err * (1 - x_l1**2)
dw += batch[j] * delta_l1
w -= learn_rate * (dw / batch_size)
print("Mean error: %f" % (err_sum / len(ytr)))
在测试中给出了87%的准确度。
现在,还有一件事:你总是从头到尾经历训练集。你应该在每次迭代中 shuffle 数据。始终以相同的顺序进行操作会影响您的表现,尤其是首先是A级的所有样本,然后是B级的所有样本。这也可以让你的训练循环进行。所以只需按随机顺序浏览该集,例如与
order = np.random.permutation(len(ytr))
并在i
函数中将所有order[i]
替换为epoch()
。
更一般的说法:全局变量通常被认为是糟糕的设计,因为您无法控制哪些代码段修改变量。而是将w
作为参数传递。学习率和批量大小也是如此。