1.引言
在之前的文章中我们提到过反向传播:https://blog.dotcpp.com/a/89149 ,在反向传播中,参数是根据求该参数和损失函数的梯度来更新的,也就是沿着梯度下降的方向来更新模型参数。
2.概念理解
那什么叫梯度消失呢?
梯度消失其实就是梯度已经差不多趋近于0了,参数已经更新不动了,从而导致收敛速度慢,训练时间无限延长。
3.原因
下面我们通过公式推导寻找梯度消失的原因
假设我们的模型参数是
w
w
w,而更新
w
w
w的方法是:
w = w − ε ∂ L ∂ w w=w-\varepsilon\frac{\partial L}{\partial w} w=w−ε∂w∂L
ε \varepsilon ε为学习率, L L L为损失函数。
假设我们的网络具有8层,设每一层的输入输出参数分别为:
I
1
,
O
1
,
W
1
,
.
.
.
,
I
8
,
O
8
,
W
8
I_1,O_1,W_1,...,I_8,O_8,W_8
I1,O1,W1,...,I8,O8,W8
接下来,具体求解过程:
我们把数据分为两部分:
w = w 1 w 2 ∗ . . . . . . . . ∗ w 8 w = w1 w2 * ........ * w8 w=w1w2∗........∗w8
O = O 8 ∗ ( 1 − O 8 ) ∗ . . . . . . . . . ∗ O 1 ∗ ( 1 − O 1 ) O = O_8 * (1-O_8) * ......... * O_1 * (1-O_1) O=O8∗(1−O8)∗.........∗O1∗(1−O1)
也就是最终的梯度值为 w o w o wo ,梯度消失也就意味着 w ∗ o w * o w∗o 是一个很小很小的数.
可以o必然是一个很小的数,为什么.
O 8 O 7 O 6 O 5 O 4 O 3 O 2 O 1 O_8 O_7 O_6 O_5 O_4 O_3 O_2 O_1 O8O7O6O5O4O3O2O1是sigmode的输出,我们以 O 8 ∗ ( 1 − O 8 ) O_8 * (1 - O_8) O8∗(1−O8)为列,进行分析:
O 8 O_8 O8的输出范围在[0,1]之间,如果 I 8 > 0 I_8>0 I8>0的, O 8 O_8 O8接近1,但是 1 − O 8 1-O_8 1−O8肯定很小了, O 8 O_8 O8和 1 − O 8 1-O_8 1−O8就是对立的.
O 8 ∗ ( 1 − O 8 ) O_8 * (1-O_8) O8∗(1−O8) 很小,更何况这个很小的数还要和 O 7 ∗ ( 1 − O 7 ) , O 6 ∗ ( 1 − O 6 ) . . . O 1 ∗ ( 1 − O 1 ) O_7 * (1-O_7) ,O_6 * (1-O_6) ...O_1 * (1-O_1) O7∗(1−O7),O6∗(1−O6)...O1∗(1−O1) 这些小数相乘.
所以也许靠近输出层的那几层梯度下降也许比较ok,但是靠近输入层的梯度下降肯定没这么快.
解决的方案就是用 R e l u Relu Relu来替代 s i g m o d sigmod sigmod,为何因为这样 O 7 O 8 O 1 . . . O_7 O_8 O_1 ... O7O8O1...就会变为常数了( R e l u Relu Relu输出对输入求导后为常数)。肯定会有比较好的梯度下沉 。