目录
0.问题确认
0.0 梯度消失
- 异常:RuntimeError: stack expects a non-empty TensorList
- 打印梯度值,梯度值为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函数。
梯度消失的表现:
模型无法从训练数据中获得更新,损失几乎保持不变。
二、梯度爆炸
梯度爆炸出现的原因:
同梯度消失的原因一样,求解损失函数对参数的偏导数时,在梯度的连续乘法中总是遇上很大的绝对值,部分参数的梯度因为乘了很多较大的数而变得非常大,导致模型无法收敛。
所以梯度爆炸出现的原因也是网络层次过深,或者权值初始化值太大。
梯度爆炸的表现:
(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,每当梯度达到一定的阈值,就把他们设置回一个小一些的数字;
原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/278200.html