我正在努力学习一本关于深入学习的书,但我发现一些关于网络仿射层的内容令人困惑。假设我有一个网络,它接受一些手写数字(0 ~ 9)图像(Mnist),这些图像被扁平成一维数组,例如np.array([123, 255, 0, ...]),它将输出每个可能输出的分数,例如np.array([0., 0., 0.3, 0., 0., 0.6, 0., 0., 0., 0.1])(因此图像可能是数字5)。
下面是仿射层的实现:
class AffineLayer(object):
...
def backward(self, dy):
dx = np.dot(dy, self._W.T)
self._dW = np.dot(self._x.T, dy) # Question related part
self._db = np.sum(dy, axis=0)
dx = dx.reshape(self._original_x_shape)
return dx
...以下是一些解释:
self._W是权矩阵。self._dW = np.dot(self._x.T, y) # Question related part。X * W + B = Y
(N,2) matrix product (2,3) (1,3) (N,3).(2,)来自于X.shape of numpy.array等,为了简化我的问题,我选择了这些维数。术语结束后,现在出现了一个问题:
通过一些数学(省略),我们可以得到反向传播中使用的等式(因此代码中使用了
self._dW = np.dot(self._x.T, y)):d L T d L:--- == X * ---:d W d Y准(2,3) (2,N) * (N,3).请注意,无论如何调整N,即批处理的大小,dL/dW的维数,即L权矩阵的偏导数,都不会改变,而且总是(2,3)。 这是否意味着这些N批次的总体效果被合并/浓缩成dL/dW?这与我如何实现输出层有关,例如软最大-交叉熵层作为最后一层。我目前的结论是,N批处理意味着进行反向传播N次数,并且需要将梯度dL/dW除以N来平均/摊销该批的总效果。但现在看来,我只需要做一次,而划分应该是“第一步”。
编辑:
我还找到了似乎在最后一步将其划分为mnielsen/神经网络和深度学习- GitHub的版本,以供参考。
由于softmax-交叉熵层类是网络的最后一层,在反向传播中,它将成为我前面提到的“第一步”:
class SoftmaxCrossEntropy(object):
...
def backward(self, dout=1):
batch_size = self._t.shape[0]
# one-hot
if self._t.size == self._y.size:
dx = (self._y - self._t) / batch_size # <-- why divided by N here?
else: # not one-hot
dx = self._y * 1
dx[np.arange(batch_size), self._t] -= 1
dx = dx / batch_size # <-- why divided by N here?
return dx
...发布于 2018-04-29 12:25:00
这是否意味着这些N批输入的效果被合并/浓缩到dW中?
因为X的第一行是一个一维数组,它与第一个平面图像相关。如果我把X转到
粉末冶金T
X ,,然后是列来表示那些扁平的图像。如果N增加,尽管
结果的维数(dW)不变,计算每个元素的中间步骤
粉末冶金T d L
粉末冶金dW = X * ---
增加d Y ,,这意味着
粉末冶金N
粉末冶金dW = Sum ( pixel_info * class_scores_deriv. )
i,j n=1 i,n n,j ,哪个N是批处理
大小。显然,每个class_scores_derivative_(n,j)“加入”了dW_(i,j)的决定,但这意味着需要按batch_size = N进行除法,因为上面的求和并不是该批的平均效果,而是需要dW来表示该批的平均影响。如果我除以class_scores_deriv.的每个元素,即行
然后是dx = (self._y - self._t) / batch_size
粉末冶金N 1
粉末冶金Sum ( pixel_info * --- class_scores_deriv. )
粉末冶金n=1 i,n N n,j
粉末冶金1 N
粉末冶金= --- Sum ( pixel_info * class_scores_deriv. )
粉末冶金N n=1 i,n n,j
粉末冶金1
粉末冶金= --- dW
这是我想要的真正的N ,。
所以答案(我希望)应该是
整个批处理确定dW,但要压缩它,需要
SoftmaxCrossEntropy::backward(self, dout=1)中的分区。
https://stackoverflow.com/questions/50085616
复制相似问题