跳转至

RNN

循环神经网络(Recurrent Neural Network, RNN)是一类专门用于处理序列数据(Sequential Data)的神经网络。

RNN Explainer

下面这个 RNN Explainer 交互式可视化项目适合拿来直观看 RNN、LSTM、GRU 的结构和序列建模过程:

RNN Explainer

RNN 的核心思想

  • 输入不是孤立样本,而是按时间顺序展开的序列
  • 当前时刻的输出不仅依赖当前输入,也依赖历史信息
  • 同一组参数会在不同时间步重复使用

背景

很多任务天然带有顺序关系,样本之间不是独立的:

  • 文本中的词有上下文关系
  • 语音信号具有时间连续性
  • 时间序列数据依赖历史观测值
  • 用户行为序列往往与前面的动作相关

如果使用普通全连接网络,通常需要把整个序列一次性展开输入,这样会:

  • 丢失顺序结构的表达优势
  • 参数量变大
  • 难以自然处理变长序列

RNN 的设计正是为了解决这类问题。

RNN


基本结构

RNN 的基本结构如下:

RNN

RNN 在每一个时间步都会接收:

  • 当前输入 \(x_t\)
  • 上一个时间步的隐藏状态 \(h_{t-1}\)

然后计算新的隐藏状态:

\[ h_t = f(U x_t + W h_{t-1} + b) \]

再基于隐藏状态产生输出:

\[ y_t = V h_t + c \]

其中:

  • \(x_t\) 表示第 \(t\) 个时间步的输入
  • \(h_t\) 表示第 \(t\) 个时间步的隐藏状态
  • \(y_t\) 表示第 \(t\) 个时间步的输出
  • \(U\) 表示输入到隐藏状态的权重
  • \(W\) 表示上一时刻隐藏状态到当前隐藏状态的权重
  • \(V\) 表示隐藏状态到输出的权重
  • \(f\) 表示非线性激活函数,比如 tanh

时间展开

RNN 通常会在概念上沿时间轴展开来看。

RNN

虽然看起来像很多层串联起来,但这些时间步共享同一组参数:

  • 第 1 个时间步使用参数 \(W, U, V\)
  • 第 2 个时间步仍然使用参数 \(W, U, V\)
  • 后续所有时间步都复用同一组参数

这就是 RNN 参数量不会随着序列长度线性增长的重要原因。

共享参数的意义

  • 模型可以处理不同长度的序列
  • 参数规模相对可控
  • 学到的是“序列模式”,而不是某个固定位置的规则

常见输入输出形式

RNN 可以根据任务设计成不同的输入输出结构:

类型 示例任务 说明
One-to-One 图像分类 普通前馈网络更常见
One-to-Many 图像描述生成 一个输入生成一个序列
Many-to-One 情感分类 一个序列输出一个结果
Many-to-Many 机器翻译、序列标注 输入序列对应输出序列

训练方式

RNN 的训练通常使用 通过时间的反向传播(Backpropagation Through Time, BPTT)。

它本质上是把时间展开后的 RNN 看成一个更深的网络,然后沿时间方向做反向传播。

主要步骤如下:

  1. 按时间顺序做前向计算,得到每个时间步的隐藏状态和输出。
  2. 计算总损失,损失可能来自最后一步,也可能来自每一步。
  3. 沿时间反向传播梯度,更新共享参数。

语言模型里的训练

例如输入序列是 ["我", "喜欢", "深度学习"],模型可以在每一步预测“下一个词”,然后把多个时间步的损失累加起来一起训练。


梯度消失与梯度爆炸

RNN 最经典的问题是:当序列很长时,梯度需要跨很多时间步传播,容易出现:

  • 梯度消失(Vanishing Gradient):前面时间步的信息很难传到后面
  • 梯度爆炸(Exploding Gradient):梯度值变得非常大,训练不稳定

这会导致基础 RNN 很难学习长期依赖(Long-Term Dependency)。

什么是长期依赖

指的是当前预测需要依赖很久之前的信息。

例如句子:

The keys to the cabinet ... are on the table.

模型在预测 are 时,需要记住前面真正的主语 keys,而不是被中间一串词干扰。

常见缓解方式

  • 使用更稳定的门控结构,比如 LSTM、GRU
  • 做梯度裁剪(Gradient Clipping)
  • 合理初始化参数
  • 使用较短的截断反向传播(Truncated BPTT)

LSTM

LSTM(Long Short-Term Memory)是 RNN 的重要改进版本,专门用于缓解长期依赖问题。

LSTM

它引入了细胞状态(Cell State)和多个门(Gate)来控制信息流动:

  • 遗忘门(Forget Gate):决定丢掉哪些旧信息
  • 输入门(Input Gate):决定写入哪些新信息
  • 输出门(Output Gate):决定输出哪些信息

遗忘门

遗忘门(Forget Gate)的作用是:决定上一时刻的细胞状态 \(C_{t-1}\) 中,哪些信息应该保留,哪些信息应该丢弃。

Forget Gate

可以把它理解成一个“筛子”:

  • 接近 1 的部分表示尽量保留
  • 接近 0 的部分表示尽量忘掉

这一步很重要,因为不是所有历史信息都对当前任务有用。LSTM 先通过遗忘门清理掉无关或过时的信息,再进行后续更新。


输入门

输入门(Input Gate)的作用是:决定当前输入 \(x_t\) 和当前候选记忆中,有哪些新信息值得写入细胞状态。

Input Gate

它本质上回答的是:

  • 当前这一刻来了哪些新内容
  • 这些新内容里哪些值得记住

因此,输入门负责“写入”过程。它让 LSTM 不会把每一步的输入都无条件塞进记忆里,而是有选择地更新状态。


输出门

输出门(Output Gate)的作用是:决定当前细胞状态中,哪些信息应该暴露为当前时刻的隐藏状态 \(h_t\),并传递给下一层或下一时间步。

Output Gate

也就是说:

  • 细胞状态更像是内部长期记忆
  • 隐藏状态更像是当前时刻对外可见的表达

输出门控制“记住的东西里,哪些现在拿出来用”。这让 LSTM 可以保留长期信息,同时只输出当前真正需要的部分。

因此 LSTM 在很多长序列任务上比基础 RNN 更稳定。


GRU

GRU(Gated Recurrent Unit)也是常见的门控循环单元,可以看作是 LSTM 的简化版本。

GRU

它通常包含:

  • 更新门(Update Gate)
  • 重置门(Reset Gate)

相较于 LSTM:

  • 结构更简单
  • 参数更少
  • 训练速度通常更快

在不少任务上,GRU 可以用更低成本达到接近 LSTM 的效果。


RNN、LSTM、GRU 对比

RNN、LSTM、GRU 对比

模型 特点 优势 局限
RNN 基础循环结构 简单直观 难处理长依赖
LSTM 带细胞状态和多个门 长序列建模更强 参数较多,计算更重
GRU 简化门控结构 更轻量,训练更快 表达能力依任务而定

优点与局限

  • RNN 的优点


    • 天然适合处理序列数据
    • 可以建模时间依赖关系
    • 参数在时间步之间共享,参数量相对可控
    • 是理解序列建模的基础
  • RNN 的局限


    • 难以捕捉长距离依赖
    • 训练难并行,时间步之间存在依赖
    • 长序列训练容易不稳定
    • 在很多任务上已被 Transformer 超越

适用场景

RNN 及其变体常见于以下任务:

  • 语言模型
  • 文本分类
  • 序列标注
  • 语音识别
  • 时间序列预测
  • 日志或用户行为序列建模