梯度消失和梯度爆炸

0.问题确认

0.0 梯度消失

  • 模型无法从训练数据中获得更新,损失几乎保持不变
  • 打印梯度值,梯度值为0或者非常小,比如 -->grad_value: tensor(3.1044e-10, device='cuda:0')
for name, parms in self.model.named_parameters(): if parms.requires_grad: # print("&&", name, "**", parms) print('-->name:', name, '-->grad_requirs:', parms.requires_grad, '--weight', parms.data, '--weight', torch.mean(parms.data), ' -->grad_value:', torch.mean(parms.grad))

0.1 梯度爆炸

1.梯度消失

梯度消失出现的原因:在深层网络中,如果激活函数的导数小于1,根据链式求导法则,靠近输入层的参数的梯度因为乘了很多的小于1的数而越来越小,最终就会趋近于0,例如sigmoid函数,其导数f′(x)=f(x)(1−f(x))的值域为(0,1/4),极易发生这种情况。所以梯度消失出现的原因经常是因为网络层次过深,以及激活函数选择不当,比如sigmoid函数。

2.梯度爆炸

梯度爆炸出现的原因:
同梯度消失的原因一样,求解损失函数对参数的偏导数时,在梯度的连续乘法中总是遇上很大的绝对值,部分参数的梯度因为乘了很多较大的数而变得非常大,导致模型无法收敛。
所以梯度爆炸出现的原因也是网络层次过深,或者权值初始化值太大。

梯度爆炸的表现:
(1)模型型不稳定,更新过程中的损失出现显著变化。
(2)训练过程中,模型损失变成 NaN。

三、梯度消失爆炸的解决方法:
重新设置网络结构,减少网络层数,调整学习率(消失增大,爆炸减小)。
预训练加微调
此方法来自Hinton在2006年发表的一篇论文,Hinton为了解决梯度的问题,提出采取无监督逐层训练方法,其基本思想是每次训练一层隐节点,训练时将上一层隐节点的输出作为输入,而本层隐节点的输出作为下一层隐节点的输入,此过程就是逐层“预训练”(pre-training);在预训练完成后,再对整个网络进行“微调”(fine-tunning)。Hinton在训练深度信念网络(Deep Belief Networks中,使用了这个方法,在各层预训练完成后,再利用BP算法对整个网络进行训练。此思想相当于是先寻找局部最优,然后整合起来寻找全局最优,此方法有一定的好处,但是目前应用的不是很多了。
激活函数采用relu,leaky relu,elu等。
batch normalization
更换参数初始化方法(对于CNN,一般用xavier或者msra的初始化方法)
调整深度神经网络的结构
使用残差模块,DESNET模块或LSTM等结构(避免梯度消失)
l1、l2正则化(避免梯度爆炸)
减小学习率、减小batch size(避免梯度爆炸)
梯度裁剪(避免梯度爆炸)
对于RNN,加入gradient clipping,每当梯度达到一定的阈值,就把他们设置回一个小一些的数字;


__EOF__

本文作者userName
本文链接https://www.cnblogs.com/pyclq/p/16539679.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   哈哈哈喽喽喽  阅读(210)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示