RNN

Recurrent Neural Network 循环神经网络

RNN 通过隐藏状态的循环连接实现对序列数据的建模,使网络具备"记忆"能力,能够捕捉时间步之间的依赖关系。 属于深度学习中处理变长序列数据的基础架构,是 LSTM、GRU 及现代序列模型的理论起点。

核心思想:隐状态的循环传递

与前馈神经网络不同,RNN 在隐藏层中引入循环连接:每个时间步的隐藏状态不仅依赖当前输入,还依赖前一时间步的隐藏状态。这使得网络能够将历史信息编码到隐状态中,实现对序列上下文的建模。

ht=fW(ht1,xt)

其中 ht 是时间步 t 的隐藏状态,xt 是当前输入,fW 是参数共享的状态转移函数。

数学公式

隐藏状态更新:

ht=tanh(Wxhxt+Whhht1+bh)

输出计算:

yt=g(Whyht+by)

其中:

参数共享

RNN 的关键特性是权重在所有时间步上共享Wxh,Whh,Why 不随 t 变化)。这使得网络可以处理任意长度的序列,且参数量与序列长度无关。

训练:BPTT

RNN 使用时间反向传播 (Backpropagation Through Time, BPTT) 进行训练。将 RNN 沿时间轴展开后,等价于一个深度前馈网络,然后应用标准的反向传播算法计算梯度。

对于损失函数 L=t=1TLt,参数梯度涉及沿时间步的链式求导:

LWhh=t=1Tk=1tLtht(j=k+1thjhj1)hkWhh

梯度问题

梯度消失与梯度爆炸

由于 BPTT 中梯度需要经过多个时间步的连乘 hjhj1,当序列较长时:

  • Whh 的谱范数 <1:梯度指数衰减 → 梯度消失,无法学习长距离依赖
  • Whh 的谱范数 >1:梯度指数增长 → 梯度爆炸,训练不稳定

缓解策略:

问题 解决方案 说明
梯度爆炸 梯度裁剪 (Gradient Clipping) 当梯度范数超过阈值时进行缩放
梯度消失 门控机制 (LSTM/GRU) 通过门控制信息流,维持长距离梯度
梯度消失 残差连接 提供梯度的"捷径"
梯度消失 正交初始化 使 Whh 初始化为正交矩阵,谱范数为 1

主要变种

LSTM (Long Short-Term Memory)

LSTM 引入细胞状态 ct 和三个门控机制来解决长距离依赖问题:

ft=σ(Wf[ht1,xt]+bf)(遗忘门)it=σ(Wi[ht1,xt]+bi)(输入门)c~t=tanh(Wc[ht1,xt]+bc)(候选状态)ct=ftct1+itc~t(细胞状态更新)ot=σ(Wo[ht1,xt]+bo)(输出门)ht=ottanh(ct)(隐藏状态)

细胞状态 ct 通过线性的自循环路径传递,梯度可以几乎无衰减地流过多个时间步。

GRU (Gated Recurrent Unit)

GRU 是 LSTM 的简化版本,将遗忘门和输入门合并为更新门,参数更少:

zt=σ(Wz[ht1,xt])(更新门)rt=σ(Wr[ht1,xt])(重置门)h~t=tanh(W[rtht1,xt])(候选状态)ht=(1zt)ht1+zth~t(状态更新)

RNN 变种架构对比

特性 Vanilla RNN LSTM GRU
参数量 O(n2) O(4n2) O(3n2)
长距离依赖
门控机制 3 个门 2 个门
训练速度 中等
适用场景 短序列 长序列、复杂任务 数据量较小的任务

序列建模模式

RNN 支持多种输入-输出模式:

PyTorch 示例

python
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, hidden_size, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)

    def forward(self, x, h0=None):
        # x: (batch, seq_len, input_size)
        out, hn = self.rnn(x, h0)
        # 取最后一个时间步的输出用于分类
        out = self.fc(out[:, -1, :])
        return out

# 使用 LSTM 替代
class LSTMModel(nn.Module):
    def __init__(self, input_size, hidden_size, output_size, num_layers=2):
        super().__init__()
        self.lstm = nn.LSTM(input_size, hidden_size,
                           num_layers=num_layers, batch_first=True,
                           dropout=0.2)
        self.fc = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        out, (hn, cn) = self.lstm(x)
        return self.fc(out[:, -1, :])

局限与后续发展

发展脉络

Vanilla RNN → LSTM (1997) → GRU (2014) → Attention 机制 → Transformer (2017) → 大语言模型


神经网络 | 机器学习 | 深度学习 | CNN