RNN(循环神经网络):从序列建模到 LSTM/GRU
本文从 AI 工程师和系统架构师的视角,系统分析 RNN(Recurrent Neural Network,循环神经网络)的核心思想、数学原理、反向传播、梯度消失、LSTM、GRU、训练方法以及工程实践。
RNN 虽然已经不是现代大模型的主流架构,但理解 RNN 是理解 Transformer、Attention、LLM、Agent Memory 和序列建模的重要基础。
1. 为什么需要 RNN?
传统神经网络通常假设输入之间相互独立。
例如:
x1 → Neural Network → y1
x2 → Neural Network → y2
x3 → Neural Network → y3
但是现实世界大量数据具有明显的序列特征:
- 自然语言
- 语音
- 时间序列
- 股票价格
- 用户行为
- 传感器数据
- 日志
- 网络流量
- 视频帧
例如:
我 → 喜欢 → 学习 → 人工智能
当模型看到:
“我喜欢学习……”
它应该能够利用前面的上下文预测后面的内容。
这意味着模型需要具备一种能力:
当前计算不仅依赖当前输入,还应该依赖之前看到的信息。
RNN 的核心思想就是:
把过去的信息通过 hidden state 传递到当前时刻。
2. RNN 的核心思想
RNN 与普通神经网络最大的区别,是存在一个循环结构。
基本结构:
┌──────────────┐
│ ↓
x_t → [ RNN Cell ] → h_t → [ RNN Cell ]
↑
│
h_(t-1)
在时间维度展开以后:
x1 ──→ [RNN] ──→ h1
│
x2 ──→ [RNN] ──→ h2
│
x3 ──→ [RNN] ──→ h3
│
x4 ──→ [RNN] ──→ h4
其中:
x_t:当前时间步输入h_t:当前隐藏状态h_(t-1):前一个时间步隐藏状态y_t:当前输出
核心公式:
h_t = f(W_xh x_t + W_hh h_(t-1) + b_h)
输出:
y_t = g(W_hy h_t + b_y)
其中:
W_xh
负责:
当前输入 → Hidden State
而:
W_hh
负责:
Previous Hidden State → Current Hidden State
这就是 RNN 能够“记住过去”的关键。
3. RNN 本质上是什么?
从工程角度看,RNN 可以理解成一个:
带状态的神经网络。
普通神经网络:
Input
↓
Network
↓
Output
RNN:
Input + Previous State
↓
Network
↓
Current State + Output
因此:
State_t = F(Input_t, State_(t-1))
这实际上和很多传统系统设计思想非常类似。
例如:
state = update(state, event);
RNN 做的事情就是:
h_t = update(h_(t-1), x_t)
所以可以把 RNN 看成一种:
可学习的状态机(Learnable State Machine)。
这是理解 RNN 非常重要的一个视角。
4. RNN 的数学结构
假设输入:
x_t ∈ R^D
隐藏状态:
h_t ∈ R^H
那么:
W_xh ∈ R^(H×D)
W_hh ∈ R^(H×H)
偏置:
b_h ∈ R^H
计算:
z_t = W_xh x_t + W_hh h_(t-1) + b_h
然后经过激活函数:
h_t = tanh(z_t)
最终:
y_t = W_hy h_t + b_y
所以完整模型:
x_t
│
▼
W_xh x_t
│
├─────────────┐
│ │
▼ │
(+) ← W_hh h_(t-1)
│
▼
tanh
│
▼
h_t
│
▼
Output
5. 为什么 RNN 能处理变长输入?
这是 RNN 非常重要的特点。
例如:
Hello
长度:
5
或者:
I love artificial intelligence
长度:
32
RNN 并不要求固定长度输入。
它可以:
x1 → h1
x2 → h2
x3 → h3
...
xn → hn
因此:
Sequence Length = n
可以动态变化。
这使 RNN 非常适合:
- NLP
- Speech Recognition
- Time Series
- Event Stream
- Sensor Data
6. RNN 的关键问题:长期记忆
RNN 虽然能够传递状态,但存在一个非常严重的问题:
长期依赖(Long-Term Dependency)问题。
例如:
The cat that was sitting on the table near the window
was hungry.
模型需要知道:
cat → was
但是中间存在很多词。
信息需要经过:
h1 → h2 → h3 → h4 → ... → h50
随着序列越来越长,早期的信息可能逐渐丢失。
这就是:
Long-Term Dependency Problem
7. RNN 的梯度消失问题
这是理解 RNN 最重要的理论知识之一。
RNN 通过时间反向传播:
Backpropagation Through Time(BPTT)
假设:
h_t = tanh(W_hh h_(t-1) + ...)
在反向传播过程中:
∂L/∂h_(t-k)
需要连续乘很多 Jacobian:
∂L/∂h_t
×
∂h_t/∂h_(t-1)
×
∂h_(t-1)/∂h_(t-2)
×
...
简化理解:
gradient ≈ W^k
如果:
|W| < 1
那么:
W^k → 0
例如:
0.5^10 ≈ 0.00098
0.5^50 ≈ 8.88 × 10^-16
随着时间步增加,梯度迅速趋近于:
0
这就是:
Vanishing Gradient(梯度消失)
8. 梯度爆炸
另外一种情况是:
|W| > 1
例如:
1.5^10 ≈ 57.7
1.5^50 ≈ 6.37 × 10^8
梯度会越来越大。
这就是:
Exploding Gradient(梯度爆炸)
表现为:
loss → NaN
或者:
gradient → extremely large
9. Gradient Clipping
解决梯度爆炸的常见方法:
Gradient Clipping
例如:
if ||gradient|| > threshold:
gradient = gradient * threshold / ||gradient||
PyTorch:
torch.nn.utils.clip_grad_norm_(
model.parameters(),
max_norm=1.0
)
其思想非常简单:
正常梯度
↓
直接更新
超大梯度
↓
限制最大范数
↓
再更新
需要注意:
Gradient Clipping 可以缓解梯度爆炸,但不能从根本上解决 RNN 的长期依赖问题。
真正重要的解决方案是:
LSTM / GRU
10. LSTM:RNN 的重要升级
LSTM:
Long Short-Term Memory
中文:
长短期记忆网络。
LSTM 的核心思想是:
增加一个独立的 Cell State,并通过 Gate 控制信息流。
普通 RNN:
h_(t-1)
↓
RNN
↓
h_t
LSTM:
Cell State
│
▼
h_(t-1) → [ Gates + Memory ] → h_t
↑
│
x_t
LSTM 主要包含三个 Gate:
Forget Gate
Input Gate
Output Gate
11. Forget Gate
Forget Gate 决定:
过去的信息哪些应该忘掉?
公式:
f_t = σ(W_f [h_(t-1), x_t] + b_f)
其中:
σ = sigmoid
输出范围:
0 ~ 1
例如:
f_t = 0
表示:
完全忘记。
f_t = 1
表示:
完全保留。
因此:
Old Memory
│
▼
Forget Gate
│
▼
Filtered Memory
12. Input Gate
Input Gate 决定:
当前输入哪些信息应该写入 Memory?
首先:
i_t = σ(W_i[h_(t-1), x_t] + b_i)
然后产生候选记忆:
C̃_t = tanh(W_C[h_(t-1), x_t] + b_C)
最终:
C_t =
f_t ⊙ C_(t-1)
+
i_t ⊙ C̃_t
这里的:
⊙
表示逐元素乘法。
这一步是 LSTM 最核心的地方。
13. Output Gate
Output Gate 决定:
当前 Memory 中哪些信息应该输出?
公式:
o_t = σ(W_o[h_(t-1), x_t] + b_o)
然后:
h_t = o_t ⊙ tanh(C_t)
因此完整 LSTM:
┌───────────────┐
│ Cell State │
│ C_t │
└───────────────┘
↑
Forget/Input
↑
│
x_t ─────────→ [ LSTM Cell ]
│
↓
h_t
14. 为什么 LSTM 能解决长期依赖?
这是理解 LSTM 的核心。
普通 RNN:
h1 → h2 → h3 → h4 → h5 → ...
每一步都需要经过:
tanh
信息很容易衰减。
LSTM 引入:
Cell State
它提供了一条相对稳定的信息传递路径:
C1 ───────────────→ C2 ───────────────→ C3 ─────────────→ Cn
↑ ↑ ↑
Gate Gate Gate
Gate 可以决定:
保留
删除
写入
输出
所以 LSTM 本质上是在学习:
什么信息应该记住,什么信息应该忘记。
15. GRU:更简单的 LSTM
GRU:
Gated Recurrent Unit
它可以理解为:
简化版 LSTM。
GRU 没有独立的 Cell State。
主要有两个 Gate:
Update Gate
Reset Gate
Update Gate:
z_t = σ(W_z[x_t, h_(t-1)] + b_z)
Reset Gate:
r_t = σ(W_r[x_t, h_(t-1)] + b_r)
候选状态:
h̃_t =
tanh(
W_h[x_t, r_t ⊙ h_(t-1)]
)
最终:
h_t =
(1-z_t) ⊙ h_(t-1)
+
z_t ⊙ h̃_t
16. LSTM vs GRU
| 特性 | RNN | LSTM | GRU |
|---|---|---|---|
| Hidden State | ✅ | ✅ | ✅ |
| Cell State | ❌ | ✅ | ❌ |
| Gate | ❌ | 3 | 2 |
| 参数量 | 少 | 多 | 中 |
| 长期依赖 | 弱 | 强 | 强 |
| 计算成本 | 低 | 高 | 中 |
| 训练速度 | 快 | 较慢 | 较快 |
工程实践中:
简单序列 → RNN
复杂长期依赖 → LSTM
希望降低复杂度 → GRU
17. RNN 的四种典型结构
RNN 不只是“一进一出”。
常见结构包括:
17.1 One-to-One
Input → Model → Output
实际上普通神经网络即可。
17.2 One-to-Many
┌→ y1
x → RNN ├→ y2
└→ y3
例如:
Image Caption
输入一张图片:
Image
↓
CNN
↓
RNN
↓
A cat is sitting...
17.3 Many-to-One
x1
↓
x2 → RNN → y
↓
x3
例如:
Sentiment Analysis
输入:
I really love this movie
输出:
Positive
17.4 Many-to-Many
x1 → RNN → y1
x2 → RNN → y2
x3 → RNN → y3
例如:
POS Tagging
I → PRON
love → VERB
AI → NOUN
18. Bidirectional RNN
普通 RNN:
x1 → x2 → x3 → x4
信息只能:
过去 → 现在
BiRNN:
Forward:
x1 → x2 → x3 → x4
Backward:
x4 → x3 → x2 → x1
最终:
h_t = [h_forward ; h_backward]
这样模型同时利用:
Past Context
+
Future Context
例如:
I went to the bank to deposit money.
“bank”的语义需要上下文判断。
双向模型可以利用:
前文 + 后文
因此在 NLP 中非常有效。
19. RNN 的训练:BPTT
RNN 训练使用:
Backpropagation Through Time
首先把 RNN 在时间维度展开:
┌───────────────┐
x1 → [RNN] → h1 │
│ │
x2 → [RNN] → h2 │
│ │
x3 → [RNN] → h3 │
│ │
x4 → [RNN] → h4 │
虽然看起来像多个网络:
RNN1
RNN2
RNN3
RNN4
实际上它们共享参数:
W_xh
W_hh
W_hy
这也是 RNN 参数量不会随着序列长度线性增加的原因。
20. Truncated BPTT
如果序列特别长:
x1 → x2 → ... → x100000
完整 BPTT 的成本非常高。
因此实际训练经常使用:
Truncated Backpropagation Through Time
例如每:
20 steps
截断一次:
x1 → ... → x20
↓
Backprop
x21 → ... → x40
↓
Backprop
这样能够:
- 降低内存消耗
- 降低计算成本
- 提高训练效率
但代价是:
模型无法通过反向传播学习非常长的依赖关系。
21. RNN 在 NLP 中的应用
早期 NLP 系统大量使用:
Embedding
↓
RNN / LSTM
↓
Classifier
例如文本分类:
"I love this product"
↓
Tokenization
↓
Embedding
↓
LSTM
↓
Hidden State
↓
Fully Connected
↓
Positive
22. Word Embedding + RNN
RNN 本身不能直接理解:
cat
dog
machine
通常需要 Embedding。
例如:
"cat"
↓
Embedding
↓
[0.21, -0.33, 0.72, ...]
得到:
x1
x2
x3
...
然后:
x1 → RNN
x2 → RNN
x3 → RNN
因此经典 NLP 架构:
Text
↓
Tokenizer
↓
Embedding
↓
RNN/LSTM/GRU
↓
Dense
↓
Prediction
23. RNN 为什么最终被 Transformer 大量替代?
这是理解现代 AI 技术栈非常重要的问题。
RNN 最大的问题不是“表达能力不足”,而是:
序列计算天然具有强依赖关系。
例如:
h1
↓
h2
↓
h3
↓
h4
必须等待:
h1 → h2 → h3 → h4
因此难以完全并行。
而 Transformer 可以:
x1 ─┐
x2 ─┤
x3 ─┼→ Self-Attention
x4 ─┤
x5 ─┘
大量计算可以并行执行。
这对 GPU/TPU 非常重要。
24. RNN 与 Transformer 的本质区别
可以从“信息访问方式”理解。
RNN:
Current Token
↓
Previous Hidden State
↓
Previous Context
信息必须逐步传递。
Transformer:
┌─────────────┐
x1 ─────────→│ │
x2 ─────────→│ Self │
x3 ─────────→│ Attention │
x4 ─────────→│ │
x5 ─────────→│ │
└─────────────┘
每个 Token 可以直接关注其他 Token。
例如:
The cat sat on the mat because it was tired.
模型可以通过 Attention 直接建立:
it → cat
而不需要像 RNN 一样依赖:
cat → ... → it
逐步传递。
25. RNN → LSTM → Attention → Transformer
从 AI 技术演进来看:
RNN
│
├── LSTM
│
└── GRU
│
↓
Attention
│
↓
Transformer
│
↓
LLM
这条技术路线非常重要。
可以把它理解成:
第一阶段:RNN
解决:
如何处理序列?
第二阶段:LSTM / GRU
解决:
如何记住长期信息?
第三阶段:Attention
解决:
当前信息应该重点关注过去的哪些信息?
第四阶段:Transformer
解决:
如何高效、并行地进行大规模序列建模?
第五阶段:LLM
进一步解决:
如何利用 Transformer 学习语言、知识、推理和复杂任务能力?
26. 从系统架构角度理解 RNN
作为软件工程师,可以把 RNN 看成:
Input Stream
↓
┌──────────────┐
│ State Machine│
│ │
│ state = h_t │
└──────────────┘
↓
Output
每次输入一个 Event:
event_t
↓
state transition
↓
new state
即:
h_t = F(h_(t-1), x_t)
这和:
Event Sourcing
Stream Processing
Stateful Processing
存在非常直观的概念联系。
例如 Kafka Stream:
Event1
Event2
Event3
Event4
↓
Stateful Processor
↓
Current State
RNN:
x1
x2
x3
x4
↓
RNN
↓
h4
区别在于:
Kafka Processor 的状态更新规则由程序员定义,而 RNN 的状态更新函数由神经网络通过训练学习出来。
27. 一个简单的 PyTorch RNN
下面是一个最基本的 RNN 模型:
import torch
import torch.nn as nn
class SimpleRNN(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super().__init__()
self.rnn = nn.RNN(
input_size=input_size,
hidden_size=hidden_size,
batch_first=True
)
self.fc = nn.Linear(
hidden_size,
output_size
)
def forward(self, x):
output, hidden = self.rnn(x)
last_hidden = hidden[-1]
return self.fc(last_hidden)
数据:
[batch_size, sequence_length, input_size]
例如:
x.shape
可能是:
[32, 50, 128]
含义:
32 = batch size
50 = sequence length
128 = feature dimension
28. LSTM PyTorch 实现
class LSTMModel(nn.Module):
def __init__(
self,
input_size,
hidden_size,
output_size
):
super().__init__()
self.lstm = nn.LSTM(
input_size=input_size,
hidden_size=hidden_size,
batch_first=True
)
self.fc = nn.Linear(
hidden_size,
output_size
)
def forward(self, x):
output, (hidden, cell) = self.lstm(x)
last_hidden = hidden[-1]
return self.fc(last_hidden)
这里:
hidden
代表:
h_t
而:
cell
代表:
C_t
这正对应 LSTM 的两个状态。
29. 实际工程中 RNN 的重要超参数
使用 RNN/LSTM/GRU 时,需要重点关注:
hidden_size
例如:
64
128
256
512
越大:
模型容量 ↑
计算成本 ↑
内存 ↑
num_layers
例如:
nn.LSTM(
input_size=128,
hidden_size=256,
num_layers=3
)
代表:
LSTM Layer 1
↓
LSTM Layer 2
↓
LSTM Layer 3
dropout
用于降低过拟合。
例如:
nn.LSTM(
input_size=128,
hidden_size=256,
num_layers=3,
dropout=0.2
)
bidirectional
nn.LSTM(
input_size=128,
hidden_size=256,
bidirectional=True
)
此时输出维度通常变为:
256 × 2 = 512
30. RNN 的主要优点
虽然 Transformer 已经成为主流,但 RNN 仍然有一些优势。
30.1 参数共享
同一个 RNN Cell 可以处理:
x1
x2
x3
...
xn
参数不随序列长度增长。
30.2 适合流式处理
RNN 可以逐个处理输入:
Event1 → State1
Event2 → State2
Event3 → State3
因此非常适合:
- Streaming
- Online Prediction
- Real-time Sensor
- Edge Computing
30.3 内存需求可以较低
不需要像某些 Transformer 训练场景那样显式处理整个序列的 Attention Matrix。
对于某些特殊的:
Streaming / Online
场景,RNN 仍然具有价值。
31. RNN 的主要缺点
31.1 长期依赖
普通 RNN:
Long Sequence
↓
Information Loss
31.2 梯度消失
Gradient
↓
Repeated Multiplication
↓
Very Small
↓
Learning Stops
31.3 梯度爆炸
Gradient
↓
Repeated Multiplication
↓
Very Large
↓
Training Instability
31.4 难以并行
h1 → h2 → h3 → h4
后一个时间步依赖前一个时间步。
因此:
GPU Parallelism
↓
受限
32. RNN 的现代价值
学习 RNN 不是为了在今天所有 AI 项目中直接使用 RNN。
真正重要的是理解它解决问题的方式。
RNN 教会我们三个非常重要的概念:
1. State
Past → State → Future
2. Sequence Modeling
x1, x2, ..., xn
不是独立数据,而是一个整体。
3. Attention 的动机
RNN:
过去的信息
↓
逐步压缩
↓
Hidden State
这个设计天然存在信息瓶颈。
Attention 的出现,本质上就是在解决:
为什么一定要把整个历史压缩到一个固定大小的 Hidden State?
Attention 让模型可以直接访问历史信息。
这是从 RNN 理解 Transformer 最重要的桥梁之一。
33. RNN、LSTM、Transformer 的认知模型
可以用一句话概括:
RNN:
我把过去压缩成一个状态。
LSTM:
我会决定哪些过去的信息应该保留。
Attention:
我可以直接查看过去的信息,并决定关注什么。
Transformer:
我可以并行地让大量 Token 相互建立关系。
LLM:
我在 Transformer 的基础上学习语言、知识、推理和复杂任务。
34. RNN 学习中的核心知识地图
建议把 RNN 的知识体系理解成:
RNN
│
┌────────────┼────────────┐
│ │ │
Forward State Output
│ │ │
↓ ↓ ↓
h_t h_(t-1) y_t
│
↓
BPTT
│
┌──────────┴──────────┐
↓ ↓
Gradient Vanishing Gradient Explosion
│ │
↓ ↓
LSTM Gradient Clipping
│
↓
GRU
│
↓
Attention
│
↓
Transformer
│
↓
LLM
这张知识地图实际上连接了:
Deep Learning
↓
Sequence Modeling
↓
RNN
↓
LSTM / GRU
↓
Attention
↓
Transformer
↓
Generative AI
↓
LLM
↓
Agent
35. 作为 AI 工程师,RNN 最应该掌握什么?
如果目标是进入现代 AI / LLM 工程,而不是专门做传统序列模型,那么 RNN 不需要停留在大量公式推导上。
建议重点掌握以下 8 个概念:
| 优先级 | 知识 | 重要性 |
|---|---|---|
| 1 | Hidden State | ⭐⭐⭐⭐⭐ |
| 2 | Sequence Modeling | ⭐⭐⭐⭐⭐ |
| 3 | BPTT | ⭐⭐⭐⭐ |
| 4 | Vanishing Gradient | ⭐⭐⭐⭐⭐ |
| 5 | LSTM | ⭐⭐⭐⭐⭐ |
| 6 | GRU | ⭐⭐⭐⭐ |
| 7 | Bidirectional RNN | ⭐⭐⭐ |
| 8 | RNN → Attention → Transformer | ⭐⭐⭐⭐⭐ |
其中最重要的是:
RNN 为什么需要 State?
↓
为什么长期依赖困难?
↓
为什么出现 LSTM?
↓
为什么又出现 Attention?
↓
为什么最终发展到 Transformer?
一旦理解了这条逻辑链,现代大模型架构会容易理解很多。
36. 总结
RNN 是深度学习历史上非常重要的一类序列模型。
它通过:
Current Input
+
Previous Hidden State
↓
RNN Cell
↓
Current Hidden State
建立了对序列数据的建模能力。
但普通 RNN 存在:
Long-Term Dependency
Gradient Vanishing
Gradient Explosion
Sequential Computation
等问题。
于是产生:
RNN
↓
LSTM / GRU
↓
Attention
↓
Transformer
↓
LLM
从今天 AI 技术发展的角度看,RNN 最大的价值已经不仅仅是“一个可以使用的神经网络”。
更重要的是:
RNN 是理解现代序列建模思想的一块基石。
如果真正理解:
Hidden State
Cell State
BPTT
Gradient Vanishing
LSTM Gate
GRU Gate
再进一步理解:
Attention
Self-Attention
Transformer
就能够形成一条非常完整的 AI 技术演进链。