为了帮助计算 $\frac { d E } { d w _ { i j } }$ ,我们还为每个节点分别存储了两个导数:节点dE/dx的输入以及节点dE/dy的输出(见图10-18的右图,比较左图和右图)。
如图10-18右图所示(见图上箭头),下面开始反向传播误差导数。由于我们拥有此特定输入样本的预测输出,因此可以计算误差随该输出的变化情况。根据误差函数:
$$
\begin{array} { r } { E = \frac { 1 } { 2 } ( y _ { o u t p u t } - y _ { t a r g e t } ) ^ { 2 } } \end{array}
$$
可以得出:
$$
\frac { \partial E } { \partial y _ { o u t p u t } } = y _ { o u t p u t } - y _ { t a r g e t }
$$
有了dE/dy,接下来便可以根据链式法则得出dE/dx(见图10-18,从顶端往下走)。
$$
{ \frac { \partial E } { \partial x } } = { \frac { d y } { d x } } { \frac { \partial E } { \partial y } } = { \frac { d } { d x } } f ( x ) { \frac { \partial E } { \partial y } }
$$
其中,当f(x)是S型激活函数时:
$$
\begin{array} { r } { \frac { d } { d x } f ( x ) = f ( x ) ( 1 - f ( x ) ) } \end{array}
$$
一旦得出相对于某节点的总输入的误差导数,我们便可以得出相对于进入该节点的权重的误差导数:
$$
\frac { \partial E } { \partial w _ { i j } } = \frac { \partial x _ { j } } { \partial w _ { i j } } \frac { \partial E } { \partial x _ { j } } = y _ { i } \frac { \partial E } { \partial x _ { j } }
$$
根据链式法则,我们还可以根据上一层得出dE/dy。此时,形成了一个完整的循环。
$$
\frac { \partial E } { \partial y _ { i } } = \sum _ { j \in o u t ( i ) } \frac { \partial x _ { j } } { \partial y _ { i } } \frac { \partial E } { \partial x _ { j } } = \sum _ { j \in o u t ( i ) } w _ { i j } \frac { \partial E } { \partial x _ { j } }
$$
接下来,只需重复前面的几个公式,直到计算出所有误差导数即可。反向传播完成。
值得注意的是,很多常见情况都会导致反向传播算法出错。
梯度消失
反向传播依赖于梯度。较低层(更接近输入)的梯度可能会变得非常小。在深度网络中,计算这些梯度时,可能涉及许多小项的乘积。当较低层的梯度逐渐消失到0时,这些层的训练速度会非常缓慢,甚至不再训练。ReLU激活函数有助于防止梯度消失。一般来讲,我们尽量将模型的深度限制为最小的有效深度。
梯度爆炸
如果网络中的权重过大,那么较低层的梯度会涉及许多大项的乘积。在这种情况下,梯度就会爆炸:梯度过大导致难以收敛。批标准化可以降低学习速率,因而有助于防止梯度爆炸。
第10章 神经网络
323