神经网络:批量版仿射层反向传播权重矩阵更新



我试图关注一本关于深度学习的书,但我发现关于网络的仿射层的某些部分令人困惑。假设我有一个网络,它接受一些手写数字(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,)来自numpy.array等的X.shape。为了简化我的问题,我选择了这些维度数字。

术语结束,现在问题来了:

通过一些数学(省略(,我们可以得出反向传播中使用的等式,(因此代码中使用了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中?这与我将如何实现输出层有关,例如softmax交叉熵层作为最后一层。我目前的结论是,N批次意味着进行反向传播N次,并且需要将梯度dL/dW除以N来平均/摊销该批次的总效果。但现在看来,我只需要做一次,划分应该是"第一步"。

编辑:

我还找到了似乎在最后一步划分它的版本 mnielsen/neural-networks-and-deep-learning - 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
    ...

是否意味着这N批输入的效果被组合/压缩到dW中?

由于第 i

X是与第 i 个展平图像相关的一维数组。如果我将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

所以答案(我希望(应该是

整个批次确定 dW,但要压缩它,需要SoftmaxCrossEntropy::backward(self, dout=1)的划分。

最新更新