深度学习训练中梯度消失的原因有哪些?有哪些解决方法?
1.为什么要使用梯度反向传播?
归根结底,深度学习训练中梯度消失的根源在于梯度更新规则的使用。目前更新深度神经网络参数都是基于反向传播的思想,即基于计算损失函数或者代价函数的误差通过梯度反向传播的方式,对模型中的参数进行更新优化。那么,模型中的参数更新为什么要使用反向传播的思想呢? 这样做是有原因的,首先,神经网络是由许多非线性层堆叠而来,而每一层非线性层都可是为一个非线性函数
f
(
x
)
f(x)
f(x)(其非线性来自于激活函数的非线性),因此整个神经网络可以视作是一个复合的非线性多元函数:
$$\F(x)=fn(…f3(f2(f1(x)*a+ b1) + b2) …)$$
优化神经网络模型的目的就是为了很好的完成输入到输出之间的映射,假如输入为x时,目标输出为
g
(
x
)
g(x)
g(x),我们要求
F
(
x
)
F(x)
F(x)和
g
(
x
)
g(x)
g(x)之间的差值最小,假设我们构建的损失函数为:
L
o
s
s
=
∣
∣
F
(
x
)
−
g
(
x
)
∣
∣
2
Loss = ||F(x) - g(x)||^2
Loss=∣∣F(x)−g(x)∣∣2
假设损失函数的数据空间是下图这样的,我们最优的权值就是为了寻找下图中的最小值点,对于这种数学寻找最小值问题,采用梯度下降的方法再适合不过了。
2.梯度消失,梯度爆炸的原因分析
首先,要明白梯度消失和梯度爆炸的原理都是一样的,只是导致这种现象产生的初始状态不一样。梯度消失出现的原因主要有两种,一是在深层神经网络中,二是使用了Sigmoid激活函数。而梯度爆炸产生的原因主要是因为初始话的权重过大导致的。
2.1从深层网络的角度
从一个比较简单的深层神经网络出发,如下图:
图中是一个四层的全连接网络,假设每一层网络激活后的输出为fi(x),
x
x
x表示第
i
i
i层的输入,也就是第
i
−
1
i-1
i−1层的输出,
f
f
f是激活函数,那么可以得出fi+1(x) = f(fi*wi+1+bi+1),BP算法基于梯度下降策略,以目标的负梯度方向对参数进行调整,参数的更新为w←w+Δw 给定学习率 alpha ,得出:
如果要更新第二隐藏层的权值信息,根据链式求导法则,更新梯度信息:
,很容易看出来
,即第二隐藏层的输入。所以说,
就是对激活函数进行求导,如果此部分大于1,那么层数增多的时候,最终的求出的梯度更新将以指数形式增加,即发生梯度爆炸,如果此部分小于1,那么随着层数增多,求出的梯度更新信息将会以指数形式衰减,即发生了梯度消失。如果说从数学上看不够直观的话,下面几个图可以很直观的说明深层网络的梯度问题
2.2激活函数的角度
在之前的讨论中发现,对权重的更新包含对激活函数的求导信息,所以如果选择的激活函数不合适,比如Sigmoid函数,那么梯度消失现象就会变得很明显。具体原因可见下图中Sigmoid函数及其导函数的图像,可以发现Sigmoid的导函数值不会大于0.25,因此,随着神经网络中误差的不断反传,会不断的将导数值乘以增量,这就使得最终的增量越变越小,从而导致梯度消失。
3.梯度消失,梯度爆炸的解决方案
3.1预训练+微调
此方法来自Hinton在2006年发表的一篇论文,Hinton为了解决梯度的问题,提出采取无监督逐层训练方法,其基本思想是每次训练一层隐节点,训练时将上一层隐节点的输出作为输入,而本层隐节点的输出作为下一层隐节点的输入,此过程就是逐层“预训练”(pre-training);在预训练完成后,再对整个网络进行“微调”(fine-tunning)。Hinton在训练深度信念网络(Deep Belief Networks中,使用了这个方法,在各层预训练完成后,再利用BP算法对整个网络进行训练。此思想相当于是先寻找局部最优,然后整合起来寻找全局最优,此方法有一定的好处,但是目前应用的不是很多了
3.2 使用ReLU、Leakrelu、elu等激活函数
ReLU解决梯度消失问题的关键就在于,该函数的导数值固定为1,这就使得各个层中的权重以相同的速度进行更新。其公式为:
R
e
L
U
(
x
)
=
m
a
x
(
0
,
x
)
ReLU(x) = max(0, x)
ReLU(x)=max(0,x)
其函数图像及导函数图像如下图所示:
从上图中,我们可以很容易看出,relu函数的导数在正数部分是恒等于1的,因此在深层网络中使用relu激活函数就不会导致梯度消失和爆炸的问题。
relu的主要贡献在于:
- 解决了梯度消失、爆炸的问题
- 计算方便,计算速度快
- 加速了网络的训练
同时也存在一些缺点:
- 由于负数部分恒为0,会导致一些神经元无法激活(可通过设置小学习率部分解决)
- 输出不是以0为中心的
尽管relu也有缺点,但是仍然是目前使用最多的激活函数
leakrelu就是为了解决relu的0区间带来的影响,其数学表达为:leakrelu=max(k∗x,x)其中k是leak系数,一般选择0.01或者0.02,或者通过学习而来
leakrelu解决了0区间带来的影响,而且包含了relu的所有优点。
elu激活函数也是为了解决relu的0区间带来的影响,其数学表达为:
但是该函数更加复杂,计算更加耗时。
3.3batchnorm
batchnorm全名是batch normalization,简称BN,即批规范化,通过规范化操作将输出信号x规范化保证网络的稳定性。batchnorm就是通过对每一层的输出规范为均值和方差一致的方法,消除了xxx带来的放大缩小的影响,进而解决梯度消失和爆炸的问题,或者可以理解为BN将输出从饱和区拉倒了非饱和区。
3.4残差结构
3.5 LSTM
3.6 梯度剪切、正则
梯度剪切这个方案主要是针对梯度爆炸提出的,其思想是设置一个梯度剪切阈值,然后更新梯度的时候,如果梯度超过这个阈值,那么就将其强制限制在这个范围之内。这可以防止梯度爆炸。
另外一种解决梯度爆炸的手段是采用权重正则化(weithts regularization)比较常见的是l1正则,和l2正则,
正则化是通过对网络权重做正则限制过拟合,仔细看正则项在损失函数的形式:
其中,α\alphaα是指正则项系数,因此,如果发生梯度爆炸,权值的范数就会变的非常大,通过正则化项,可以部分限制梯度爆炸的发生。
参考资料
https://blog.csdn.net/qq_25737169/article/details/78847691