我试图用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
,它是一个向量。它是否正确?有没有更好的方法来写这个?
正如我所说,你有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)
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)