梯度消失和爆炸原因以及解决方法

1、梯度消失与梯度爆炸问题简述

        层数比较多的神经网络模型在使用梯度下降法对误差进行反向传播时会出现梯度消失和梯度爆炸问题。梯度消失问题和梯度爆炸问题一般会随着网络层数的增加变得越来越明显。
      例如,对于图所示的含有3个隐藏层的神经网络,梯度消失问题发生时,靠近输出层的hidden layer 3的权值更新相对正常,但是靠近输入层的hidden layer1的权值更新会变得很慢,导致靠近输入层的隐藏层权值几乎不变,扔接近于初始化的权值。这就导致hidden layer 1 相当于只是一个映射层,对所有的输入做了一个函数映射,这时此深度神经网络的学习就等价于只有后几层的隐藏层网络在学习。

     梯度爆炸的情况是:当初始的权值过大,靠近输入层的hidden layer 1的权值变化比靠近输出层的hidden layer 3的权值变化更快,就会引起梯度爆炸的问题。在深层网络或循环神经网络中,误差梯度可在更新中累积,变成非常大的梯度,然后导致网络权重的大幅更新,并因此使网络变得不稳定。在极端情况下,权重的值变得非常大,以至于溢出,导致 NaN 值。网络层之间的梯度(值大于 1.0)重复相乘导致的指数级增长会产生梯度爆炸。

                                         

      那么为什么会出现梯度消失的现象呢?因为通常神经网络所用的激活函数是sigmoid函数,这个函数有个特点,就是能将负无穷到正无穷的数映射到0和1之间,并且对这个函数求导的结果是f′(x)=f(x)(1−f(x))。因此两个0到1之间的数相乘,得到的结果就会变得很小了。神经网络的反向传播是逐层对函数偏导相乘,因此当神经网络层数非常深的时候,最后一层产生的偏差就因为乘了很多的小于1的数而越来越小,最终就会变为0,从而导致层数比较浅的权重没有更新,这就是梯度消失

2、推导梯度消失与梯度爆炸的原因

1.深层网络角度

下面以上图中含有三个隐藏层的单神经元神经网络为例,激活函数使用sigmoid:

图中是一个四层的全连接网络,假设每一层网络激活后的输出为f_{i}(x),其中i 为第i 层, x代表第i层的输入,也就是第i−1层的输出,f是激活函数,那么得出 :,记为

BP算法基于梯度下降策略,以目标的负梯度方向对参数进行调整,参数的更新为w \leftarrow w+\Delta w,如果要更新第二隐藏层的权值信息,根据链式求导法则,更新梯度信息: 
                              

f_{2}=f(f_{1}*w_{2})得,,其中f_{1}是第一层的输出。

                                               \frac{\partial f_4}{\partial f_3} =f^{'}*w_{4}  ,\frac{\partial f_3}{\partial f_2} =f^{'}*w_{3} .

   对激活函数进行求导f^{'},如果此部分大于1,那么层数增多的时候,最终的求出的梯度更新将以指数形式增加,即发生梯度爆炸,如果此部分小于1,那么随着层数增多,求出的梯度更新信息将会以指数形式衰减,即发生了梯度消失.

      从深层网络角度来讲,不同的层学习的速度差异很大,表现为网络中靠近输出的层学习的情况很好,靠近输入的层学习的很慢,有时甚至训练了很久,前几层的权值和刚开始随机初始化的值差不多。因此,梯度消失、爆炸,其根本原因在于反向传播训练法则,属于先天不足。如下图所示,对于四个隐层的网络来说,第四隐藏层比第一隐藏层的更新速度慢了两个数量级:

            

2.激活函数角度

        上文中提到计算权值更新信息的时候需要计算前层偏导信息,因此如果激活函数选择不合适,比如使用sigmoid,梯度消失就会很明显了,左图是sigmoid的损失函数图,右边是其导数的图像,如果使用sigmoid作为损失函数,其梯度是不可能超过0.25的,这样经过链式求导之后,很容易发生梯度消失。

sigmoid函数数学表达式为:
                                       

                  
     可见sigmoid的导数的最大值为1/4,通常初始化的网络权值w通常都小于1,从而有 |\sigma ^{'}(z)w|\leq \frac{1}{4}                                     

     当|\sigma ^{'}(z)w|> 1,也就是w比较大的情况。则前面的网络层比后面的网络层梯度变化更快,引起了梯度爆炸的问题。通常来说当激活函数是sigmoid时,梯度消失比梯度爆炸更容易发生。

    同理,tanh作为激活函数,它的导数图如下,可以看出,tanh比sigmoid要好一些,但是它的导数仍然是小于1的。tanh数学表达为:
                                                        

        

3、梯度消失、爆炸的解决方案

如何确定是否出现梯度爆炸?如:

  1. 模型无法从训练数据中获得更新(如低损失)。
  2. 模型不稳定,导致更新过程中的损失出现显著变化。
  3. 训练过程中,模型损失变成 NaN。

1. 重新设计网络模型

       梯度爆炸可以通过重新设计层数更少的网络来解决。使用更小的批尺寸对网络训练也有好处。另外也许是学习率过大导致的问题,减小学习率。

2. 使用 ReLU 激活函数

      梯度爆炸的发生可能是因为激活函数,如之前很流行的 Sigmoid 和 Tanh 函数。使用 ReLU 激活函数可以减少梯度爆炸。采用 ReLU 激活函数是最适合隐藏层的,是目前使用最多的激活函数。

                                                 

     relu函数的导数在正数部分是恒等于1的,因此在深层网络中使用relu激活函数就不会导致梯度消失和爆炸的问题。

    relu的主要贡献在于:

  1.  -- 解决了梯度消失、爆炸的问题
  2.  -- 计算方便,计算速度快, 加速了网络的训练

同时也存在一些缺点:

  1. 由于负数部分恒为0,会导致一些神经元无法激活(可通过设置小学习率部分解决)
  2. 输出不是以0为中心的

leakrelu
                                  

  leak relu就是为了解决relu的0区间带来的影响,而且包含了relu的所有优点,其数学表达为:

                                               

其中k是leak系数,一般选择0.01或者0.02,或者通过学习而来。

elu

elu激活函数也是为了解决relu的0区间带来的影响,其数学表达为:

                                                        

其函数及其导数数学形式为:

但是elu相对于leakrelu来说,计算要更耗时间一些。

3. 使用长短期记忆网络

     在循环神经网络中,梯度爆炸的发生可能是因为某种网络的训练本身就存在不稳定性,使用长短期记忆(LSTM)单元和相关的门类型神经元结构可以减少梯度爆炸问题。采用 LSTM 单元是适合循环神经网络的序列预测的最新最好实践。

4. 使用梯度截断(Gradient Clipping)

      梯度剪切这个方案主要是针对梯度爆炸提出的,其思想是设置一个梯度剪切阈值,然后更新梯度的时候,如果梯度超过这个阈值,那么就将其强制限制在这个范围之内。这可以防止梯度爆炸。

5. 使用权重正则化(Weight Regularization)

     如果梯度爆炸仍然存在,可以尝试另一种方法,即检查网络权重的大小,并惩罚产生较大权重值的损失函数。该过程被称为权重正则化,通常使用的是 L1 惩罚项(权重绝对值)或 L2 惩罚项(权重平方)。比如在tensorflow中,若搭建网络的时候已经设置了正则化参数,则调用以下代码可以直接计算出正则损失:

regularization_loss = tf.add_n(tf.losses.get_regularization_losses(scope='my_resnet_50'))

正则化是通过对网络权重做正则限制过拟合,仔细看正则项在损失函数的形式:

                                           
其中,α 是指正则项系数,如果发生梯度爆炸,权值的范数就会变的非常大,通过正则化项,可以部分限制梯度爆炸的发生。

注:事实上,在深度神经网络中,往往是梯度消失出现的更多一些。

6、预训练加finetunning

        其基本思想是每次训练一层隐藏层节点,将上一层隐藏层的输出作为输入,而本层隐节点的输出作为下一层隐节点的输入,这就是逐层预训练。在预训练完成后,再对整个网络进行“微调”(fine-tunning)。Hinton在训练深度信念网络(Deep Belief Networks中,使用了这个方法,在各层预训练完成后,再利用BP算法对整个网络进行训练。此思想相当于是先寻找局部最优,然后整合起来寻找全局最优,此方法有一定的好处,但是目前应用的不是很多了。现在基本都是直接拿imagenet的预训练模型直接进行finetunning。

7、批量归一化

      Batchnorm具有加速网络收敛速度,提升训练稳定性的效果,Batchnorm本质上是解决反向传播过程中的梯度问题。batchnorm全名是batch normalization,简称BN,即批规范化,通过规范化操作将输出信号x规范化保证网络的稳定性。

from:Batch Normalization批量归一化

8、残差结构

      残差网络的出现导致了image net比赛的终结,自从残差提出后,几乎所有的深度网络都离不开残差的身影,相比较之前的几层,几十层的深度网络,残差可以很轻松的构建几百层,一千多层的网络而不用担心梯度消失过快的问题,原因就在于残差的捷径(shortcut)部分,残差网络通过加入 shortcut connections,变得更加容易被优化。包含一个 shortcut connection 的几层网络被称为一个残差块(residual block),如下图所示:
                               
     相比较于以前网络的直来直去结构,残差中有很多这样的跨层连接结构,这样的结构在反向传播中具有很大的好处,见下式:
                       

     式子的第一个因子表示的损失函数到达 L的梯度,小括号中的1表明短路机制可以无损地传播梯度,而另外一项残差梯度则需要经过带有weights的层,梯度不是直接传递过来的。残差梯度不会那么巧全为-1,而且就算其比较小,有1的存在也不会导致梯度消失。所以残差学习会更容易。

from:CNN经典模型:深度残差网络(DRN)ResNet


from:https://blog.csdn.net/qq_25737169/article/details/78847691

from :https://www.jianshu.com/p/243ab5aff906

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章