不稳定的梯度

2021年1月7日 / 4次阅读 / Last Modified 2021年1月7日
神经网络

深度神经网络DNN在训练的时候,会存在两个潜在的与不稳定的梯度有关的问题:(1)梯度消失(vanishing gradient);(2)梯度爆炸(exploding gradient)。

梯度消失,会导致DNN中,前面的层(从左到右)学习缓慢,甚至停止学习。梯度爆炸,会让学习完全无效,会让网络中对应的weights和bias更新到一个荒谬的值,可能还不如不要更新。

我们先从数学上来研究一下为什么会出现这样的情况:

上图是一个简化后的示例。

假设这个神经网络,从输入到输出,每一层都只有一个神经元,那么对于b1的偏导数公式,就是如图中所示。经过层层后向传导计算,在传导过程中,要不断地乘以连接权重w,不断地乘以神经元激活函数针对z(weighted input,wa+b)的导数。

上式是极度简化后的,只是为了说明问题。正常的网络,计算b1的偏导数,是整个后向传播所有连接计算的求和。(为什么是求和?因为最后计算cost,就是计算vector的长度平方)

梯度消失

貌似现在这个问题在MLP网络中更容易出现。

初始化神经网络的weights和bias时,一般都是np.random.randn,即N(0,1),就是所有的w和b在一起,符合mean=0,var=1的normal distribution。大部分的w和b在-1到1之间。

如果激活函数使用经典的sigmoid,这个函数有个特点,它的导数最大值才0.25:

这样,一层层往后计算的过程中,得到的值就越来越小,这就是梯度消失的原因!

使用其它激活函数可以改善梯度消失的问题,但不能更本解决,如何w和b依然悬而未决。

梯度爆炸

梯度不能太大,正如Learning Rate也不能太大一样,可能出现overshooting或者梯度爆炸。

我们还是要回到上文的那个数学公式上来分析。很明显,如果w和b的初始值就很大,就直接梯度爆炸了。

以上分析可以看出,不管是更换激活函数,或者在N(0,1)范围内初始化w和b,都不能根本上解决问题。下面只是记录一下现在业界的方案,还未深入研究:

  • 预训练加微调。此方法来自Hinton在2006年发表的一篇论文,Hinton为了解决梯度的问题,提出采取无监督逐层训练方法,其基本思想是每次训练一层隐节点,训练时将上一层隐节点的输出作为输入,而本层隐节点的输出作为下一层隐节点的输入,此过程就是逐层“预训练”(pre-training);在预训练完成后,再对整个网络进行“微调”(fine-tunning)。Hinton在训练深度信念网络(Deep Belief Networks中,使用了这个方法,在各层预训练完成后,再利用BP算法对整个网络进行训练。此思想相当于是先寻找局部最优,然后整合起来寻找全局最优,此方法有一定的好处,但是目前应用的不是很多了。
  • 梯度剪切,正则。梯度剪切这个方案主要是针对梯度爆炸提出的,其思想是设置一个梯度剪切阈值,然后更新梯度的时候,如果梯度超过这个阈值,那么就将其强制限制在这个范围之内。这可以防止梯度爆炸。另外一种解决梯度爆炸的手段是采用权重正则化(weithts regularization)比较常见的是 l 1 l1 l1正则,和 l 2 l2 l2正则,在各个深度框架中都有相应的API可以使用正则化。
  • ReLU系列激活函数。
  • BatchNorm。
  • 残差结构。
  • LSTM。

-- EOF --

本文链接:https://www.pynote.net/archives/3094

留言区

电子邮件地址不会被公开。 必填项已用*标注


前一篇:
后一篇:

More


©Copyright 麦新杰 Since 2019 Python笔记

go to top