梯度消失、梯度爆炸及其表现和解决方法
一、梯度消失
梯度消失出现的原因:
在深层网络中,如果激活函数的导数小于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,每当梯度达到一定的阈值,就把他们设置回一个小一些的数字;
扩展:
loss突然变nan的原因?
可能原因:
1、training sample中出现了脏数据,或输入数据未进行归一化
2、学习速率过大,梯度值过大,产生梯度爆炸;
3、在某些涉及指数计算,可能最后算得值为INF(无穷)(比如不做其他处理的softmax中分子分母需要计算exp(x),值过大,最后可能为INF/INF,得到NaN,此时你要确认你使用的softmax中在计算exp(x)做了相关处理(比如减去最大值等等));
4、不当的损失函数(尤其是自定义的损失函数时);
5、在卷积层的卷积步伐大于卷积核大小的时候。
现在的网络普遍采用ReLU激活函数,为什么仍然存在梯度爆炸和消失的问题呢?
梯度消失和 梯度爆炸在relu下都存在, 随着 网络层数变深, activations倾向于越大和越小的方向前进, 往大走梯度爆炸(回想一下你在求梯度时, 每反向传播一层, 都要乘以这一层的activations), 往小走进入死区, 梯度消失。 这两个问题最大的影响是,深层网络难于converge。BN和xavier初始化(经指正, 这里最好应该用msra初始化, 这是he kaiming大神他们对xavier的修正, 其实就是xavier多除以2)很大程度上解决了该问题。sigmoid不存在梯度爆炸, 在activations往越大越小的方向上前进时, 梯度都会消失。
ReLU的负半轴梯度为0,所以有时候(比较少见)也还是会梯度消失,这时可以使用PReLU替代,如果用了PReLU还会梯度弥散和爆炸,请调整初始化参数,对自己调参没信心或者就是懒的,请直接上BN。至于sigmoid为什么会有梯度消失现象,是因为sigmoid(x)在不同尺度的x下的梯度变化太大了,而且一旦x的尺度变大,梯度消失得特别快,网络得不到更新,就再也拉不回来了。
参考网址:
训练深度学习网络时候,出现Nan是什么原因,怎么才能避免?
梯度消失和梯度爆炸原因,表现,解决方案
警惕!损失Loss为Nan或者超级大的原因
知乎:训练神经网络循环3000次后,交叉熵损失为nan原因?
详解机器学习中的梯度消失、爆炸原因及其解决方法
梯度消失,梯度爆炸及表现
知乎:怎么理解梯度弥散和梯度爆炸呢?
更多推荐
所有评论(0)