loss突然变nan的原因?
可能原因:
1、training sample中出现了脏数据,或输入数据未进行归一化
2、学习速率过大,梯度值过大,产生梯度爆炸;
3、在某些涉及指数计算,可能最后算得值为INF(无穷)(比如不做其他处理的softmax中分子分母需要计算exp(x),值过大,最后可能为INF/INF,得到NaN,此时你要确认你使用的softmax中在计算exp(x)做了相关处理(比如减去最大值等等));
4、不当的损失函数(尤其是自定义的损失函数时);
原文链接:梯度消失、梯度爆炸及其表现和解决方法_梯度消失的表现-CSDN博客
梯度消失?
梯度消失出现的原因:
在深层网络中,如果激活函数的导数小于1,根据链式求导法则,靠近输入层的参数的梯度因为乘了很多的小于1的数而越来越小,最终就会趋近于0,例如sigmoid函数,其导数f′(x)=f(x)(1−f(x))的值域为(0,1/4),极易发生这种情况。
所以梯度消失出现的原因经常是因为网络层次过深,以及激活函数选择不当,比如sigmoid函数。
sigmoid为什么会有梯度消失现象?是因为sigmoid(x)在不同尺度的x下的梯度变化太大了,而且一旦x的尺度变大,梯度消失得特别快,网络得不到更新,就再也拉不回来了。
梯度爆炸
梯度爆炸:误差的梯度可在更新中累积相乘。如果网络层之间的梯度值大于 1.0,那么重复相乘会导致梯度呈指数级增长
- 针对梯度爆炸提出的,其思想是设置一个梯度剪切阈值
- 另外一种解决梯度爆炸的手段是采用权重正则化(weithts regularization),正则化主要是通过对网络权重做正则来限制过拟合。
原文链接:梯度消失、梯度爆炸及其表现和解决方法_梯度消失的表现-CSDN博客
-
解决方案:
- 梯度消失和 梯度爆炸在relu下都存在, 随着 网络层数变深, activations倾向于越大和越小的方向前进, 往大走梯度爆炸(回想一下你在求梯度时, 每反向传播一层, 都要乘以这一层的activations), 往小走进入死区, 梯度消失。
- 这两个问题最大的影响是,深层网络难于converge。
- BN和xavier初始化(经指正, 这里最好应该用msra初始化, 这是he kaiming大神他们对xavier的修正, 其实就是xavier多除以2)很大程度上解决了该问题。
- sigmoid不存在梯度爆炸, 在activations往越大越小的方向上前进时, 梯度都会消失。
- ReLU的负半轴梯度为0,所以有时候(比较少见)也还是会梯度消失,这时可以使用PReLU替代。
- 如果用了PReLU还会梯度弥散和爆炸,请调整初始化参数,对自己调参没信心或者就是懒的,请直接上BN。
- 可以理解为BN将输出从饱和区拉倒了非饱和区。
- 激活函数
例如使用relu、leakrelu、elu之类的激活函数,如果激活函数的导数为1,那么就不存在梯度消失爆炸的问题了,每层的网络都可以得到相同的更新速度
- relu解决了梯度消失、爆炸的问题
- 计算方便,计算速度快
- 加速了网络训练
————————————————