一、什么是梯度消失和梯度爆炸
1. 梯度消失(gradient vanishing problem)
我们知道神经网络在进行反向传播(BP)的时候会对参数W进行更新,梯度消失就是靠后面网络层(如layer3)能够正常的得到一个合理的偏导数,但是靠近输入层的网络层,计算的到的偏导数近乎零,W几乎无法得到更新。
2. 梯度爆炸(gradient exploding problem)
梯度爆炸的意思是,靠近输入层的网络层,计算的到的偏导数极其大,更新后W变成一个很大的数(爆炸)。
二、梯度消失和梯度爆炸产生的原因
产生梯度消失和梯度爆炸都是因为在神经网络中使用了sigmoid激活函数并且网络很深。为什么呢?
以下图的反向传播为例(假设每一层只有一个神经元且对于每一层,其中为sigmoid函数)
可以推导出
而sigmoid的导数如下图所示:
可见sigmoid的导数的最大值是0.25。然后我们观察上面的推导式,是三个的连乘。
当初始时 < 1 , 这种概率是很大的,因为一般初始化w都是小于1, 这时候,经过很多个小于1的数的连乘,最终得到的偏导数远远小于1,甚至接近于零,就产生了梯度消失的现象。这个时候,前面的hidden layer 1的权值更新会变得很慢,导致前面的层权值几乎不变,仍接近于初始化的权值,这就导致hidden layer 1相当于只是一个映射层,对所有的输入做了一个同一映射,这是此深层网络的学习就等价于只有后几层的浅层网络的学习了。
当初始时 > 1, 就是w的初始化值远远大于4,这时候,经过很多个大于1的数的连乘,最终的到的偏导数远远大于1, 这就产生了梯度爆炸的现象。
无论是梯度消失还是梯度下降,都是使得神经网络的训练过程变得更为曲折,应该尽可能避免它们。
三、如何解决梯度消失和梯度爆炸?
梯度消失和梯度爆炸问题都是因为网络太深,网络权值更新不稳定造成的,本质上是因为梯度反向传播中的连乘效应。解决梯度消失、爆炸主要有以下几种方法:
(1) pre-training+fine-tunning
此方法来自Hinton在2006年发表的一篇论文,Hinton为了解决梯度的问题,提出采取无监督逐层训练方法,其基本思想是每次训练一层隐节点,训练时将上一层隐节点的输出作为输入,而本层隐节点的输出作为下一层隐节点的输入,此过程就是逐层“预训练”(pre-training);在预训练完成后,再对整个网络进行“微调”(fine-tunning)。此思想相当于是先寻找局部最优,然后整合起来寻找全局最优,此方法有一定的好处,但是目前应用的不是很多了。
(2) 梯度剪切:对梯度设定阈值
梯度剪切这个方案主要是针对梯度爆炸提出的,其思想是设置一个梯度剪切阈值,然后更新梯度的时候,如果梯度超过这个阈值,那么就将其强制限制在这个范围之内。这可以防止梯度爆炸。
(3) 权重正则化
另外一种解决梯度爆炸的手段是采用权重正则化(weithts regularization),正则化主要是通过对网络权重做正则来限制过拟合。如果发生梯度爆炸,那么权值就会变的非常大,反过来,通过正则化项来限制权重的大小,也可以在一定程度上防止梯度爆炸的发生。比较常见的是 L1 正则和 L2 正则,在各个深度框架中都有相应的API可以使用正则化。
(4)选择更好的随机初始化权重的方法
一是对每个权重都进行随机初始化,尽量让每个权重都不同,使不同神经元之间区别性更好。二是选择合适的随机初始化权重,不能太小,也不能太大。一般而言,参数初始化的区间应该根据神经元的性质进行差异化的设置,如果一个神经元的输入链接很多,那么每个输入连接上的权重要小一些,以避免神经元的输出过大(当激活函数为ReLU函数,但输出为正时,导数都为1)或者过饱和(当激活函数为Sigmoid函数时,梯度会接近于0)。