人工智能之核心技术 深度学习
第四章 循环神经网络(RNN)与序列模型
前言:循环神经网络(RNN)与序列模型 —— 自然语言处理基础
如果说 CNN 是处理空间结构(如图像)的利器,那么 RNN(Recurrent Neural Network) 就是专为时间序列/顺序数据设计的深度学习模型。它在自然语言处理(NLP)、语音识别、时间序列预测等领域扮演着核心角色。
一、RNN 基础
1.1 结构与原理:建模时序依赖
人类理解语言时会“记住”上下文。例如:
“我今天吃了 ___。” → 听到“吃”,你会预期后面是“饭”、“苹果”等食物。
RNN 模拟这种记忆机制:将上一时刻的隐藏状态传递给下一时刻。
核心公式:
- :t 时刻输入(如词向量)
- :t 时刻隐藏状态(“记忆”)
- :t 时刻输出(如预测下一个词)
graph LR
x1[x₁] --> R1[RNN Cell]
h0[h₀=0] --> R1
R1 --> h1[h₁]
R1 --> y1[y₁]
x2[x₂] --> R2[RNN Cell]
h1 --> R2
R2 --> h2[h₂]
R2 --> y2[y₂]
x3[x₃] --> R3[RNN Cell]
h2 --> R3
R3 --> h3[h₃]
R3 --> y3[y₃]
style h0 fill:#f9f,stroke:#333
style h1 fill:#bbf,stroke:#333
style h2 fill:#bbf,stroke:#333
style h3 fill:#bbf,stroke:#333
💡 关键思想:参数共享!所有时间步使用同一组权重 ,使模型能处理任意长度序列。
1.2 RNN 的局限性
尽管 RNN 能建模短期依赖,但在实践中面临两大挑战:
| 问题 | 原因 | 后果 |
|---|---|---|
| 长期依赖问题 | 信息需跨多个时间步传递 | 远距离词无法有效关联(如“猫…它”) |
| 梯度消失/爆炸 | 反向传播时链式法则连乘: | - 梯度趋近 0 → 参数几乎不更新- 梯度爆炸 → 训练不稳定 |
📌 实验现象:标准 RNN 在序列长度 > 20 时几乎无法学习长期模式。
二、RNN 变体:解决长期依赖
2.1 LSTM(Long Short-Term Memory)
由 Hochreiter & Schmidhuber (1997) 提出,通过门控机制精确控制信息流动。
三大门控:
- 遗忘门(Forget Gate):决定丢弃多少旧记忆
- 输入门(Input Gate):决定存储多少新信息
- 输出门(Output Gate):决定输出多少当前记忆
单元状态(Cell State):
- 主信息流:
- 隐藏状态:
flowchart TB
subgraph LSTM_Cell
xt["x_t"] --> Concat1
h_prev["h_{t-圩}"] --> Concat1
Concat1 --> ft["Forget Gate σ"]
Concat1 --> it["Input Gate σ"]
Concat1 --> Ct_tilde["\\tilde{C}_t (tanh)"]
Concat1 --> ot["Output Gate σ"]
C_prev["C_{t-1}"] --> Mult1
ft --> Mult1
it --> Mult2
Ct_tilde --> Mult2
Mult1 --> Add1
Mult2 --> Add1
Add1 --> Ct["C_t"]
Ct --> tanh1["tanh"]
ot --> Mult3
tanh1 --> Mult3
Mult3 --> ht["h_t"]
end
✅ 优势:细胞状态像“传送带”,梯度可无损传递 → 解决长期依赖!
2.2 GRU(Gated Recurrent Unit)
Cho et al. (2014) 提出的简化版 LSTM,只有两个门:
- 重置门(Reset Gate):控制忽略过去信息的程度
- 更新门(Update Gate):控制保留多少旧状态
公式:
⚡ 优点:参数更少、训练更快;性能与 LSTM 相当 → 现代 NLP 常用
2.3 双向 RNN(Bi-RNN / Bi-LSTM)
标准 RNN 只能利用过去信息。但很多任务需要上下文双向信息,例如:
“他把__送到医院。” → 空格处可能是“病人”或“医生”,需看后文“送到医院”才能确定。
Bi-RNN 同时运行两个 RNN:
- 前向 RNN:
- 后向 RNN:
- 最终表示:
graph LR
x1 --> F1
x2 --> F2
x3 --> F3
F1 --> F2
F2 --> F3
x3 --> B3
x2 --> B2
x1 --> B1
B3 --> B2
B2 --> B1
F1 --> H1["h₁ = [→h₁; ←h₁]"]
B1 --> H1
F2 --> H2["h₂ = [→h₂; ←h₂]"]
B2 --> H2
F3 --> H3["h₃ = [→h₃; ←h₃]"]
B3 --> H3
📌 应用:命名实体识别(NER)、情感分析、机器翻译编码器
三、序列模型应用场景
3.1 文本分类 & 情感分析
- 任务:判断句子情感(正面/负面)
- 模型:
Embedding → Bi-LSTM → MaxPooling → Dense - 输出:单个概率值(Sigmoid)或类别(Softmax)
3.2 文本生成
- 任务:给定开头,生成连贯文本(如诗歌、新闻)
- 方法:自回归(Autoregressive)
- 训练:Teacher Forcing(用真实历史词作为输入)
- 推理:逐词生成(贪心搜索 / Beam Search)
3.3 机器翻译入门(Seq2Seq)
Sequence-to-Sequence(Seq2Seq) 架构:
- 编码器(Encoder):Bi-LSTM 将源句压缩为上下文向量
- 解码器(Decoder):LSTM 根据 和已生成词预测下一个词
flowchart LR
subgraph Encoder
E1["'I'"] --> Enc
E2["'love'"] --> Enc
E3["'you'"] --> Enc
Enc[LSTM] --> c[(Context Vector)]
end
subgraph Decoder
c --> Dec
D1["<sos>"] --> Dec
Dec[LSTM] --> D2["'Je'"]
D2 --> Dec2
Dec2[LSTM] --> D3["'t'aime'"]
D3 --> Dec3
Dec3[LSTM] --> D4["<eos>"]
end
🔜 后续演进:Attention 机制(Bahdanau et al., 2015)→ Transformer(2017)
四、配套代码实现(PyTorch)
示例 1:LSTM 文本分类
import torch
import torch.nn as nn
class LSTMClassifier(nn.Module):
def __init__(self, vocab_size, embed_dim, hidden_dim, num_classes, num_layers=1):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim, padding_idx=0)
self.lstm = nn.LSTM(embed_dim, hidden_dim, num_layers,
batch_first=True, bidirectional=True)
self.fc = nn.Linear(hidden_dim * 2, num_classes) # *2 for bidirectional
self.dropout = nn.Dropout(0.5)
def forward(self, x):
# x: [batch_size, seq_len]
x = self.embedding(x) # [B, L, embed_dim]
out, (hn, _) = self.lstm(x) # out: [B, L, hidden*2]
# Use last timestep output
out = self.dropout(out[:, -1, :]) # [B, hidden*2]
out = self.fc(out) # [B, num_classes]
return out
# 使用示例
model = LSTMClassifier(vocab_size=10000, embed_dim=128, hidden_dim=256, num_classes=2)
x = torch.randint(0, 10000, (32, 20)) # batch=32, seq_len=20
output = model(x)
print(output.shape) # torch.Size([32, 2])
示例 2:GRU 文本生成(简化版)
class GRUGenerator(nn.Module):
def __init__(self, vocab_size, embed_dim, hidden_dim):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim)
self.gru = nn.GRU(embed_dim, hidden_dim, batch_first=True)
self.fc = nn.Linear(hidden_dim, vocab_size)
def forward(self, x, hidden=None):
x = self.embedding(x) # [B, L, E]
out, hidden = self.gru(x, hidden) # out: [B, L, H]
out = self.fc(out) # [B, L, V]
return out, hidden
# 训练时:输入整个序列(含目标)
# 推理时:逐字生成
五、补充:RNN 的现代地位
虽然 Transformer 已成为 NLP 主流(如 BERT、GPT),但 RNN 仍有其价值:
- 低资源场景:RNN 计算开销小,适合移动端
- 时间序列预测:金融、IoT 数据仍常用 LSTM/GRU
- 教学意义:理解序列建模的基础
✅ 选择建议:
- 新项目 → 优先尝试 Transformer
- 资源受限 / 简单任务 → Bi-LSTM / GRU
六、总结对比
| 模型 | 门控机制 | 参数量 | 长期依赖 | 速度 |
|---|---|---|---|---|
| RNN | 无 | 少 | ❌ 差 | 快 |
| LSTM | 3 个门 | 多 | ✅ 强 | 慢 |
| GRU | 2 个门 | 中 | ✅ 强 | 中 |
| Bi-LSTM | 双向 + LSTM | 很多 | ✅✅ 最强 | 慢 |
graph TD
A[序列任务] --> B{需要双向上下文?}
B -->|是| C[Bi-LSTM / Bi-GRU]
B -->|否| D{资源充足?}
D -->|是| E[LSTM]
D -->|否| F[GRU]
资料关注
公众号:咚咚王 gitee:gitee.com/wy185850518…

《Python编程:从入门到实践》 《利用Python进行数据分析》 《算法导论中文第三版》 《概率论与数理统计(第四版) (盛骤) 》 《程序员的数学》 《线性代数应该这样学第3版》 《微积分和数学分析引论》 《(西瓜书)周志华-机器学习》 《TensorFlow机器学习实战指南》 《Sklearn与TensorFlow机器学习实用指南》 《模式识别(第四版)》 《深度学习 deep learning》伊恩·古德费洛著 花书 《Python深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》 《深入浅出神经网络与深度学习+(迈克尔·尼尔森(Michael+Nielsen)》 《自然语言处理综论 第2版》 《Natural-Language-Processing-with-PyTorch》 《计算机视觉-算法与应用(中文版)》 《Learning OpenCV 4》 《AIGC:智能创作时代》杜雨+&+张孜铭 《AIGC原理与实践:零基础学大语言模型、扩散模型和多模态模型》 《从零构建大语言模型(中文版)》 《实战AI大模型》 《AI 3.0》