为了账号安全,请及时绑定邮箱和手机立即绑定

多层神经网络反向传播公式

多层神经网络反向传播公式

茅侃侃 2021-08-17 10:22:11
使用反向传播演算中的符号| 深度学习,第 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) 它有效,但是:最后的准确性(对于我的用例:MNIST 数字识别)还可以,但不是很好。 将第 (1) 行替换为:delta = np.dot(self.weights[k].T, delta)  # (2)从代码机器学习与Python:培训和测试的神经网络MNIST数据集还建议:delta = np.dot(self.weights[k].T, delta)代替:delta = np.dot(self.weights[k].T, tmp)(用本文的注释,它是:output_errors = np.dot(self.weights_matrices[layer_index-1].T, output_errors))这两个参数似乎是一致的:代码 (2) 比代码 (1) 好。然而,数学似乎显示出相反的情况(参见此处的视频;另一个细节:请注意,我的损失函数乘以 1/2 而它不在视频中):问题:哪个是正确的:实现(1)还是(2)?
查看完整描述

1 回答

?
呼唤远方

TA贡献1856条经验 获得超11个赞

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


问题中用 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的增长速度print np.linalg.norm(delta)比代码 (1)快得多(有助于看到这一点)。


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


现在解决了!


查看完整回答
反对 回复 2021-08-17
  • 1 回答
  • 0 关注
  • 194 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信