LSTM
LSTM 用输入门、遗忘门、输出门和细胞状态缓解长距离依赖训练。
学习目标
- 手算一次 LSTM 的状态写入
- LSTM 的细胞状态和隐藏状态为什么不同?
- 说明:门控改善记忆路径,不能保证任意长度依赖都能学习,也不能省略变长处理。
为什么需要这个概念
LSTM 维护隐藏状态 h 与细胞状态 c,使用遗忘门 f、输入门 i、输出门 o 和候选内容 g 更新。门通常经 sigmoid,候选内容经 tanh。
学习前需要掌握
背景与问题
普通 RNN 不容易稳定地把信息传过很多时间步。LSTM 通过可控制的细胞状态通路,分别决定保留旧内容、写入新内容和暴露哪些内容。
概念定义
LSTM 维护隐藏状态 h 与细胞状态 c,使用遗忘门 f、输入门 i、输出门 o 和候选内容 g 更新。门通常经 sigmoid,候选内容经 tanh。
直观理解
细胞状态像长期笔记,遗忘门擦去一部分,输入门写入一部分,输出门决定本步向外展示多少。
核心原理
更新 c_t=f_t×c_prev+i_t×g_t,再计算 h_t=o_t×tanh(c_t)。门是 0 到 1 的连续向量,不是人工写好的二元开关。加法通路能减轻反复矩阵相乘造成的梯度问题,但遗忘门持续很小仍会快速抹去历史。
四组变换各自读取当前输入和前一隐藏状态,因此标准 LSTM 通常比相同 hidden size 的普通 RNN 有更多参数。细胞状态也不等于原始历史;它是由目标训练出来的压缩表示。
PyTorch 返回 output 和 (h_n,c_n)。多层或双向时,最终状态首轴包含层与方向;最后时间位置不等于所有方向的最终摘要。变长序列需要正确处理 padding,在线跨片段时还应明确状态携带与 detach。
数学表达
核心公式
LSTM 维护隐藏状态 h 与细胞状态 c,使用遗忘门 f、输入门 i、输出门 o 和候选内容 g 更新。门通常经 sigmoid,候选内容经 tanh。
变量含义
Nbatch sizeD/H特征或隐藏维度
计算步骤
- 1保留项为 0.5×2=1。
- 2新写入项为 0.25×0.8=0.2。
- 3c=1.2,h=0.75×tanh(1.2)。
代码对应位置
示例 1手算一次 LSTM 的状态写入的最小验证:使用完整构造输入核对手算一次 LSTM 的状态写入,输出只表示本例计算。
变量解释
| 变量 | 含义 |
|---|---|
N | batch size |
D/H | 特征或隐藏维度 |
完整数值示例
手算一次 LSTM 的状态写入
已知条件
- 上一细胞状态为 2
- f=0.5,i=0.25,g=0.8,o=0.75
计算步骤
- 保留项为 0.5×2=1。
- 新写入项为 0.25×0.8=0.2。
- c=1.2,h=0.75×tanh(1.2)。
计算结果
细胞状态为 1.2,隐藏输出约为 0.625241。
处理前后对比
- 门控改善记忆路径,不能保证任意长度依赖都能学习,也不能省略变长处理。
手算一次 LSTM 的状态写入
本例门值是人为给定,用于隔离更新公式,不是从真实网络拟合得到。c 可以超过 1,h 经 tanh 与输出门后仍被限制,这解释了两种状态为何不能互换。
若把遗忘门改为 0,旧细胞状态的直接贡献消失;若输入门为 0,则没有新内容写入。真实门向量由输入和历史动态计算,不会固定采用此处比例。
计算与实现步骤
- 保留项为 0.5×2=1。
- 新写入项为 0.25×0.8=0.2。
- c=1.2,h=0.75×tanh(1.2)。
代码实现
示例 1
手算一次 LSTM 的状态写入的最小验证
example_01.py用途:使用完整构造输入核对手算一次 LSTM 的状态写入,输出只表示本例计算。
import torch
c_prev = torch.tensor(2.)
f, i, g, o = [torch.tensor(v) for v in [0.5, 0.25, 0.8, 0.75]]
c = f * c_prev + i * g
h = o * torch.tanh(c)
print(f"cell={c.item():.6f} hidden={h.item():.6f}")代码解析
解析始终位于完整代码下方,并按实际代码段逐项对应。
输入数据与任务
使用完整构造输入核对手算一次 LSTM 的状态写入,输出只表示本例计算。
Step 1 · 1–6 行
导入当前步骤需要的数值计算、预处理、模型或评价工具。依赖集中写在代码开头,便于复现。
import torch
c_prev = torch.tensor(2.)
f, i, g, o = [torch.tensor(v) for v in [0.5, 0.25, 0.8, 0.75]]
c = f * c_prev + i * g
h = o * torch.tanh(c)
print(f"cell={c.item():.6f} hidden={h.item():.6f}")预期输出或运行结果
cell=1.200000 hidden=0.625241
常见错误 · 3 条
- 忘记 c_n
- output[:,-1] 取 padding
- 以为永不梯度消失
实际应用
- 需要较长上下文的序列基线
- 有状态在线时序预测
常见错误
- 忘记 c_n
- output[:,-1] 取 padding
- 以为永不梯度消失
常见问题
LSTM 的细胞状态和隐藏状态为什么不同?
细胞状态用于内部累加和保留信息,隐藏状态是经 tanh 与输出门暴露的表示;两者形状可能相同,但运算角色不同。
这个示例能说明什么边界?
门控改善记忆路径,不能保证任意长度依赖都能学习,也不能省略变长处理。
推荐学习资料
参考库不会生成虚假资源或无效外部链接。