深度神经网络中的梯度丢失与梯度爆炸

神经网络的反向传播

要理解梯度丢失(vanishing gradient)和梯度爆炸,首先需要理解神经网络的反向传播算法。

一般来说,训练一个神经网络需要很多个迭代。在每个迭代中,都包含两个步骤。

  • 前馈(feed forward):它指的是从神经网络的输入开始,根据每一层的权重和偏置,逐层计算输出,直到得到神经网络的最终输出。这个输出值可以是对图片的分类,也可以是对数据走势的预测等等。
  • 反向传播(back propagation):它指的是将神经网络的输出值和标准值进行比较,从而得到误差值。然后计算网络的每一层对这个误差值的“贡献”,并对每一层的权重和偏置进行调整的过程。

一个标准的神经网络训练迭代如下图所示:

Screen Shot 2017-03-11 at 9.00.21 AM

链式求导法则

那么,我们如何根据误差值更新每一个权重和偏置呢?这就涉及到我们如何计算误差值对每一个权重和偏置的梯度(gradient)。有了这个梯度,我们就可以利用梯度下降法来更新权重和偏置了。在计算误差对每个权重和偏置的梯度的过程中,我们利用了链式求导法则。下面让我们用一个具体的例子来说明链式求导在反向传播中是如何工作的。

让我们考虑下面这个简单的深度神经网络,它的每一层都只包含一个神经元,一共有三个隐藏层:

Screen Shot 2017-03-07 at 9.21.20 PM

这里的w_1, w_2, \dots表示权重,b_1, b_2, \dots表示偏置,C表示网络的输出,每个神经元的激活函数(activation function)记为\deltaa_j表示第j个神经元的输出,其中a_0等于网络的输入,a_j = \delta(z_j)z_j = w_j * a_{j-1} + b_j

在反向传播过程中,我们需要计算C对所有权重w_j和偏置b_j的偏导数。下面我们以\partial C/\partial b_1为例,说明反向传播是如何工作的。

根据链式求导法则\partial C/\partial b_1可以被写为:

\frac{\partial C}{\partial b_1} =\frac{\partial C}{\partial a_4}\times\frac{\partial a_4}{\partial b_1}

由于a_4 = \delta(z_4) = \delta(w_4 * a_3 + b_4),因此

\frac{\partial C}{\partial b_1} =\frac{\partial C}{\partial a_4}\times w_4\times\delta'(z_4)\times\frac{\partial a_3}{\partial b_1}

反复利用上述求导方法,可以最终得到:

\frac{\partial C}{\partial b_1} =\frac{\partial C}{\partial a_4}\times w_4\times\delta'(z_4)\times w_3\times\delta'(z_3)\times w_2\times\delta'(z_2)

这个等式也反映了反向传播的工作模式:它从输出层开始,逐层计算偏导数,直到输入层为止。然后,利用这些计算出来的偏导数,更新对应的权重和偏置,从而达到反向传播的目的。

梯度不稳定

梯度丢失和梯度爆炸统称为梯度不稳定。它们产生的原因是类似的。让我们首先看看梯度丢失是如何产生的。

梯度丢失

在实际应用中,最常用到的激活函数是Sigmoid函数,它的图像如下:

Screen Shot 2017-03-11 at 10.52.40 AM.png

Sigmoid函数的输出值在0到1之间,它的导函数最大值出现在x = 0的时候,最大值为0.25。它的导函数图像画如下所示:

Screen Shot 2017-03-11 at 10.51.24 AM.png

由于我们初始化权重值的时候一般从标准正态分布中采样,所以w_j的绝对值通常小于1,因此我们可以得到:

|w_j\times\delta'(z_j)| < 1

在深度网络中,为了计算初始层的梯度,我们会累乘多个w_j\times\delta'(z_j)项 ,最终计算结果将会呈指数级变小,这也就是梯度丢失产生的原因。(个人备注:所以这里说的梯度丢失实际说的是从靠近输出层一侧的隐藏层往输入层方向,计算出来的梯度呈指数级减少)

梯度爆炸

梯度爆炸产生的原因和梯度丢失正好相反。当我们选取的权重值较大时,|w_j\times\delta'(z_j)|将大于1。当累乘这些项的时候,计算结果将呈指数级增长。(个人备注:所以这里说的梯度丢失实际说的是从靠近输出层一侧的隐藏层往输入层方向,计算出来的梯度呈指数级增加)

解决方法

梯度不稳定会使得网络不收敛,最终导致我们的训练无法得到任何有意义的结果。因此,我们必须找到相应的解决方法。

梯度剪裁

梯度剪裁是用来解决梯度爆炸问题的。具体描述如下:

  • 选取一个梯度剪裁的阈值clip_norm(一般选择1)
  • 在计算完每个权重的梯度之后,我们并不像通常那样直接使用这些梯度进行权重更新,而是先求所有权重梯度的平方和global_norm
  • 最后把每个梯度乘以缩放因子clip_norm / max(global_norm, clip_norm)。

这样就保证了在一次迭代更新中,所有权重的梯度的平方和在一个设定范围以内。在实现过程中我们可以使用Tensorflow提供的库函数tf.clip_by_global_norm。关于梯度丢失也有相应的解决方法,这里就不再赘述了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值