一、循环神经网络基础
前馈神经网络(Feedforward NN)将每个输入视为独立样本,无法处理具有时序依赖关系的数据。现实世界中大量数据是序列化的——文本、语音、时间序列——它们的当前状态依赖于历史信息。
序列数据的典型场景:
- 自然语言文本:词的含义取决于上下文,"苹果"在不同句子中含义不同
- 语音信号:当前音素的识别依赖前后音素的组合
- 时间序列:股价、气温等数据具有时序相关性
- 视频帧序列:动作识别需要理解帧与帧之间的关系
循环神经网络(RNN)
- 具有循环连接(recurrent connection)
- 维护隐藏状态ht 作为"记忆"
- 参数在时间步之间共享
- 输入/输出长度可变
前馈神经网络(FNN)
- 信号单向从输入层到输出层
- 无内部记忆,每个样本独立处理
- 各层参数独立
- 输入/输出维度固定
RNN 递推公式:
隐藏状态更新:ht=σ(Whh⋅ht−1+Wxh⋅xt+bh)
输出计算:yt=Why⋅ht+by
各符号含义:
| 符号 | 含义 |
|---|
| xt | 时刻 t 的输入向量 |
| ht | 时刻 t 的隐藏状态(hidden state),编码了历史信息 |
| ht−1 | 上一时刻的隐藏状态 |
| Wxh | 输入到隐藏层的权重矩阵 |
| Whh | 隐藏层到隐藏层的权重矩阵(循环权重) |
| Why | 隐藏层到输出层的权重矩阵 |
| bh,by | 偏置项 |
| σ | 激活函数(通常为 tanh 或 ReLU) |
RNN 的循环结构可以沿时间轴展开(unfold),形成一个等价的深度前馈网络。每个时间步对应网络中的一"层",但所有层共享相同的参数 Whh,Wxh,Why。
展开后的关键性质:
- 网络深度等于序列长度 T,因此长序列 = 极深网络
- 参数共享使得模型可以处理任意长度的序列
- 展开后可以使用标准的反向传播算法
BPTT 是标准反向传播在时间维度上的推广:
- 前向传播:按时间顺序 t=1,2,…,T 计算所有隐藏状态和输出
- 计算损失:L=∑t=1TLt(yt,y^t)
- 反向传播:从 t=T 逆序回溯到 t=1,累积梯度
- 参数更新:梯度求和后一次性更新共享参数
对权重 Whh 的梯度为:
∂Whh∂L=∑t=1T∑k=1t∂ht∂Lt⋅∂hk∂ht⋅∂Whh∂hk
Truncated BPTT:实践中,为减少计算量和缓解梯度问题,通常将序列截断为固定长度的片段进行反向传播,而不是完整回溯到 t=1。
二、梯度问题
在 BPTT 中,梯度从时刻 t 传播到时刻 k 需要经过连乘:
梯度传播公式:
∂hk∂ht=∏i=k+1tWhh⋅diag(σ′(zi))
其中 zi=Whh⋅hi−1+Wxh⋅xi+bh,σ′ 为激活函数的导数。
这是一个矩阵连乘,其行为由 Whh 的特征值决定:
| 问题 | 梯度消失(Vanishing) | 梯度爆炸(Exploding) |
|---|
| 条件 | Whh 的最大特征值 <1 | Whh 的最大特征值 >1 |
| 现象 | 梯度以指数速度趋近于 0 | 梯度以指数速度趋近于 ∞ |
| 后果 | 无法学习长程依赖关系 | 参数更新过大,训练不稳定(NaN) |
| 直觉类比 | 反复乘以 0.9:0.9100≈0.000027 | 反复乘以 1.1:1.1100≈13781 |
| 解决方案 | LSTM/GRU 门控机制、残差连接 | 梯度裁剪(Gradient Clipping) |
梯度裁剪公式(解决梯度爆炸):
若 ∥g∥>threshold,则:g←threshold×∥g∥g
即保持梯度方向不变,但将其范数缩放到阈值以内。
直觉理解:梯度裁剪相当于在梯度空间中设定一个"速度上限",防止参数更新步幅过大导致训练发散。
三、LSTM(Long Short-Term Memory)
引入细胞状态(Cell State)Ct 作为信息传输的"高速公路"。细胞状态通过加法更新(而非乘法),使梯度能够无衰减地长距离流动,从根本上解决梯度消失问题。
所有门都使用 sigmoid 激活函数,输出值在 [0,1] 之间,起到"开关"的作用:0 表示完全阻断,1 表示完全通过。
决定从细胞状态中丢弃什么信息
ft=σ(Wf⋅[ht−1,xt]+bf)
当 ft≈0 时,旧信息被遗忘;当 ft≈1 时,旧信息被保留。
决定存储什么新信息到细胞状态
门控信号:it=σ(Wi⋅[ht−1,xt]+bi)
候选值:C~t=tanh(WC⋅[ht−1,xt]+bC)
it 控制候选值中哪些分量被写入细胞状态。
决定从细胞状态中输出什么信息作为隐藏状态
ot=σ(Wo⋅[ht−1,xt]+bo)
输出门过滤细胞状态,生成当前时刻的隐藏状态。
细胞状态更新(加法结构——梯度高速公路):
Ct=ft⊙Ct−1+it⊙C~t
隐藏状态输出:
ht=ot⊙tanh(Ct)
梯度消失的解决方案
- 细胞状态通过加法更新,梯度沿 Ct 传播时:∂Ct−1∂Ct=ft
- 遗忘门 ft 可以学习到接近 1 的值,使梯度几乎无损传播
- 相比标准 RNN 的连续矩阵乘法,LSTM 的加法结构避免了指数衰减
四、GRU(Gated Recurrent Unit)
GRU 是 LSTM 的简化版本,将 3 个门简化为 2 个门,同时将细胞状态和隐藏状态合并为一个状态。在许多任务上 GRU 的性能与 LSTM 相当,但参数更少、训练更快。
更新门(合并了 LSTM 的遗忘门和输入门):
zt=σ(Wz⋅[ht−1,xt])
重置门(控制遗忘多少历史信息):
rt=σ(Wr⋅[ht−1,xt])
候选隐藏状态:
h~t=tanh(W⋅[rt⊙ht−1,xt])
最终隐藏状态(插值更新):
ht=(1−zt)⊙ht−1+zt⊙h~t
直觉理解:
- 更新门 zt:决定"保留多少旧状态 vs 接受多少新信息"——当 zt=0 时完全保留旧状态,zt=1 时完全使用新候选值
- 重置门 rt:决定计算候选值时"参考多少历史"——当 rt=0 时忽略历史,相当于从头开始
| 特性 | LSTM | GRU |
|---|
| 门的数量 | 3 个(遗忘、输入、输出) | 2 个(更新、重置) |
| 状态 | 细胞状态 Ct + 隐藏状态 ht | 仅隐藏状态 ht |
| 参数量 | 4×(n2+nm+n) | 3×(n2+nm+n) |
| 计算复杂度 | 较高(更多矩阵运算) | 较低(约 LSTM 的 75%) |
| 长序列建模 | 略优(独立的细胞状态通道) | 稍逊 |
| 训练速度 | 较慢 | 较快 |
| 适用场景 | 长序列、需要精细记忆控制 | 中等序列、计算资源有限 |
| 输出暴露 | 通过输出门过滤 | 直接暴露全部状态 |
五、RNN 应用模式
Many-to-One(序列分类)
输入:整个序列 x1,x2,…,xT
输出:单个标签 y
典型应用:情感分析、文档分类
方法:取最后时刻隐藏状态 hT 进行分类
One-to-Many(序列生成)
输入:单个向量 x(如图像特征)
输出:序列 y1,y2,…,yT
典型应用:图像描述生成、音乐生成
方法:初始输入驱动,逐步生成
Many-to-Many(Seq2Seq)
输入:序列 x1,…,xT
输出:不同长度序列 y1,…,yT′
典型应用:机器翻译、文本摘要
方法:Encoder-Decoder 架构
Many-to-Many Synced(序列标注)
输入:序列 x1,x2,…,xT
输出:等长序列 y1,y2,…,yT
典型应用:词性标注(POS)、NER
方法:每个时间步都有对应输出
工作流程:
- Encoder:将输入序列编码为固定长度的上下文向量 c=hTenc
- Decoder:以上下文向量为初始状态,逐步生成输出序列
- Decoder 每一步的输入为上一步的输出(Teacher Forcing 训练时用真实标签)
瓶颈问题:所有输入信息被压缩为单个向量 c,对长序列信息损失严重。这一问题催生了注意力机制(Attention),将在后续课程中详细讨论。
六、双向 RNN(Bidirectional RNN)
标准 RNN 只能利用过去的信息(从左到右),但很多任务中未来的上下文同样重要。例如在命名实体识别中,判断一个词是否为人名需要同时看其前后的词。
双向 RNN 结构:
前向隐藏状态:ht=σ(Wh⋅ht−1+Wxh⋅xt+bh)
反向隐藏状态:ht=σ(Wh⋅ht+1+Wxh⋅xt+bh)
最终表示:ht=[ht;ht](拼接)
特点:
- 每个时刻的表示融合了过去和未来的完整上下文信息
- 参数量翻倍(前向和反向各有独立参数)
- 不适用于实时/在线任务(需要完整序列才能计算反向状态)
- 非常适合分类和标注任务(如 BERT 的本质就是双向编码)
七、深层 RNN(Deep/Stacked RNN)
将多个 RNN 层垂直堆叠,下层的隐藏状态序列作为上层的输入序列:
ht(l)=σ(Whh(l)⋅ht−1(l)+Wxh(l)⋅ht(l−1)+bh(l))
其中 l 表示层索引,ht(0)=xt。
| 模型/概念 | 核心公式 |
|---|
| 基本 RNN | ht=σ(Whhht−1+Wxhxt+bh) |
| 梯度传播 | ∂hk∂ht=∏i=k+1tWhh⋅diag(σ′(zi)) |
| 梯度裁剪 | g←threshold×∥g∥gif ∥g∥>threshold |
| LSTM 遗忘门 | ft=σ(Wf⋅[ht−1,xt]+bf) |
| LSTM 输入门 | it=σ(Wi⋅[ht−1,xt]+bi) |
| LSTM 候选值 | C~t=tanh(WC⋅[ht−1,xt]+bC) |
| LSTM 输出门 | ot=σ(Wo⋅[ht−1,xt]+bo) |
| LSTM 细胞更新 | Ct=ft⊙Ct−1+it⊙C~t |
| LSTM 隐藏状态 | ht=ot⊙tanh(Ct) |
| GRU 更新门 | zt=σ(Wz⋅[ht−1,xt]) |
| GRU 重置门 | rt=σ(Wr⋅[ht−1,xt]) |
| GRU 输出 | ht=(1−zt)⊙ht−1+zt⊙h~t |