08 循环神经网络(RNN)梯度消失问题
08 循环神经网络(RNN)梯度消失问题
1. 核心问题:长期依赖(Long-Term Dependencies)
基本的 RNN 模型在处理长序列数据时,难以捕获长期依赖关系。
案例说明:
- 句子 A:”The cat, which already ate …, was full.”(单数
cat对应was) - 句子 B:”The cats, which ate …, were full.”(复数
cats对应were) - 难点:主语(cat/cats)与谓语动词(was/were)之间可能隔着很长的从句。基本 RNN 很难记住序列开头的信息(单复数状态)并传递到序列末尾以决定输出。
- 句子 A:”The cat, which already ate …, was full.”(单数
2. 根本原因:梯度消失(Vanishing Gradients)
RNN 在时间上展开后,相当于一个非常深的神经网络(例如处理 1000 个时间步,相当于 1000 层深的网络)。
反向传播困境:
- 在反向传播过程中,误差梯度需要从序列末尾传回开头。
- 随着层数(时间步)增加,梯度通过连乘链式法则计算。如果连乘的系数小于 1,梯度会呈指数级下降。
数学表达:假设第 $t$ 时刻的隐藏状态为 $h^{(t)}$,损失函数为 $L$。梯度 $\frac{\partial L}{\partial h^{(0)}}$ 涉及连乘项:
\[\frac{\partial L}{\partial h^{(0)}} = \frac{\partial L}{\partial h^{(T)}} \prod_{t=1}^{T} \frac{\partial h^{(t)}}{\partial h^{(t-1)}}\]若 $\left \frac{\partial h^{(t)}}{\partial h^{(t-1)}} \right < 1$,当 $T$ 很大时,该乘积趋近于 0。
后果:
- 序列前部的权重无法得到有效的更新。
- 网络只能学习局部依赖(输出主要受附近输入影响),而无法学习长距离的全局依赖。
3. 伴随问题:梯度爆炸(Exploding Gradients)
虽然梯度消失是主要矛盾,但梯度也可能呈指数级上升。
- 现象:参数值变得极大,导致数值溢出,出现
NaN(Not a Number)。 - 特点:容易被发现(因为程序会报错或参数崩溃)。
解决方案:梯度修剪(Gradient Clipping)
- 原理:设定一个阈值 $\nu$。如果梯度向量 $g$ 的范数 $|g|$ 超过该阈值,则按比例缩放梯度。
公式:
\[g_{new} = \begin{cases} g & \text{if } \|g\| \leq \nu \\ \frac{\nu}{\|g\|} g & \text{if } \|g\| > \nu \end{cases}\]- 这是一种鲁棒且有效的解决方法。
4. 总结与展望
对比:
- 梯度爆炸:容易发现,可通过梯度修剪解决。
- 梯度消失:更难察觉且棘手,导致网络无法学习长期依赖,是基本 RNN 的主要缺陷。
后续方案:
- 为了解决梯度消失问题,课程接下来将介绍 GRU(Gated Recurrent Unit,门控循环单元) 和 LSTM(Long Short-Term Memory) 。
- 这些变体通过引入“门控”机制,有效地控制信息的流动,使得梯度能够更稳定地反向传播,从而捕获长距离依赖。
关键结论:基本 RNN 由于深层网络的反向传播特性,面临严重的梯度消失问题,导致其不擅长处理长序列中的长期依赖;而梯度爆炸虽存在但易于通过裁剪解决。改进模型(如 GRU/LSTM)是解决此问题的关键。
本文由作者按照 CC BY 4.0 进行授权