2. 序列到序列模型基础:RNN、LSTM、GRU的原理与局限
说到Transformer,得先聊聊它的「前任」们。
序列到序列(Seq2Seq)这个任务,说白了就是「一段进去,一段出来」。翻译、语音识别、文本摘要,全是这类问题。Transformer之前,大家靠的是循环神经网络(RNN)家族。我今天带你过一遍这三个核心成员:原始RNN、LSTM、GRU。你得理解它们为什么被设计成这样,又为什么最终被Transformer取代。
2.1 原始RNN:最朴素的记忆体
RNN的想法很直觉:让网络有「记忆」。处理当前词时,看一眼前一个词留下的状态。
结构长这样:
- 输入:当前时刻的词向量 xₜ
- 隐藏状态:hₜ = tanh(Wₓ xₜ + Wₕ hₜ₋₁ + b)
- 输出:yₜ = softmax(Wₕ hₜ + bₒ)
简单吧?但简单背后藏着大问题。
核心公式(你记一下):
hₜ = tanh(Wₓ * xₜ + Wₕ * hₕ₋₁ + b)
yₜ = softmax(Wₕ * hₜ + bₒ)
举个例子。假设我们要翻译:
"I am from China, and I love eating dumplings."
当你生成"我来自中国"时,需要记住"China"在句首。RNN靠hₜ一路传递这个信息。如果句子短,够用。但句子一长——比如说100个词——早期信息早就被tanh压碎了。
2.2 梯度消失与梯度爆炸:RNN的致命伤
为什么会这样?
你想想看,RNN在时间步上展开后,就是一个超深的网络。反向传播时,梯度要一路往回传。链式法则一乘,如果激活函数是tanh或sigmoid,导数小于1,连乘几次就趋近于0。这就是梯度消失。
反过来,如果Wₕ的范数大于1,梯度会指数级增长,变成梯度爆炸。
避坑指南:
我在项目里遇到过,模型训练到一半loss突然变成NaN,十有八九是梯度爆炸。解决方案倒是简单——梯度裁剪(gradient clipping),设定一个阈值,超过就直接截断。但我曾经因为忘记加这个,白跑了两天实验。
梯度消失更隐蔽。模型能训练,loss也在降,但长距离依赖就是学不会。我做个机器翻译,50个词以内的还能看,超过100个词直接崩了——前面主语的信息根本传不到后面。
2.3 LSTM:加了三个「门」的升级版
长短期记忆网络(LSTM)是1997年提出的,但直到2014年左右才大规模用起来。它比RNN多了三个门控机制:
- 遗忘门:决定丢掉哪些旧信息。fₜ = σ(W[ xₜ, hₜ₋₁ ] + b)
- 输入门:决定写入哪些新信息。iₜ = σ(W[ xₜ, hₜ₋₁ ] + b)
- 输出门:决定输出哪些给下一时刻。oₜ = σ(W[ xₜ, hₜ₋₁ ] + b)
还有一个细胞状态(cell state)Cₜ,这是LSTM的核心。它像一条传送带,信息可以在上面直通,不受非线性挤压。门控机制控制哪些信息进、哪些信息出。
我个人的理解方式:
把细胞状态想象成一个记笔记的本子。遗忘门决定撕掉哪些页,输入门决定新写哪些内容,输出门决定这一时刻翻到哪一页给别人看。你看,是不是好记多了?
LSTM确实缓解了梯度消失问题,但代价是参数量翻了好几倍。一个LSTM单元有4组权重矩阵(遗忘、输入、输出、候选状态),训练速度远低于原始RNN。
2.4 GRU:轻量化的替代方案
门控循环单元(GRU)是2014年提出的,比LSTM晚。它把LSTM的三个门简化为两个:
- 更新门zₜ:合并了遗忘门和输入门的功能
- 重置门rₜ:控制历史信息对当前候选状态的影响
GRU没有单独的细胞状态,直接把隐藏状态hₜ当记忆体用。结构更简洁,参数量更少。
参数量对比(假设输入维度d=512,隐藏维度d=256):
原始RNN: 4 * d * d = 524,288
LSTM: 16 * d * d = 2,097,152
GRU: 12 * d * d = 1,572,864
GRU在参数量上比LSTM少了约25%,在很多任务上效果差不多。我在做文本生成项目时做过对比,GRU训练速度快了30%,BLEU分数只低了0.2个点。性价比很高。
2.5 三者的对比表格
我做了一张表,方便你对照选择:
| 模型 | 核心机制 | 参数量(相对) | 长距离依赖 | 训练速度 | 适用场景 |
|---|---|---|---|---|---|
| 原始RNN | 隐藏状态循环 | 低(1倍) | 差(20步以上几乎无效) | 快 | 短序列、简单任务 |
| LSTM | 门控+细胞状态 | 高(4倍) | 好(可记忆100步以上) | 慢 | 长序列、精度优先 |
| GRU | 门控+简化结构 | 中(3倍) | 较好(接近LSTM) | 中 | 工程落地、速度与效果平衡 |
经验之谈:
我踩过一个坑:做金融时序预测时,以为数据越长越准,直接用LSTM吃了2000个时间步。结果训练了三天,loss死活降不下去。后来才意识到,LSTM虽然能记长距离,但2000步的梯度路径太深,局部细节反而学不好。最后切成了滑动窗口+双向LSTM,效果才出来。别迷信长序列。
2.6 无法绕过的根本局限
RNN家族(包括LSTM和GRU)有三个硬伤,这也是Transformer能取而代之的原因:
- 串行计算:t时刻必须等t-1时刻算完,GPU并行能力被浪费。想想看,一个200词的句子要串行跑200步,而Transformer一步到位。
- 长距离依赖仍然不够好:LSTM/GRU虽然比RNN强,但当我需要记住第1个词和第100个词的关系时,信息早就被衰减或压缩了。Transformer的注意力机制可以直接看任意两个位置。
- 训练不稳定:梯度爆炸虽然能用裁剪解决,但超参数调起来很烦。我见过团队花一周调LSTM的学习率和梯度阈值,换成Transformer两天就收敛了。
下面这张图总结了它们的演进关系,你看一眼:
2.7 回头看:为什么需要Transformer?
有了前面的铺垫,现在你就能理解Transformer的设计动机了。
RNN/LSTM/GRU的核心问题是顺序依赖。你必须按时间步一个一个算,GPU的并行能力被浪费了。而且,不管你用多复杂的门控,信息在长距离传递中总会衰减。
Transformer的方案是:不要递归,用注意力机制。一次性看到整个序列,任意两个位置直接建立联系。这既解决了并行问题,也解决了长距离依赖问题。
但别急着否定RNN家族。我在实际项目中发现,对于短序列(比如<20个词)、实时推理场景(计算资源受限)、或者与CNN结合的特征提取,LSTM和GRU仍然有它们的用武之地。而且,Transformer的很多思想(位置编码、多头注意力)是在解决RNN的问题时被逼出来的。理解这些「前任」,你才能把「现任」用得更好。
小结:
记住三个关键点:
- RNN因梯度消失无法处理长序列
- LSTM用门控缓解了问题,但参数量大、训练慢
- GRU是轻量化替代,参数少、效果接近
它们的共同硬伤是串行计算和长距离依赖不完美,这就是Transformer诞生的直接原因。