我试图在backpropagation
的简单3层神经网络中理解MNIST
。
输入图层包含weights
和bias
。标签为MNIST
,因此它是10
类向量。
第二层是linear tranform
。第三层是softmax activation
,以输出为概率。
Backpropagation
计算每一步的导数并将其称为渐变。
之前的图层会将global
或previous
渐变添加到local gradient
。我无法计算local gradient
softmax
在线的几个资源通过对softmax及其衍生物的解释,甚至给出softmax本身的代码样本
def softmax(x):
"""Compute the softmax of vector x."""
exps = np.exp(x)
return exps / np.sum(exps)
关于何时i = j
和何时i != j
解释衍生物。这是一个我想出的简单代码片段,希望能够验证我的理解:
def softmax(self, x):
"""Compute the softmax of vector x."""
exps = np.exp(x)
return exps / np.sum(exps)
def forward(self):
# self.input is a vector of length 10
# and is the output of
# (w * x) + b
self.value = self.softmax(self.input)
def backward(self):
for i in range(len(self.value)):
for j in range(len(self.input)):
if i == j:
self.gradient[i] = self.value[i] * (1-self.input[i))
else:
self.gradient[i] = -self.value[i]*self.input[j]
然后self.gradient
是local gradient
,它是一个向量。它是否正确?有没有更好的方法来写这个?
答案 0 :(得分:15)
我假设你有一个3层NN,W1
,b1
for与从输入层到隐藏层的线性转换相关联,W2
,b2
与从隐藏层到输出层的线性变换相关联。 Z1
和Z2
是隐藏图层和输出图层的输入向量。 a1
和a2
表示隐藏图层和输出图层的输出。 a2
是您预测的输出。 delta3
和delta2
是错误(反向传播),您可以看到损失函数相对于模型参数的渐变。
这是3层NN(输入层,只有一个隐藏层和一个输出层)的一般场景。您可以按照上述步骤计算易于计算的渐变!由于这篇文章的另一个答案已经指出了代码中的问题,我不会重复相同的内容。
答案 1 :(得分:9)
正如我所说,你有n^2
偏导数。
如果你做数学计算,你会发现dSM[i]/dx[k]
是SM[i] * (dx[i]/dx[k] - SM[i])
所以你应该有:
if i == j:
self.gradient[i,j] = self.value[i] * (1-self.value[i])
else:
self.gradient[i,j] = -self.value[i] * self.value[j]
而不是
if i == j:
self.gradient[i] = self.value[i] * (1-self.input[i])
else:
self.gradient[i] = -self.value[i]*self.input[j]
顺便说一句,这可以更简洁地计算(矢量化):
SM = self.value.reshape((-1,1))
jac = np.diagflat(self.value) - np.dot(SM, SM.T)
答案 2 :(得分:5)
np.exp不稳定,因为它有Inf。 所以你应该减去x中的最大值。
def softmax(x):
"""Compute the softmax of vector x."""
exps = np.exp(x - x.max())
return exps / np.sum(exps)
如果x是矩阵,请检查此笔记本中的softmax函数(https://github.com/rickiepark/ml-learn/blob/master/notebooks/5.%20multi-layer%20perceptron.ipynb)