人工智能之核心技术 深度学习 第四章 循环神经网络(RNN)与序列模型

14 阅读3分钟

人工智能之核心技术 深度学习

第四章 循环神经网络(RNN)与序列模型


前言:循环神经网络(RNN)与序列模型 —— 自然语言处理基础

如果说 CNN 是处理空间结构(如图像)的利器,那么 RNN(Recurrent Neural Network) 就是专为时间序列/顺序数据设计的深度学习模型。它在自然语言处理(NLP)、语音识别、时间序列预测等领域扮演着核心角色。


一、RNN 基础

1.1 结构与原理:建模时序依赖

人类理解语言时会“记住”上下文。例如:

“我今天吃了 ___。” → 听到“吃”,你会预期后面是“饭”、“苹果”等食物。

RNN 模拟这种记忆机制:将上一时刻的隐藏状态传递给下一时刻

核心公式:
ht=tanh(Whht1+Wxxt+bh)yt=Wyht+by\begin{aligned} h_t &= \tanh(W_h h_{t-1} + W_x x_t + b_h) \\ y_t &= W_y h_t + b_y \end{aligned}
  • xtx_t:t 时刻输入(如词向量)
  • hth_t:t 时刻隐藏状态(“记忆”)
  • yty_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

💡 关键思想参数共享!所有时间步使用同一组权重 Wh,WxW_h, W_x,使模型能处理任意长度序列。


1.2 RNN 的局限性

尽管 RNN 能建模短期依赖,但在实践中面临两大挑战:

问题原因后果
长期依赖问题信息需跨多个时间步传递远距离词无法有效关联(如“猫…它”)
梯度消失/爆炸反向传播时链式法则连乘:LWk=1thkhk1\frac{\partial \mathcal{L}}{\partial W} \propto \prod_{k=1}^t \frac{\partial h_k}{\partial h_{k-1}}- 梯度趋近 0 → 参数几乎不更新- 梯度爆炸 → 训练不稳定

📌 实验现象:标准 RNN 在序列长度 > 20 时几乎无法学习长期模式。


二、RNN 变体:解决长期依赖

2.1 LSTM(Long Short-Term Memory)

由 Hochreiter & Schmidhuber (1997) 提出,通过门控机制精确控制信息流动。

三大门控:
  1. 遗忘门(Forget Gate):决定丢弃多少旧记忆 ft=σ(Wf[ht1,xt]+bf)f_t = \sigma(W_f [h_{t-1}, x_t] + b_f)
  2. 输入门(Input Gate):决定存储多少新信息 it=σ(Wi[ht1,xt]+bi)i_t = \sigma(W_i [h_{t-1}, x_t] + b_i)
  3. 输出门(Output Gate):决定输出多少当前记忆 ot=σ(Wo[ht1,xt]+bo)o_t = \sigma(W_o [h_{t-1}, x_t] + b_o)
单元状态(Cell State):
  • 主信息流:Ct=ftCt1+itC~tC_t = f_t \odot C_{t-1} + i_t \odot \tilde{C}_t
  • 隐藏状态:ht=ottanh(Ct)h_t = o_t \odot \tanh(C_t)
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):控制保留多少旧状态
公式:
zt=σ(Wz[ht1,xt])rt=σ(Wr[ht1,xt])h~t=tanh(W[rtht1,xt])ht=(1zt)ht1+zth~t\begin{aligned} z_t &= \sigma(W_z [h_{t-1}, x_t]) \\ r_t &= \sigma(W_r [h_{t-1}, x_t]) \\ \tilde{h}_t &= \tanh(W [r_t \odot h_{t-1}, x_t]) \\ h_t &= (1 - z_t) \odot h_{t-1} + z_t \odot \tilde{h}_t \end{aligned}

优点:参数更少、训练更快;性能与 LSTM 相当 → 现代 NLP 常用


2.3 双向 RNN(Bi-RNN / Bi-LSTM)

标准 RNN 只能利用过去信息。但很多任务需要上下文双向信息,例如:

“他把__送到医院。” → 空格处可能是“病人”或“医生”,需看后文“送到医院”才能确定。

Bi-RNN 同时运行两个 RNN:

  • 前向 RNN:ht=RNNforward(x1,...,xt)\overrightarrow{h_t} = \text{RNN}_{\text{forward}}(x_1, ..., x_t)
  • 后向 RNN:ht=RNNbackward(xT,...,xt)\overleftarrow{h_t} = \text{RNN}_{\text{backward}}(x_T, ..., x_t)
  • 最终表示:ht=[ht;ht]h_t = [\overrightarrow{h_t}; \overleftarrow{h_t}]
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) P(w1,w2,...,wT)=t=1TP(wtw<t)P(w_1, w_2, ..., w_T) = \prod_{t=1}^T P(w_t | w_{<t})
  • 训练:Teacher Forcing(用真实历史词作为输入)
  • 推理:逐词生成(贪心搜索 / Beam Search)

3.3 机器翻译入门(Seq2Seq)

Sequence-to-Sequence(Seq2Seq) 架构:

  • 编码器(Encoder):Bi-LSTM 将源句压缩为上下文向量 cc
  • 解码器(Decoder):LSTM 根据 cc 和已生成词预测下一个词
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❌ 差
LSTM3 个门✅ 强
GRU2 个门✅ 强
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》