RNN、LSTM、GRU:大模型时代,为什么还要懂这三个老朋友
小刘檀木的大模型日记 · Day16 · RNN、LSTM、GRU-帮普通人把AI学进简历系列
Day16|RNN、LSTM、GRU:大模型时代,为什么还要懂这三个老朋友

前言:别急着把 RNN 扔进历史垃圾桶
先抛结论:如果你只会说 Transformer 很强,却说不清 RNN、LSTM、GRU 解决过什么问题,你对序列建模的理解大概率是空心的。
这话有点扎心,但很真实。
现在一聊 AI,大家张口闭口都是 attention、MoE、Agent、长上下文。RNN 像个从老项目里翻出来的类库,名字熟,没人想碰。
可我一路摸爬滚打下来,越来越觉得:老模型不是废铁。它们更像技术史里的路标,告诉你一个问题是怎么被一层一层拆开的。
今天这篇,我们不背公式,也不搞论文复读。就围绕一个问题讲清楚:
当输入是一条时间线,模型到底怎么记住过去?

PART 01:RNN 的直觉——每一步都带着上一秒的影子
先从最朴素的 RNN 讲起。
普通神经网络看输入,像看一张照片:这一刻给什么,它就算什么。可很多数据不是照片,是一段录像。
比如:
- - 用户今天、昨天、前天的点击序列
- - 一句话里第 1 个字、第 2 个字、第 3 个字
- - 传感器每秒上传一次的温度曲线
这些数据的关键不只在“当前值”,还在前后顺序。
RNN 的想法很简单:每一步都吃两个东西。
一个是当前输入 x_t,一个是上一时刻留下来的隐藏状态 h_{t-1}。然后它产出新的隐藏状态 h_t,继续传给下一步。
你可以把 h_t 理解成一句话:我读到现在为止,脑子里留下的摘要。

这就是 RNN 最迷人的地方:同一套参数,沿着时间一步一步复用。序列多长,它就展开多长。
上一个最小可运行代码,感受一下维度:
import torch
import torch.nn as nn
batch_size = 2
seq_len = 5
input_size = 3
hidden_size = 4
x = torch.randn(batch_size, seq_len, input_size)
rnn = nn.RNN(
input_size=input_size,
hidden_size=hidden_size,
batch_first=True,
)
output, h_n = rnn(x)
print(output.shape) # torch.Size([2, 5, 4])
print(h_n.shape) # torch.Size([1, 2, 4])
output 是每个时间步的隐藏状态,h_n 是最后一步的隐藏状态。
如果你做一个很短的序列任务,比如“最近 5 次点击预测下一次点击”,RNN 这个思路挺自然。
但问题也在这里。
RNN 把所有历史都压进一个隐藏状态里,就像让你把一整本书压缩成一张便利贴。前几页的重要信息,传着传着就淡了。
这就是经典的长期依赖问题。
更底层一点,是训练时的梯度消失 / 梯度爆炸。序列一长,梯度要穿过很多步反向传播,乘来乘去,要么小到几乎没信号,要么大到训练发疯。
所以 RNN 的短板不是“它完全不会记忆”,而是:
它能记住近处的影子,却很难稳稳抓住远处的因果。
PART 02:LSTM 的三扇门——让模型学会忘记和保留
LSTM 出场,就是为了解决 RNN 的这个记忆焦虑。
它做了一件很聪明的事:不再把所有记忆都塞进隐藏状态,而是额外开了一条“长期记忆高速路”,叫 cell state。
你可以把普通 RNN 想成一个人边走边背书,所有内容都靠脑子硬扛。
LSTM 则像带了一个笔记本:有些信息写进长期笔记,有些信息当场丢掉,有些信息只拿出来影响当前输出。
它靠三扇门完成这件事:
- - 遗忘门 forget gate:过去的信息,哪些该删掉?
- - 输入门 input gate:当前的新信息,哪些该写进去?
- - 输出门 output gate:长期记忆里,哪些该拿出来影响当前判断?

这三个门听起来玄,其实工程味很重。
做业务系统久了你就知道,信息管理最难的不是“多记”,而是该记的记住,该忘的忘掉。
比如做用户行为预测,用户三个月前买过一次键盘,这个信息可能还有用;但他 10 秒前误点了一个广告,可能就不该被长期记住。
LSTM 让模型自己学这个取舍。
同样用 PyTorch,换一行模型就能跑:
import torch
import torch.nn as nn
x = torch.randn(2, 5, 3)
lstm = nn.LSTM(
input_size=3,
hidden_size=4,
batch_first=True,
)
output, (h_n, c_n) = lstm(x)
print(output.shape) # torch.Size([2, 5, 4])
print(h_n.shape) # torch.Size([1, 2, 4])
print(c_n.shape) # torch.Size([1, 2, 4])
注意这里多了一个 c_n,它就是 LSTM 的 cell state。
这也是 LSTM 和普通 RNN 最关键的差别:隐藏状态负责当前表达,细胞状态负责长期记忆。
当然,LSTM 也不是免费午餐。门多了,参数也多,训练更慢,调参更烦。
但在 Transformer 统治世界之前,LSTM 长期是文本、语音、时间序列里的主力选手,不是因为大家怀旧,而是因为它确实把“长一点的记忆”这件事做得更稳。
PART 03:GRU 的取舍——少一扇门,快一点,够用很多场景
讲完 LSTM,再看 GRU 就很顺了。
GRU 可以理解成 LSTM 的轻量版。它觉得:三扇门是不是有点复杂?长期状态和隐藏状态是不是可以合并?
于是 GRU 只保留两扇门:
- - 更新门 update gate:过去的信息保留多少,新信息写入多少?
- - 重置门 reset gate:计算当前候选状态时,要不要忽略一部分过去?
它没有单独的 cell state,结构更简单,参数更少,训练通常也更快。
所以在很多工程场景里,GRU 是一个很务实的选择。
不是最豪华,但够用、快、成本低。
import torch
import torch.nn as nn
x = torch.randn(2, 5, 3)
gru = nn.GRU(
input_size=3,
hidden_size=4,
batch_first=True,
)
output, h_n = gru(x)
print(output.shape) # torch.Size([2, 5, 4])
print(h_n.shape) # torch.Size([1, 2, 4])
你看,GRU 的返回又回到了 output, h_n,没有额外的 c_n。
那项目里到底怎么选?
我给一个不玄学的版本:
- - 序列很短、逻辑简单:RNN 可以作为 baseline
- - 有较长依赖、数据量还可以:优先试 LSTM
- - 资源敏感、延迟敏感、小数据:GRU 常常更划算
- - 长文本理解、多轮复杂推理、大规模预训练:交给 Transformer

这也是很多人容易误解的一点。
Transformer 不是因为“会记忆”才强,而是因为它用 attention 让序列里的任意位置可以直接互相看见。RNN 家族是一步一步传话,Transformer 更像把全班同学同时拉进一个会议室。
传话有传话的成本优势,开会有开会的全局视野。
真正成熟的工程判断,不是“新的一定替代旧的”,而是知道每个工具的代价。
结尾:旧模型不是废铁,是地基
RNN、LSTM、GRU 这三个名字,今天看起来确实不够时髦。
但你把它们串起来,会看到一条非常清晰的技术演进线:
RNN 解决“序列怎么读”,LSTM 解决“长期怎么记”,GRU 解决“能不能更轻一点”。
这条线走通了,再回头看 Transformer 的 self-attention,你会更明白它为什么像一次范式跃迁。
大模型时代,旧模型不是废铁,而是地基。地基越稳,楼才敢盖得越高。
互动时间:
你第一次接触 RNN / LSTM / GRU 是在 NLP、时间序列,还是推荐系统里?评论区聊聊,我想看看大家踩过哪些“序列建模”的坑。
下一篇预告:Day17 准备讲 Self-Attention 和 Transformer——为什么它能绕开 RNN 的长距离传话问题,又为什么会成为大模型的骨架。关注「小刘檀木」,别错过。
— END —
小刘檀木 · 帮普通人把 AI 学进简历
更多推荐




所有评论(0)