前言
数值稳定性,这个说起来简单但真正碰到确实一个非常难的问题,而且它十分的重要。 当神经网络在训练的过程中,碰到NAN 和inf 的时候,是最为恼火的,这严重地影响了训练。 有的时候,模型不断训练但没有结果也可能是数值稳定性问题。
次幂的恐怖
回想一些梯度求导的式子,采用的是链式求导法则,也就是说最终的结果是多个导数的乘积。 来计算两个式子:
1.
2
50
=
9
,
100.4381500021497733275852753426
0.
8
50
=
1.4272476927059598810582859694495
e
?
5
1.2^{50}=9,100.4381500021497733275852753426 \newline 0.8^{50}=1.4272476927059598810582859694495e-5
1.250=9,100.43815000214977332758527534260.850=1.4272476927059598810582859694495e?5 我们不妨假设,一个神经网络有50层,每层的导数为1.2,那么当这个梯度传导到输入层的时候,其已经是一个巨大无比的数了,这样的训练显然达不到我们想要的效果。 同样如果每层的导数是0.8,那么输入层的梯度就是一个非常小的数了,因此时就无法训练了。 第一种情况叫做:梯度爆炸,求出的梯度非常大, 第二种情况叫做:梯度消失,求出的梯度非常小。
解决方法
并没有特别好的方法,但是有一些办法可以缓解此类现象。
合理的初始化
一般来说,最开始的时候梯度是非常大的,但在接近极值点的时候,梯度会相对较小一些。 而最开始的时候,权重都是随机的,如果随机的权重都是几千,那么用不到几层的反向传播梯度就会爆炸;同样,随机出来的梯度都特别小也是不行的,因为会出现梯度消失的情况。
选择合适的激活函数
如果激活函数的导数都特别大,也非常容易造成梯度爆炸的情况。 不过一般常用的激活函数都不会出现这个问题。例如ReUL,其导数也就是1(x>0)。
|