【深度学习】梯度消失和爆炸

首先,梯度消失分为两种情况:

1、在 CNN 中;

对于前者,即使发生梯度消失(例如使用了 sigmoid 激活函数),并不是说整个网络的梯度都消失了,而是网络靠近输出层的部分梯度较大,越往前梯度越小。也就是说,梯度消失只发生在网络前几层。如此说来,只需对网络每层的梯度按照不同的比例进行缩放(例如每往前一层,梯度乘一个大于一的因子 gamma),就能保证每层的梯度的数量级基本相同。而事实上,在进行参数更新时,更大的梯度等价于更大的学习率(即 learning_rate * (gamma *g) = (gamma*learning_rate) * g,其中 g 是参数的梯度,gamma > 1 为 scaling 的超参数),所以只需每层采用不同的学习率即可,例如 Layerwise Adaptive Rate Scaling 算法([1708.03888] Large Batch Training of Convolutional Networks)就是这么做的。

但是从另一个角度想,其实我们现在已经有了很多自适应学习率的优化算法,又何必劳烦去逐层设置学习率呢?Adam 之类的优化算法在大多数时候已经可以使我们不关心梯度的范数了。

2、在 RNN 中。

对于后者,梯度消失实际上是一个伪问题。因为在 RNN 中,相同的权重参数 W 会在各个时间步复用,最终 W 的梯度 g = g1 + g2 + ... + gT,即各个时间步的梯度之和。即使网络中存在梯度消失,那也是逐层发生的,也就是说 g1/g2 这样的靠前的层梯度较小,而 gT 等靠后的层梯度较大,因此他们的总和 g 仍然是不会消失的,只是被靠后的 gT 主导了而已。因此,总的梯度不会消失,不必处理——当然这么做可能带来的后果是,网络只能学到近距离的依赖,难以学到远距离的依赖。可是难道 gradient clipping 就没有这个问题吗?假设梯度爆炸了,总的梯度是被较远距离的 g1 主导的,而较近的 gT 却被忽略了(因为 g1 >> gT),即使做了 clipping,不至于让模型参数一朝回到解放前,但是这一步的更新却是被远距离依赖主导的,近距离的依赖被忽视了,做法同样很糙。更加精致的做法应该是,每一步的梯度 gt 都缩放一下,砍到差不多的数量级,最后再加起来得到总梯度,用来更新网络参数。不过,一个合理的反驳是,梯度消失发生的频率远大于梯度爆炸发生的频率,因此即使用同样粗糙的手法来处理,梯度爆炸的 clipping 造成的负面影响要小得多。这是我勉强接受的一个反驳。

那么现在使用最广泛的梯度消失的解决方案是什么呢?现代门控 RNN 单元,以 LSTM 和 GRU 为代表。可是如果仔细推导的话,就会发现这些 RNN 单元并不能完全解决梯度消失问题——LSTM只是做到了在一条关键路径上进行加性更新(因此梯度比较稳定),但是其他路径上求导仍然会出现矩阵连乘(进而导致梯度消失或爆炸)。因此即便使用LSTM​​​​​​​,仍然需要搭配 gradient clipping 来使用,因为它仍然有可能发生梯度爆炸(LSTM/GRU 可以解决梯度爆炸问题是一个常见的误解)。LSTM/GRU 的梯度消失问题和普通 RNN 的梯度消失问题相比,区别是这样的:LSTM/GRU可以在一条关键路径上保持梯度流,其他路径依然可能发生梯度消失;普通 RNN在最后几个时间步上保持梯度流,较早的时间步则会发生梯度消失。所以现代门控单元对梯度消失的解决并不彻底,只是改善了很多而已。

那么 gradient scaling 在 RNN 的场景下是否能奏效呢?Reddit 上有一个讨论(r/MachineLearning - Solving The Vanishing Gradient and Exploding Gradient Problem With One Line Of Code?),其中题主说到『Long story short, I figured out a very simple alternative that seems to work astonishingly well, at least with RMSProp. Also, the way I am scaling the gradients by the inverse of the norm of the gradients, seems like it would solve not only the exploding gradients, but also the vanishing gradients?』显然,gradient scaling 的方案是有人试过的,并且至少在 toy example 上是有效果的。但是即便你告诉我这个结论,我也不打算在自己写代码的时候用到这个方案:因为 LSTM/GRU 发生梯度消失的情况已经很少了啊,我何必多此一举放大一下梯度呢,还要调放大倍数这样(可能并不稳定)的超参?

参考:

梯度消失问题为什么不通过 gradient scaling 来解决? - Towser的回答 

猜你喜欢

转载自blog.csdn.net/weixin_31866177/article/details/88930462