RNN 循环神经网络
循环神经网络(Recurrent Neural Network, RNN)是深度学习三大架构族中处理序列数据的主力(与 CNN 并列,见 深度学习概览)。本页系统讲解 RNN 的核心原理、梯度消失问题、LSTM/GRU 门控变体、双向 RNN、seq2seq 架构,以及注意力机制的诞生——这条技术线最终催生了 Transformer 架构。注意力机制的深入讲解另见 注意力机制。
处理序列数据(文本、语音、时间序列)的核心难题:当前时刻的输出依赖于之前的上下文。RNN 的解题思路:
- RNN = 接力赛跑:每个时间步接收一个输入,同时拿到上一棒传来的”接力棒”(隐藏状态),处理后把新接力棒传给下一棒。信息逐级传递,但接力棒容量有限——句子一长,开头的细节就”遗忘”了。
- LSTM = 带开关的接力棒:在普通接力棒基础上装了三个阀门——遗忘门(该忘什么)、输入门(该记什么新东西)、输出门(该输出什么)。阀门学会了自动开关,重要信息可以一路保留到终点。
- GRU = 精简版 LSTM:把三个阀门合并成两个(重置门 + 更新门),参数更少、速度更快,效果通常接近 LSTM。
Vanilla RNN 时序展开
Section titled “Vanilla RNN 时序展开”RNN 在每个时间步处理一个输入,用隐藏状态 h 传递上下文。展开后是一条逐级传递的链:
每个时间步的核心计算公式:
x_t:当前时刻输入(如第 t 个词的向量)h_{t-1}:上一时刻的隐藏状态(“记忆”)W_xh、W_hh:权重矩阵(W_hh是”记忆传递”的权重)tanh:激活函数(hyperbolic tangent,双曲正切),将值压到 [-1, 1]W_hy、b_y:将隐藏状态映射到输出的权重和偏置
隐藏状态
h就是”到目前为止的浓缩记忆”。每一步的输出y_t可以是分类结果(如情感分析),也可以是传给下一步的中间表示。
权重共享:RNN 的核心特性
Section titled “权重共享:RNN 的核心特性”注意 RNN 在所有时间步中使用同一组权重 W_xh、W_hh、W_hy——不论序列有多长,模型参数量不变。这是 RNN 与”把整个序列一次性喂入全连接网络”的关键区别:权重共享让模型可以处理任意长度的序列,也让每个时间步学到的模式可以泛化到序列中的任何位置。
梯度消失与梯度爆炸
Section titled “梯度消失与梯度爆炸”普通 RNN 训练时使用沿时间反向传播(BPTT, Backpropagation Through Time)——将 RNN 沿时间轴展开成一个多层网络,再用标准反向传播。梯度需要沿着时间链逐级回传,每经过一个时间步就乘以一次 W_hh(再经过 tanh 的导数)。当序列很长时:
每个 ∂h_k/∂h_{k-1} 是一个雅可比矩阵(Jacobian matrix,即向量对向量的偏导数矩阵),包含 W_hh 和 tanh 的导数。
- 如果这些雅可比矩阵的乘积的特征值 < 1 → 连乘后梯度指数衰减至 0 → 梯度消失:模型学不到开头的信息。
- 如果特征值 > 1 → 连乘后梯度指数增长 → 梯度爆炸:参数更新炸掉(可用梯度裁剪 gradient clipping 缓解)。
为什么 tanh 让梯度消失更严重
Section titled “为什么 tanh 让梯度消失更严重”tanh 的导数最大值为 1(仅在输入为 0 时),大部分区域导数远小于 1(如输入绝对值 > 2 时导数接近 0)。因此每经过一个时间步,梯度大致乘以一个小于 1 的数,序列一长(如 50 步以上),梯度就衰减到 0.9^50 ≈ 0.005 量级——几乎为零。
梯度消失是致命的:它意味着 RNN 在数学上就”记不住”远距离依赖。一句话的第 1 个词和第 50 个词之间的关系,普通 RNN 基本无法建模。这正是 LSTM 诞生的动机。
LSTM 门控机制
Section titled “LSTM 门控机制”LSTM(Long Short-Term Memory,Hochreiter & Schmidhuber, 1997)在隐藏状态之外增加了一条细胞状态 C(cell state),并用三个门来控制信息流动:
三个门的数学公式(σ 为 sigmoid 函数,将任意实数压到 (0,1),可看作”开/关”的概率):
- 遗忘门 :决定从旧细胞状态中丢弃什么
- 输入门 :决定写入哪些新信息
- 候选值 :候选的新信息(范围 )
- 输出门 :决定输出什么
- 细胞状态更新 :遗忘门过滤旧状态 + 输入门写入新信息
- 隐藏状态 :输出门控制细胞状态的输出
⊙ 表示逐元素乘法(Hadamard 积,即对应位置相乘)。
[h_{t-1}, x_t]表示向量拼接。
为什么 LSTM 能解决梯度消失
Section titled “为什么 LSTM 能解决梯度消失”细胞状态 C 是一条贯穿整条序列的”高速公路”。注意 C_t = f_t ⊙ C_{t-1} + i_t ⊙ C̃_t 中,C_t 对 C_{t-1} 的梯度是 f_t(遗忘门的输出),这是一个加法运算而非乘法运算——如果遗忘门接近 1(“记住全部”),梯度可以几乎无损地一路传到序列开头。对比普通 RNN 中梯度要反复乘以 W_hh(导致指数衰减),LSTM 的细胞状态提供了一条梯度可以畅通无阻的直达通路。
门控的直觉解释
Section titled “门控的直觉解释”- 遗忘门:想象你在读一篇小说,每读到新的一章,“上一章的场景描写”可能不再重要——遗忘门学会在合适的时机”忘记”过时的信息。
- 输入门:读到关键情节时(如”凶手是管家”),输入门打开,将这条信息写入细胞状态。
- 输出门:当前需要输出(如回答”凶手是谁?“)时,输出门从细胞状态中提取相关信息。
这三个门都是可学习的——网络通过反向传播自动学会何时开关。
GRU 简化门控
Section titled “GRU 简化门控”GRU(Gated Recurrent Unit,Cho et al., 2014)将 LSTM 的三门合并为两门,去掉了独立的细胞状态:
- 更新门 z_t 同时承担了 LSTM 遗忘门和输入门的功能:
1 - z_t控制”保留多少旧记忆”,z_t控制”写入多少新信息”。注意这两个系数加和恒为 1(互补关系),比 LSTM 更紧凑。 - 重置门 r_t 控制”计算候选值时用多少旧记忆”——重置门接近 0 时,候选值几乎不依赖旧状态,相当于”重置记忆”。
| 对比 | LSTM | GRU |
|---|---|---|
| 门数量 | 3(遗忘/输入/输出) | 2(重置/更新) |
| 细胞状态 | 独立的 C,与 h 分离 | 无独立 C,直接复用 h |
| 参数量 | 较多(4 组权重) | 较少(3 组权重,少约 25%) |
| 效果 | 长序列略优 | 短-中序列相当,速度更快 |
| 适用场景 | 需要强记忆的复杂任务 | 追求效率、数据量适中的任务 |
多层 RNN(Stacked RNN)
Section titled “多层 RNN(Stacked RNN)”RNN 可以像 CNN 一样堆叠多层——第一层 RNN 的隐藏状态序列作为第二层的输入,依此类推。低层学习局部/短时模式(如词级别语法),高层学习全局/长时模式(如句子级语义)。
输入序列 → [LSTM Layer 1] → h1_1, h1_2, ..., h1_T ↓ [LSTM Layer 2] → h2_1, h2_2, ..., h2_T ↓ [LSTM Layer 3] → 最终隐藏状态实践中 2-4 层最常见。层数过多会导致训练不稳定且速度极慢。PyTorch 中只需设置 num_layers 参数:nn.LSTM(embed_dim, hidden_dim, num_layers=2)。层与层之间可加 Dropout 做正则化。
双向 RNN(BiLSTM / BiGRU)
Section titled “双向 RNN(BiLSTM / BiGRU)”普通 RNN 只能”从左到右”看序列,但很多任务中,后面的信息对理解前面也很重要。比如”这只猫 ___ 追了一下午”——空格处需要后面的”追”才能判断。
双向 RNN 同时运行两个方向:
每个位置的最终输出是正向隐藏状态和反向隐藏状态的拼接 [h_forward ; h_backward]。双向 RNN 不能用于实时生成任务(因为需要看到”未来”),但非常适合分类、标注等有完整输入的场景。
seq2seq 编码器-解码器
Section titled “seq2seq 编码器-解码器”seq2seq(Sutskever et al., 2014)是机器翻译的里程碑架构——也是 Transformer 的直接前身。核心思想:用一个 RNN(编码器)把整条源序列压缩成一个固定长度的上下文向量 c,再用另一个 RNN(解码器)从 c 逐步生成目标序列:
瓶颈问题:无论源序列多长,都要压成一个固定大小的向量 c。长句子时信息严重丢失——这正是注意力机制的出发点。
Teacher Forcing(教师强制)
Section titled “Teacher Forcing(教师强制)”训练解码器时,每一步的输入用真实的前一个词(而非模型自己预测的词),这种策略叫 Teacher Forcing:
训练时(Teacher Forcing): 输入: <START> → 预测 "I" 输入: "I" → 预测 "love" ← 用真实词 "I",而非模型预测的结果 输入: "love" → 预测 "you"Teacher Forcing 让训练更稳定、收敛更快——因为早期模型预测的词几乎全错,如果用错误预测作为下一步输入,错误会滚雪球式累积。缺点是”训练-推理偏差”(exposure bias):推理时没有真实标签可用,模型可能没学会应对自己的错误。缓解方法是 Scheduled Sampling(计划采样):训练初期 100% 用 Teacher Forcing,随着训练推进逐渐以一定概率改用模型自己的预测。
Bahdanau 注意力的诞生
Section titled “Bahdanau 注意力的诞生”Bahdanau et al.(2014)提出:解码器在生成每个词时,不应该只看一个固定向量 c,而应该”回看”编码器的所有隐藏状态,动态选择与自己最相关的部分。这就是注意力机制的雏形:
对解码器的第 步:
- :对每个编码器隐状态打分
- :归一化为注意力权重(加和为 1)
- :加权求和得到动态上下文
每一步的上下文 c_t 不再固定不变,而是根据当前正在生成的词动态计算。这一思想后来被 Transformer 发扬光大——将 RNN 完全去掉,只保留注意力,即”Attention Is All You Need”。详见 Transformer 架构 和 注意力机制。
LSTM 文本分类器
Section titled “LSTM 文本分类器”用 LSTM 做情感分析(如”这部电影太好看了”→ 正面):
import torchimport torch.nn as nn
# 用 LSTM 做文本分类(如情感分析)class LSTMClassifier(nn.Module): def __init__(self, vocab_size, embed_dim=64, hidden_dim=128, num_classes=2, num_layers=2, dropout=0.3): super().__init__() self.embedding = nn.Embedding(vocab_size, embed_dim, padding_idx=0) self.lstm = nn.LSTM(embed_dim, hidden_dim, num_layers=num_layers, batch_first=True, dropout=dropout) self.dropout = nn.Dropout(dropout) self.fc = nn.Linear(hidden_dim, num_classes)
def forward(self, x): emb = self.embedding(x) # (B, seq_len) → (B, seq_len, embed_dim) out, (h, c) = self.lstm(emb) # h: (num_layers, B, hidden) last_h = h[-1] # 取最后一层的隐藏状态 → (B, hidden) return self.fc(self.dropout(last_h))
model = LSTMClassifier(vocab_size=10000)print(model)# 打印模型结构,可以看到 Embedding → LSTM(2层) → Dropout → Linear关键点:
h[-1]取最后一层最后一个时间步的隐藏状态作为整句话的”总结表示”,再接全连接层做分类。padding_idx=0让 padding 位置的词向量恒为 0,不影响训练。
GRU 逐字生成 Demo
Section titled “GRU 逐字生成 Demo”用 GRU 做字符级文本生成——给定开头,逐字续写:
import torchimport torch.nn as nn
class GRUGenerator(nn.Module): def __init__(self, vocab_size, embed_dim=64, hidden_dim=128, num_layers=2): super().__init__() self.num_layers = num_layers self.hidden_dim = hidden_dim self.embedding = nn.Embedding(vocab_size, embed_dim) self.gru = nn.GRU(embed_dim, hidden_dim, num_layers=num_layers, batch_first=True, dropout=0.3) self.fc = nn.Linear(hidden_dim, vocab_size) # 预测下一个字符
def forward(self, x, hidden=None): emb = self.embedding(x) # (B, seq_len) → (B, seq_len, embed_dim) out, hidden = self.gru(emb, hidden) # out: (B, seq_len, hidden) logits = self.fc(out) # (B, seq_len, vocab_size) return logits, hidden # 返回预测 + 传给下一步的状态
@torch.no_grad() def generate(self, start_ids, max_len=100, temperature=0.8): """自回归生成:逐字预测,每次把预测结果作为下一次输入""" self.eval() ids = start_ids[:] hidden = None for _ in range(max_len): x = torch.tensor([[ids[-1]]]) logits, hidden = self.forward(x, hidden) # 用温度系数控制生成多样性:temperature 越小越确定,越大越随机 probs = torch.softmax(logits[0, -1] / temperature, dim=0) next_id = torch.multinomial(probs, 1).item() ids.append(next_id) return ids
model = GRUGenerator(vocab_size=5000)print(model)生成时,把上一步预测的字符作为下一步的输入,循环调用
forward——这就是自回归生成(详见 自回归模型)。温度系数(temperature)控制生成的随机性:temperature < 1使分布更尖锐(更保守),temperature > 1使分布更平坦(更多样)。
梯度裁剪(Gradient Clipping)
Section titled “梯度裁剪(Gradient Clipping)”训练 RNN 时几乎必须设置梯度裁剪,防止梯度爆炸。最常用的是全局范数裁剪:
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=5.0)原理:计算所有梯度的全局 L2 范数,如果超过阈值(如 5.0),则等比例缩放到阈值。这不会改变梯度方向,只限制大小。
处理变长序列
Section titled “处理变长序列”实际任务中序列长度不一。有两种处理策略:
- Padding + Packing:将短序列补零到批次内最长长度,再用 PyTorch 的
pack_padded_sequence告诉 LSTM 跳过 padding 位置。这既节省计算,又避免 padding 干扰隐藏状态。 - Masked Loss:在计算损失时,padding 位置的预测不计入损失(用 mask 矩阵过滤)。
from torch.nn.utils.rnn import pack_padded_sequence, pad_packed_sequence
# lengths 是每个序列的真实长度(降序排列)packed = pack_padded_sequence(emb, lengths, batch_first=True, enforce_sorted=True)packed_out, (h, c) = lstm(packed)out, _ = pad_packed_sequence(packed_out, batch_first=True)学习率与优化器
Section titled “学习率与优化器”- 优化器:Adam(学习率 1e-3)是 RNN 的默认选择,比 SGD 收敛快得多。
- 学习率调度:ReduceLROnPlateau(验证损失停滞时衰减)或 Cosine Annealing 均可。
- Dropout:在 LSTM/GRU 的层间和输出后加 Dropout(0.3-0.5)。注意 PyTorch 的
nn.LSTM只支持层间 Dropout(dropout参数),同一层内的时间步之间不共享 Dropout。
- 随机初始化 + 端到端训练:Embedding 层随机初始化,随模型一起训练。数据量小时容易过拟合。
- 预训练词向量:用 Word2Vec / GloVe / FastText 等预训练词向量初始化 Embedding 层(如 300 维),然后选择冻结或微调。这在小数据集上提升显著。
- 子词(Subword):对于未登录词(OOV),可用 Byte-Pair Encoding(BPE)或 WordPiece 将词拆分为子词单元,避免
<UNK>的问题。这一技术后来被 GPT/BERT 等大模型广泛采用。
最新进展(2024-2025)
Section titled “最新进展(2024-2025)”RNN 的”复兴”:线性 RNN 与状态空间模型
Section titled “RNN 的”复兴”:线性 RNN 与状态空间模型”2023-2024 年,一系列工作重新审视了 RNN 架构,提出线性循环可以兼具 RNN 的常数推理成本和 Transformer 的并行训练能力:
- RWKV(2023-2024):将 Attention 机制改写成线性循环形式,推理时是 RNN(O(1) 显存),训练时可以并行。RWKV-6(2024)在多项语言建模基准上接近同规模 Transformer,同时推理速度更快、显存更省。
- Mamba(Gu & Dao, 2023):基于状态空间模型(SSM, State Space Model),提出选择性状态空间机制,让模型能根据输入动态调整”记忆”——类似 LSTM 的门控但用数学上更优雅的方式实现。Mamba 在长序列建模(如基因组、音频)上展现出超越 Transformer 的潜力。
- Mamba-2(2024):进一步改进,将 SSM 与 Attention 统一在一个框架下,训练效率大幅提升。
- Jamba(AI21 Labs, 2024):将 Mamba 与 Transformer 混合,52B 参数的 Jamba 在长上下文任务中表现出色。
这些工作的核心洞察是:RNN 的 O(1) 推理复杂度和 O(L) 训练时序依赖并非不可拆分。通过巧妙的数学设计,可以实现”训练时并行、推理时循环”的架构,兼顾 Transformer 的表达力和 RNN 的效率。
经典 RNN 仍在使用的场景
Section titled “经典 RNN 仍在使用的场景”尽管 Transformer 已主导 NLP,经典 LSTM/GRU 在以下场景仍有不可替代的优势:
- 流式语音识别(ASR):实时场景(如手机语音助手)要求逐帧处理音频、低延迟输出,RNN 的因果性和 O(1) 推理成本天然适配。参见 语音识别 ASR。
- 资源受限的边缘设备:嵌入式设备(智能手表、IoT 传感器)上跑不了 Transformer,轻量 GRU 是时序信号处理的首选。
- 在线时间序列预测:股票、传感器等流式数据的实时预测,RNN 的增量更新特性比 Transformer 更高效。
- 强化学习中的记忆模块:许多 RL agent 使用 LSTM 来记忆历史状态(如 DeepMind 的 Atari agent)。
RNN 在大模型时代的历史定位
Section titled “RNN 在大模型时代的历史定位”2024-2025 年,几乎没有人会用 LSTM 从头训练一个新的语言模型——Transformer 及其变体(Mamba、RWKV)已经全面取代了这个位置。但理解 RNN/LSTM 仍然是理解现代深度学习的必备基础:
- LSTM 引入的门控思想(选择性地记住和遗忘)影响了几乎所有后续架构。
- Transformer 中的残差连接和层归一化虽然来自 CNN,但”沿序列维度操作”的思维方式来自 RNN。
- Mamba/RWKV 等新架构本质上是对 RNN 的重新发明——理解经典 RNN 的梯度消失问题,才能理解这些新架构在解决什么问题。
- RNN 的致命弱点:无法并行:LSTM/GRU 必须逐时间步处理,长序列训练极慢。除非有特殊需求(流式语音识别、实时时序预测),否则优先用 Transformer。
- 梯度裁剪(Gradient Clipping):训练 RNN 时几乎必须设置——将梯度的全局范数截断(如
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=5.0)),防止梯度爆炸。 - LSTM vs GRU 选择:数据量小、要求速度 → GRU;序列长、需要强记忆 → LSTM;不确定 → 两个都试。实践中差异通常不大。
- 双向 RNN 适用于”看完整个输入再输出”的任务(分类、序列标注、NER),不能用于自回归生成(生成时还没有”未来”信息)。
- PyTorch 中 LSTM/GRU 的隐藏状态维度:返回的
h形状是(num_layers * num_directions, batch, hidden),用h.squeeze(0)或h[-1]取最后一层。 - 处理长序列:如果序列超过 200 步,考虑用 Attention 增强的 RNN(如 BiLSTM + Attention)或直接转向 Transformer。对于超长序列(> 4096),现代 Mamba/RWKV 架构是更好的选择。
- Embedding 层的初始化:小数据集建议用预训练词向量(GloVe、FastText)初始化;大数据集可以从头训练。
- 语音识别(早期方案):在 Transformer 之前,Apple Siri、Microsoft Cortana 等语音助手用 LSTM 声学模型将音频帧逐帧映射为音素,再接语言模型解码成文字。流式语音识别至今仍有 RNN 方案的影子,详见 语音识别 ASR。
- 机器翻译(早期方案):2014–2016 年间,Google 翻译使用 LSTM seq2seq + 注意力机制,质量大幅超越统计机器翻译,后被 Transformer 取代。
- 文本生成:早期自动补全、聊天机器人用 LSTM/GRU 逐字符或逐词生成文本,虽远不如 GPT,但在小模型场景下仍有价值。
- 时间序列预测:电力负荷、交通流量、股票趋势等时序预测,LSTM 长期是默认基线模型(现正被 Transformer 时序变体如 Informer、PatchTST,以及 Mamba 等新架构追赶)。
- 视频动作识别:CNN 提取每帧特征 → LSTM 建模帧间时序关系,用于动作识别(如打架检测、手势识别)。
- 音乐生成:LSTM 在符号化音乐生成(MIDI 序列)中仍有应用——相比音频波形,MIDI 序列更短、更离散,LSTM 的表达能力足够。
典型类库与工具
Section titled “典型类库与工具”| 类库 | 语言 | 说明 |
|---|---|---|
| PyTorch | Python | nn.LSTM / nn.GRU / nn.RNN 内置,灵活搭建各种循环网络 |
| TensorFlow / Keras | Python | tf.keras.layers.LSTM / GRU / Bidirectional,一行实现双向 RNN |
| fairseq | Python | Meta 开源的序列建模工具箱,支持 seq2seq 翻译训练 |
| OpenNMT | Python | 开源神经机器翻译工具箱,支持 LSTM seq2seq + 注意力 |
| AllenNLP | Python | 学术友好型 NLP 库,内置 BiLSTM、ELMo 等经典模型组件 |
| Mamba | Python | 状态空间模型(SSM)库,提供 Mamba/RWKV 等线性 RNN 变体 |
| 术语 | 英文 | 解释 |
|---|---|---|
| 循环神经网络 | RNN (Recurrent Neural Network) | 按时间步逐步处理序列并在步骤间传递隐藏状态的神经网络 |
| 隐藏状态 | Hidden State | RNN 在每个时间步传递的”记忆”,编码了到当前为止的上下文信息 |
| 细胞状态 | Cell State | LSTM 中贯穿序列的信息通道,通过加法更新,缓解梯度消失 |
| 梯度消失 | Vanishing Gradient | 长序列中梯度沿时间链回传时指数衰减至零,导致无法学习远距离依赖 |
| 梯度爆炸 | Exploding Gradient | 梯度沿时间链回传时指数增长,导致参数更新发散,可用梯度裁剪缓解 |
| 沿时间反向传播 | BPTT (Backpropagation Through Time) | RNN 的训练方法,将网络沿时间展开后应用标准反向传播 |
| 长短期记忆 | LSTM | 用遗忘门/输入门/输出门控制信息流动,解决 RNN 梯度消失的变体 |
| 门控循环单元 | GRU | LSTM 的简化版,将三门合并为重置门和更新门,参数更少速度更快 |
| 双向 RNN | Bidirectional RNN | 同时正向和反向处理序列,拼接两个方向的隐藏状态,适用于分类标注 |
| seq2seq | Sequence-to-Sequence | 编码器将源序列编码为向量、解码器从向量生成目标序列的架构 |
| Teacher Forcing | Teacher Forcing | 训练解码器时用真实标签而非模型预测作为下一步输入的策略 |
| 状态空间模型 | SSM (State Space Model) | 用状态方程建模序列的数学框架,Mamba 等现代线性 RNN 的理论基础 |
- RNN 谱系:Jordan 网络(1986)/ Elman 网络(1990)→ LSTM(Hochreiter & Schmidhuber, 1997,解决梯度消失)→ GRU(Cho et al., 2014,简化版 LSTM)→ seq2seq(Sutskever et al., 2014)→ Bahdanau 注意力(2014)。2017 年后大面积被 Transformer 取代。
- 注意力机制的诞生:Bahdanau 注意力是为了解决 seq2seq 的固定上下文向量瓶颈而提出的。这一思想直接启发了自注意力机制,最终催生了 Transformer。深入理解注意力机制见 注意力机制。
- Transformer 的全面讲解见 Transformer 架构。
- 大语言模型的起点:GPT 系列本质上是”去掉 RNN、用 Transformer Decoder 的自回归语言模型”,详见 语言模型演进 和 自回归模型。
- RNN 的现代复兴:Mamba(Gu & Dao, 2023)和 RWKV(2023-2024)重新审视了 RNN 架构,通过线性循环实现了”训练并行 + 推理常数复杂度”,在长序列建模上展现出超越 Transformer 的潜力。
- Pascanu et al., 「On the difficulty of training Recurrent Neural Networks」(ICML 2013):系统分析了 RNN 的梯度消失/爆炸问题,是理解 LSTM 动机的经典文献。