反向传播

反向传播

现在我们来到了如何让多层神经网络学习的问题上。之前我们了解了如何用梯度下降来更新权重。反向传播算法是它的一个延伸,用链式法则来找到误差与输入层到输入层链接的权重(两层神经网络)。

要更新输入到隐藏层的权重,你需要知道隐藏层节点的误差对最终输出的影响是多大。输出是由两层之间的权重决定的,这个误差是输入跟权重在网络中正向传播的结果。既然我们知道输出误差,我们可以用权重来反向传播到隐藏层。

例如,输出层的话,在每一个输出节点 k 的误差是 δko 。隐藏节点 j 的误差来自输出层和隐藏层之间的权重(以及梯度)。

梯度下降跟之前一样,只是用新的误差:

wij 是输入和隐藏层之间的权重, xi 是输入值。这个形式可以表示任意层数。权重更新步长等与步长乘以层输出误差再乘以这层的输入值。

这里,你有了输出误差,δoutput,从高层反向传播这些误差。Vin 是对这一层的输入,经过隐藏层激活后到输出节点。

通过一个实际案例学习

让我们一起过一遍计算一个简单的两层网络权重的更新过程。假设有两个输入值,一个隐藏节点,一个输出节点,隐藏层和输出层的激活函数都是 sigmoid 。下图描述了这个网络。(注意:输入在这里显示为图最下方的节点,网络的输出标记为顶端的 y^,输入本身不算做层,这也是为什么这个网络结构被称作两层网络。)

假设我们试着输入一些二分类数据,目标是 y=1。我们从正向传导开始,首先计算输入到隐藏层

h=iwixi=0.1×0.40.2×0.3=0.02

隐藏层的输出

a=f(h)=sigmoid(−0.02)=0.495.

把它作为输出层的输入,神经网络的输出是:

y^=f(Wa)=sigmoid(0.1×0.495)=0.512.

有了这个输出,我们就可以开始反向传播来计算两层的权重更新了。sigmoid 函数特性 f(Wa)=f(Wa)(1f(Wa)),输出误差是:

δo=(yy^)f(Wa)=(10.512)×0.512×(10.512)=0.122.

现在我们要通过反向传播来计算隐藏层的误差。这里我们吧输出误差与隐藏层到输出层的权重 W 相乘。隐藏层的误差 δjh=kWjkδkof(hj),这里因为只有一个隐藏节点,这就比较简单了

δh=Wδof(h)=0.1×0.122×0.495×(10.495)=0.003

有了误差,就可以计算梯度下降步长了。隐藏层到输出层权重步长是学习率乘以输出误差再乘以隐藏层激活值。

ΔW=ηδoa=0.5×0.122×0.495=0.0302

从输入到隐藏层的权重 wi,是学习率乘以隐藏节点误差再乘以输入值。

Δwi=ηδhxi=(0.5×0.003×0.1,0.5×0.003×0.3)=(0.00015,0.00045)

这个例子你可以看出用 sigmoid 做激活函数的效果。sigmoid 函数最大的导数是 0.25,输出层的误差被至少减少了75%,隐藏层的误差被减少了至少93.75%!你可以看出,如果你有很多层,用 sigmoid 激活函数函数会很快把权重降到靠近输入的细小值。这被称作梯度消失问题。后面的课程中你会学到其它的激活函数在这方面表现比它好,也被用于最新的网络架构中。

用 NumPy 来实现

现在你已经有了大部分用 NumPy 来实现反向传导的知识。

但是之前接触的是一个元素的误差项。现在在权重更新时,我们需要考虑隐藏层每个节点的误差:

Δwij=ηδjxi

首先,这里会有不同数量的输入和隐藏节点,所以试图把误差与输入当作行向量来乘会报错 

hidden_error*inputs
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-22-3b59121cb809> in <module>()
----> 1 hidden_error*x

ValueError: operands could not be broadcast together with shapes (3,) (6,)

同时,wij 现在是一个矩阵,所以右侧对应也应该有跟左侧同样的维度。幸运的是,NumPy 这些都能搞定。如果你用一个列向量序列和一个行向量序列乘,它会把列向量的第一个元素与行向量的每个元素相乘,然后第一行是一个二维序列。列向量的每一个元素会这门做,所以你会得到一个二维序列,维度是(len(column_vector), len(row_vector))

hidden_error*inputs[:,None]
array([[ -8.24195994e-04,  -2.71771975e-04,   1.29713395e-03],
       [ -2.87777394e-04,  -9.48922722e-05,   4.52909055e-04],
       [  6.44605731e-04,   2.12553536e-04,  -1.01449168e-03],
       [  0.00000000e+00,   0.00000000e+00,  -0.00000000e+00],
       [  0.00000000e+00,   0.00000000e+00,  -0.00000000e+00],
       [  0.00000000e+00,   0.00000000e+00,  -0.00000000e+00]])

这正好是我们如何计算权重更新的步长。跟以前一样,如果你的输入是一个一行的二维序列,你可以用hidden_error*inputs.T,如果 inputs 是一维序列,就不行了。

反向传播练习

接下来你会用代码来实现一次两个权重的反向传播更新。我们提供了正向传播的代码,你来实现反向传播的代码。

要做的事

  • 计算网络输出误差
  • 计算输出层误差的梯度
  • 用反向传播计算隐藏层误差
  • 计算权重更新步长
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ncst

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值