数值稳定性---梯度消失and梯度爆炸

数值稳定性—梯度消失and梯度爆炸

初始化方案的选择在神经网络学习中起着举足轻重的作用,它对保持数值稳定性至关重要。此外, 这些初始化方案的选择可以与非线性激活函数的选择有趣的结合在一起。我们选择哪个函数以及如何初始化参数可以决定优化算法收敛的速度有多快。糟糕选择可能会导致我们在训练时遇到梯度爆炸或梯度消失。


梯度消失和梯度爆炸

梯度爆炸(gradient exploding)问题:参数更新过大,破坏了模型的稳定收敛;

梯度消失(gradient vanishing)问题:参数更新过小,在每次更新时几乎不会移动,导致模型无法学习

梯度消失和梯度爆炸两种情况产生的原因可以总结成2类原因:1.深层网络的结构;2.不合适的损失函数,比如Sigmoid函数。梯度爆炸一般出现在深层网络和权值初始化值太大的情况下

具体原因:

​ 1.神经网络角度

​ 假设有一个四层的全连接网络,假设每层网络激活后的输出为 f i ( x ) f_i(x) fi(x) ,其中i为第i层,x为第i层的输入,也就是第i-1层的输出,f是激活函数,那么, f i + 1 = f ( f i × w i + 1 + b i + 1 ) f_{i+1}=f(f_i\times w_{i+1}+b_{i+1}) fi+1=f(fi×wi+1+bi+1)。我们知道反向传播算法基于梯度下降的思想,以目标负梯度方向对参数进行调整,参数的更新为 w = w − α ∂ L o s s ∂ w w=w-\alpha\frac{\partial Loss}{\partial w} w=wαwLoss ,如果要更新第二隐藏层的权值信息,根据链式求导: Δ w 2 = ∂ L o s s ∂ w = ∂ f 4 ∂ f 3 ∂ f 3 ∂ f 2 ∂ f 2 ∂ w 2 \Delta w_2=\frac{\partial Loss}{\partial w}=\frac{\partial f_4}{\partial f_3}\frac{\partial f_3}{\partial f_2}\frac{\partial f_2}{\partial w_2} Δw2=wLoss=f3f4f2f3w2f2

​ 其实类似 ∂ f 4 ∂ f 3 \frac{\partial f_4}{\partial f_3} f3f4就是对激活函数进行求导。如果在此部分大于1,那么随着层数的增加,求出的梯度的更新将以指数形式增加,发生梯度爆炸。如果此部分小于1,那么随着层数的增加求出的梯度更新的信息会以指数形式衰减,发生梯度消失

​ 2.激活函数角度

​ sigmoid导数最大的时候也只有0.25,其余时候远小于0.25,因此如果每层的激活函数都为Logistic函数的话,很容易导致梯度消失问题,Tanh函数的导数峰值是1那也仅仅在取值为0的时候,其余时候都是小于1,因此通过链式求导之后,Tanh函数也很容易导致梯度消失。

import torch
from d2l import torch as d2l
x = torch.arange(-8.0, 8.0, 0.1, requires_grad=True)
y = torch.sigmoid(x)
y.backward(torch.ones_like(x))

d2l.plot(x.detach().numpy(), [y.detach().numpy(), x.grad.numpy()],
legend=['sigmoid', 'gradient'], figsize=(4.5, 2.5))

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

1.预训练和微调

​ 预训练:无监督逐层训练,每次训练一层隐藏点,训练时将上一层隐节点的输出作为输入,而本层隐节点的输出作为下一层隐节点的输入。称为逐层预训练。在预训练完成后还要对整个网络进行微调。

2.梯度剪切、正则

​ 梯度截断的方式有2种:

  • 按值截断:在第t次迭代时,梯度为 g t g_t gt,给定一个区间[a,b],如果一个参数的梯度小于a时,就将其设为a;如果大于b时,就将其设为b。

g t = m a x ( m i n ( g t , b ) , a ) g_t=max(min(g_t,b),a) gt=max(min(gt,b),a)

  • 按模截断:将梯度的模截断到一个给定的截断阈值b。如果 ∣ ∣ g t ∣ ∣ 2 ≤ b ||g_t||^2≤b ∣∣gt2b ,保持 g t g_t gt 不变。如果 $||g_t||^2>b , , ||g_t||=\frac{b}{||g_t||}g_t$ ,b为超参数,往往一个小的阈值可以达到很好的效果。在训练循环神经网络时,按模截断是避免题都爆炸问题的有效方法。

​ 另一种解决梯度爆炸的手段是采用权重正则化,较常见的是l1正则和l2正则,正则化是通过对网络权重做正则限制过拟合,仔细看正则项在损失函数的形式: L o s s = ( y − W T x ) 2 + λ ∣ ∣ W ∣ ∣ 2 Loss=(y-W^Tx)^2+\lambda||W||^2 Loss=(yWTx)2+λ∣∣W2 λ \lambda λ是正则项系数,如果发生梯度爆炸,权值的范数会变得非常大,通过正则化项,可以部分限制梯度爆炸的发生。

3.relu、leakyrelu、elu等激活函数

​ 从relu的函数特性我们知道,在小于0的时候梯度为0,大于0的时候梯度恒为1,那么此时就不会再存在梯度消失和梯度爆炸的问题了,因为每层的网络得到的梯度更新速度都一样。

​ relu的主要贡献:

  • 解决了梯度消失和梯度爆炸的问题
  • 计算方便计算速度快(梯度恒定为0或1)
  • 加速了网络的训练

缺陷:

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

​ 尽管relu也有缺点,但是仍然是目前使用最多的激活函数

​ leakyrelu就是为了解决relu的0区间带来的影响,在小于0的区间,梯度为很小的数(非零),leakyrelu解决了0区间带来的影响,而且包含了relu所有优点。

​ elu激活函数也是为了解决relu的0区间带来的影响,但是elu相对于leakyrelu来说,计算要耗时一些(有e的幂计算)。

4.Batch Normalization(批规范化)

​ BN就是通过对每一层的输出规范为均值和方差一致的方法,消除了 w w w带来的放大缩小的影响,进而解决梯度消失和爆炸的问题,或者可以理解为BN将输出从饱和区拉到了非饱和区(比如Sigmoid函数)。


深度学习之3——梯度爆炸与梯度消失 - 知乎 (zhihu.com)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜鸡不叫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值