繁体   English   中英

多层神经网络反向传播公式(使用随机梯度下降)

[英]Multi-layer neural network back-propagation formula (using stochastic gradient descent)

使用反向传播演算中的符号| 深度学习,第 4 章,我有一个 4 层(即 2 个隐藏层)神经网络的反向传播代码:

def sigmoid_prime(z): 
    return z * (1-z)  # because σ'(x) = σ(x) (1 - σ(x))

def train(self, input_vector, target_vector):
    a = np.array(input_vector, ndmin=2).T
    y = np.array(target_vector, ndmin=2).T

    # forward
    A = [a]  
    for k in range(3):
        a = sigmoid(np.dot(self.weights[k], a))  # zero bias here just for simplicity
        A.append(a)

    # Now A has 4 elements: the input vector + the 3 outputs vectors

    # back-propagation
    delta = a - y
    for k in [2, 1, 0]:
        tmp = delta * sigmoid_prime(A[k+1])
        delta = np.dot(self.weights[k].T, tmp)  # (1)  <---- HERE
        self.weights[k] -= self.learning_rate * np.dot(tmp, A[k].T) 

它有效,但是:

这两个参数似乎是一致的:代码 (2) 比代码 (1) 好。

然而,数学似乎相反(请参阅此处的视频;另一个细节:请注意,我的损失函数乘以 1/2 而它不在视频中):

在此处输入图片说明

问题:哪个是正确的:实现(1)还是(2)?


在乳胶中:

$$C = \frac{1}{2} (a^L - y)^2$$
$$a^L = \sigma(\underbrace{w^L a^{L-1} + b^L}_{z^L}) = \sigma(z^L)$$
$$\frac{\partial{C}}{\partial{w^L}} = \frac{\partial{z^L}}{\partial{w^L}} \frac{\partial{a^L}}{\partial{z^L}} \frac{\partial{C}}{\partial{a^L}}=a^{L-1} \sigma'(z^L)(a^L-y)$$
$$\frac{\partial{C}}{\partial{a^{L-1}}} = \frac{\partial{z^L}}{\partial{a^{L-1}}} \frac{\partial{a^L}}{\partial{z^L}} \frac{\partial{C}}{\partial{a^L}}=w^L \sigma'(z^L)(a^L-y)$$
$$\frac{\partial{C}}{\partial{w^{L-1}}} = \frac{\partial{z^{L-1}}}{\partial{w^{L-1}}} \frac{\partial{a^{L-1}}}{\partial{z^{L-1}}} \frac{\partial{C}}{\partial{a^{L-1}}}=a^{L-2} \sigma'(z^{L-1}) \times w^L \sigma'(z^L)(a^L-y)$$

我花了两天时间来分析这个问题,我用偏导数计算填满了几页笔记本......我可以确认:

  • 问题中用 LaTeX 写的数学是正确的
  • 代码 (1) 是正确的,它与数学计算一致:

     delta = a - y for k in [2, 1, 0]: tmp = delta * sigmoid_prime(A[k+1]) delta = np.dot(self.weights[k].T, tmp) self.weights[k] -= self.learning_rate * np.dot(tmp, A[k].T)
  • 代码(2)是错误的:

     delta = a - y for k in [2, 1, 0]: tmp = delta * sigmoid_prime(A[k+1]) delta = np.dot(self.weights[k].T, delta) # WRONG HERE self.weights[k] -= self.learning_rate * np.dot(tmp, A[k].T)

    使用 Python进行机器学习时有一个小错误:使用 MNIST 数据集训练和测试神经网络

     output_errors = np.dot(self.weights_matrices[layer_index-1].T, output_errors)

    应该

    output_errors = np.dot(self.weights_matrices[layer_index-1].T, output_errors * out_vector * (1.0 - out_vector))

现在是我花了几天才意识到的困难部分:

  • 显然代码 (2) 比代码 (1) 具有更好的收敛性,这就是为什么我误认为代码 (2) 是正确的而代码 (1) 是错误的

  • ...但实际上这只是巧合,因为learning_rate设置得太低了 原因如下:当使用代码 (2) 时,参数delta的增长速度比代码 (1) 增长得更快( print np.linalg.norm(delta)有助于看到这一点)。

  • 因此,“不正确的代码 (2)”只是通过具有更大的delta参数来补偿“学习速度太慢”,并且在某些情况下,它会导致明显更快的收敛。

现在解决了!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM