一 LSTM基本概念

1 LSTM定义

        长短期记忆网络(Long Short-Term Memory,LSTM)是一种改进的循环神经网络(RNN)结构,由 Hochreiter 和 Schmidhuber 于 1997 年提出。它通过在网络中引入“门控机制”(Gating Mechanism)与“记忆单元”(Cell State),能够在序列数据中有选择地保留或遗忘信息,从而有效解决传统 RNN 在长序列训练中容易出现的梯度消失与梯度爆炸问题

        LSTM 的核心思想是让模型既能记住长期依赖的信息,又能对短期变化做出响应,因此被广泛应用于自然语言处理、时间序列预测、语音识别等需要捕捉长距离依赖关系的任务中。

2 传统RNN存在的问题

        循环神经网络(RNN)的核心思想是通过“循环结构”让前一时刻的隐藏状态 ht-1 参与当前时刻的计算,从而在时间维度上传递信息。这使得 RNN 理论上可以利用序列中的上下文信息,理解“前因后果”。然而在实际训练中,RNN 会遇到两个关键问题,具体如下所示。

2.1 梯度消失与梯度爆炸(Vanishing/Exploding Gradient)

        在反向传播过程中,梯度需要沿时间维度不断传递和相乘。当序列较长时,梯度会被反复缩小或放大,导致前面时间步的参数几乎得不到有效更新。结果是——模型只能记住“短期信息”,而“远处的信息”被遗忘。

2.2无法捕捉长距离依赖(Long-term Dependency)

        在短语句中,RNN 可以根据临近的上下文完成预测,比如 “the clouds are in the ?” 很容易预测出 “sky”;但在长句中,如 “I grew up in France ... I speak fluent ?”,预测 “French” 需要模型记住很久以前的“France”信息。普通 RNN 无法保持这种长时间跨度的记忆,从而失去语义关联。

        简而言之,RNN 善于记忆“近处”,却难以记住“远方”。这正是 LSTM 被提出的原因——通过更精细的“记忆控制机制”,解决 RNN 在长序列建模中的遗忘问题。

3 LSTM核心思想

        面对 RNN 中梯度消失和长期依赖无法捕捉的问题,LSTM(Long Short-Term Memory) 的核心创新在于:它在结构中引入了一个 “记忆单元(Cell State)”“门控机制(Gating Mechanism)”,让网络可以有选择地记住重要信息、遗忘无关信息,从而在长序列中保持稳定的梯度流。

3.1 Cell状态        

        普通 RNN 的隐藏状态 ht​ 既要负责短期的输出,又要传递长期的记忆,任务过于繁重。而 LSTM 将这两者分开隐藏状态 ht:负责当前时刻的输出;记忆单元 Ct:负责跨时间步的长期信息保存,它可以从上一时刻直接通到下一时刻

        这种设计让梯度可以沿着 Ct 这条“几乎无衰减的高速通道”直接传播,避免了传统 RNN 的梯度消失问题。

3.2 门

        如果 LSTM 只是原封不动地保存之前的记忆,那就没有太多价值。它还必须根据需要,能够增加新的记忆,同时擦除旧的无用记忆。LSTM 是通过一种叫作“门”的机制来控制怎么擦除旧记忆、写入新记忆的,下面我们逐步来介绍这种机制。

        如上图所示,可以用来控制信息是否能够通过。它是一个激活函数为 sigmoid 的层,
0表示阻止任何信息通过,1表示所有信息通过,而 0∼1之间的值表示部分通过。

3.2.1 遗忘门

        ft​ 叫做遗忘门(Forget Gate),表示上一个时间步传下来的记忆 Ct−1​ 中,哪些信息应该保留,哪些应该被遗忘​。遗忘门激活函数为:

f_t = \sigma(W_f [h_{t-1}, x_t] + b_f)

3.2.2 输入门

        输入门的作用是控制“当前输入 xt 和 前一时刻隐状态 ht−1”中提取出的新信息,有多少比例能够进入记忆单元 Ct。输入门由两个部分组成:输入门系数 it 与输入门候选值 C~t​。

(1)输入门系数

i_t = \sigma(W_i [h_{t-1}, x_t] + b_i)

(2)输入门候选值

\tilde{C}_t = \tanh(W_C [h_{t-1}, x_t] + b_C)

(3)输入门工作机制

i_t \odot \tilde{C}_t

        最终结果会被加入到 Cell 状态更新公式中:

C_t = f_t \odot C_{t-1} + i_t \odot \tilde{C}_t

3.2.3 输出门

        输出门决定了“记忆单元 Ct 中哪些信息需要被输出到隐藏状态 ht,即哪些内容可以被当前时间步传递到下一个时间步或外部网络。输出门由两部分组成:计算输出门激活值 ot、计算当前隐藏状态 ht。

(1)计算输出门激活值 ot

o_t = \sigma(W_o [h_{t-1}, x_t] + b_o)

(2)计算当前隐藏状态 ht

h_t = o_t \odot \tanh(C_t)

        总体而言,LSTM 通过遗忘门、输入门与输出门的协同控制,实现了对信息流的选择性记忆与抑制。这种“门控记忆机制”使得网络能够在时间序列中保留重要的上下文特征,并抑制无关或过时的内容,从而显著提升了长序列建模的稳定性和表达能力。

二 Pytorch实现

1 LSTM函数原型

torch.nn.LSTM(
    input_size, 
    hidden_size, 
    num_layers=1,
    bias=True, 
    batch_first=False, 
    dropout=0, 
    bidirectional=False
)

2 参数说明

  • input_size:输入特征的维度。

  • hidden_size:隐藏状态的维度,也是输出特征的维度。

  • num_layers(可选参数):LSTM 的层数(即堆叠的 LSTM 层数)。

    • 默认值为 1,表示只有一层 LSTM。

    • 如果设置为 2,则会堆叠 2 层 LSTM,每一层的输入是前一层的输出。

  • bias(可选参数):是否使用偏置项,默认值为 True

  • batch_first(可选参数):是否将输入和输出的第一个维度视为批量大小。

    • 默认值 False,输入数据的形状为 (seq_len, batch_size, input_size)

    • 如果为 True,输入和输出张量形状为 (batch_size, seq_len, feature_size)

    • 通常在处理序列数据时,batch_first=True 更符合常见的数据格式。

  • dropout(可选参数):在 LSTM 层之间的 dropout 比例。

    • 仅当有多层 LSTM (num_layers > 1) 时生效。

    • dropout 会在不同层之间随机“丢弃”部分神经元连接,用于防止过拟合。

  • bidirectional(可选参数):是否使用双向 LSTM,默认值为 False

    • 如果为 True,LSTM 会同时学习正向反向的序列信息,增强模型对上下文的理解。

    • 当使用双向 LSTM 时,输出张量的形状中 hidden_size 会变为 hidden_size * 2

3 LSTM的输入

LSTM 接受的输入是一个三维张量:

  • 如果 batch_first=False:输入形状为 (seq_len, batch_size, input_size)

  • 如果 batch_first=True:输入形状为 (batch_size, seq_len, input_size)

其中:

  • seq_len:序列的长度,即时间步数。

  • batch_size:每个批次的样本数。

  • input_size:每个时间步输入数据的特征维度。

⚠️ 若输入为二维数据:PyTorch 会自动把二维张量视为一个“序列”,而不是一个 “batch”。
也就是说,它默认你只有一个样本。这样效果会大打折扣,记得将二维数据修改为三维数据。

4 LSTM的输出

当我们通过 lstm(input_data) 进行前向传播时,LSTM 会返回两个输出:

1️⃣ output:LSTM 层的最终输出(所有时间步的输出)。
2️⃣ (h_n, c_n):LSTM 的隐藏状态和细胞状态,即上图中的 ht与 Ct​。


🔹 output

output 是 LSTM 对每个时间步输出的隐藏状态。

  • batch_first=False:输出形状为 (seq_len, batch_size, hidden_size),即每个时间步对应一个隐藏状态向量。

  • batch_first=True:输出形状为 (batch_size, seq_len, hidden_size)

示例:

  • 输入形状为 (5, 2, 10),hidden_size=20,则 output 的形状为 (5, 2, 20)

  • 每个时间步的输出表示输入数据经过 LSTM 后得到的隐藏状态。

🔹 h_n(隐藏状态)

h_n 是 LSTM 在最后一个时间步的隐藏状态,表示序列的最终输出(可用于后续任务,如分类等)。

  • h_n 的形状为 (num_layers, batch_size, hidden_size)

  • 若有多层 LSTM,h_n 会包含所有层的隐藏状态(最上层为最后的隐藏状态)。

示例:

  • num_layers=1h_n 形状为 (1, 2, 20)

  • num_layers=2h_n 形状为 (2, 2, 20),表示有两层 LSTM,每层的最后一个时间步的隐藏状态。

🔹 c_n(细胞状态)

c_n 是 LSTM 中细胞状态的最后一个时间步的输出,它保留了长期的记忆信息。

  • c_n 的形状与 h_n 相同:(num_layers, batch_size, hidden_size)

示例:

  • num_layers=1c_n 形状为 (1, 2, 20)

  • num_layers=2c_n 形状为 (2, 2, 20)

5 示例

import torch
import torch.nn as nn

# 定义一个单向 LSTM 模型
input_size = 10       # 输入特征维度
hidden_size = 20      # 隐藏层维度
num_layers = 2        # LSTM 层数
batch_size = 3        # 每批次样本数
seq_len = 5           # 序列长度(时间步数)

# 初始化 LSTM 模型
lstm = nn.LSTM(input_size, hidden_size, num_layers)

# 构造一个输入张量
input_tensor = torch.randn(seq_len, batch_size, input_size)

# 将输入传递给 LSTM 模型
output, (hn, cn) = lstm(input_tensor)

# 打印输出张量的形状
print("Output shape:", output.shape)      # 输出特征的形状
print("Hidden state shape:", hn.shape)    # 最后一个时间步的隐藏状态形状
print("Cell state shape:", cn.shape)      # 最后一个时间步的细胞状态形状

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐