序列转导模型演进史:从RNN到Transformer的关键一战

发布时间:2026/11/3 3:48:10
序列转导模型演进史:从RNN到Transformer的关键一战

为什么我说"transformmr"才是那个时代的记忆

先澄清一个拼写问题。很多人搜索"transformmr"以为是 Transformer 的笔误,其实严格说这倒也不算太离谱——在我印象里,2017 年前后那批最早接触 Attention 架构的同行,确实有人把它写成过 transformmr 或者 transormer,因为当时的输入法联想优先级还没跟上学术界换代的速度。序列转导模型这个词现在听起来学术味很重,但在那个节点,它就是机器翻译、文本摘要、语音识别这些任务背后的统称:输入一个序列,输出另一个序列,模型要学的是一整套"形状转换"的规则。

这篇文章不是来写 Transformer 论文复现的,我想写的是它之前那段被很多人忽略的"前戏"。如果你刚接触这一领域,想搞清楚为什么 RNN 会被干掉、注意力机制是怎么一步步从"辅助工具"变成"核心算子的",那你算来对地方了。如果你已经做了几年模型训练,想回头复盘一下架构演进里那些关键决策的底层逻辑,这篇文章也值得你花十分钟翻一翻。序列转导模型的演进史,本质上就是一部"计算瓶颈如何倒逼架构创新"的工程史。

1. 序列转导任务到底难在哪里

1.1 什么是序列转导,它和普通分类任务差多少

序列转导的数学定义不复杂:给定输入序列 x_1, x_2, ..., x_m,模型需要输出另一条序列 y_1, y_2, ..., y_n,其中 m 和 n 不需要相等。机器翻译是教科书级例子——中文"你好,世界"翻译成英文"Hello, world",输入长度是 4,输出长度是 2,长度直接变了。文本摘要也是:一篇 5000 字的新闻要压成 200 字的摘要。语音识别也是:一段声学特征序列要变成一段文字序列。

这看起来不过是个"序列进、序列出"的活,但它和普通分类任务有本质区别。分类任务里,你只需要把整个输入压缩成一个固定维度的向量,然后在这个向量上做一个 softmax。转导任务里,你不仅要理解输入序列的整体语义,还要决定输出序列的每一个位置"该对齐输入哪个部分"。这个对齐问题,在传统机器学习时代叫"词对齐",在神经网络时代叫"注意力"。

我做序列标注项目那会儿,一开始最不适应的地方就是损失函数的构造。分类任务一个样本一个 label,简单粗暴。转导任务里你面对的是一个序列的联合概率 P(y_1, y_2, ..., y_n | x_1, ..., x_m),要拆成 P(y_1) * P(y_2|y_1) * ... 的乘积形式才能做极大似然估计。这就意味着模型天然是自回归的——每一步都要基于之前已经生成的内容来预测下一个 token。

1.2 三个绕不开的硬骨头

从事后来看,序列转导模型的历史演进,几乎就是围绕三个硬骨头展开的。

第一个是长距离依赖。自然语言里的长距离依赖非常普遍:"The dog that ate the cake and then went outside, ... ran away" 的动词 ran 要和单数主语 dog 保持一致,中间隔着十几个词。经典 RNN 理论上能记住任意长度的信息,但实际上梯度在反向传播时会被反复相乘,要么爆炸要么消失。这就是后来 LSTM 门控机制要解决的问题,但门控也只是缓兵之计。

第二个是对齐问题。输入和输出序列之间不存在天然的一一对应关系。中文的"我"在英文里可能是"I",但中文的"了"在英文里可能根本不需要翻译,英文的"have done"里的 have 又对应中文的"已经"。这种松散的对应关系,早期靠统计模型里的对齐表硬算,后来靠注意力机制动态计算。

第三个是训练效率。RNN 天然是顺序计算的——t 时刻的隐状态必须等 t-1 时刻算完才能算。GPU 的并行能力在 RNN 面前使不上劲。同样一批数据,卷积网络可以一口气把整个矩阵算完,RNN 只能一步一步来。这个效率差距在大模型时代是致命的。

记住这三个词:长距离依赖、对齐、并行化。接下来的所有架构演进,本质上都是在这三个维度上做权衡。

2. 前戏第一幕:从统计学到神经网络的改朝换代

2.1 统计机器翻译的黄金时代与隐忧

在神经机器翻译之前,主流方案是统计机器翻译(SMT),行业里管它叫 phrase-based SMT。这套系统的核心是把翻译拆成几个独立模块:词对齐模型负责搞清楚两种语言的词对应关系,短语表负责存储常见的多词对译单位,调序模型负责处理语序差异,语言模型负责让输出看起来更像人话。

这套架构统治了机器翻译领域整整十几年,效果也确实能用。我记得 2014 年前后跑过一个英德翻译系统,BLEU 值大概在 20 出头,对日常短句表现还行。但它的瓶颈非常明显:整个流程是多个子系统拼起来的,每个模块独立优化,最后拼在一起的时候错位问题一大堆。短语表是有限集合,遇到没见过的表达就抓瞎。调序规则靠人工设计,面对复杂语序变化经常翻车。

更本质的问题是,SMT 的设计哲学是基于"局部统计"的——两个词是否经常共现、某个短语在语料库中出现多少次。它缺乏对整体语义的表达能力。而神经网络在这一点上有天然优势:通过多层非线性变换,它能把整个句子的语义压缩成一个稠密向量。这个向量不是某个词或某个短语的简单计数,而是分布式表示,理论上可以捕捉更加抽象的语义关系。

2.2 RNN 序列到序列框架的横空出世

2014 年,Sutskever 等人的经典论文 Sequence to Sequence Learning with Neural Networks 出现了,这是真正意义上的序列转导模型神经网络化的里程碑。思路非常简单:用一个 LSTM 把整个输入序列编码成一个固定长度的向量(这个向量被称为 encoder 的最后一层隐状态),再用另一个 LSTM 从这个向量出发,逐步解码出输出序列。

当时的做法是经典的 encoder-decoder 架构。编码器和解码器各是一个多层 LSTM,编码器把输入句子读完,把最终隐状态传给解码器作为初始状态。解码器每走一步,既是预测输出 token,又是为下一步生成提供条件信息。

这个框架的问题也明显:那个固定长度的向量是信息瓶颈。输入句子越长,需要塞进这个向量里的信息就越多,但向量的容量是固定的。实验结果也证明了这一点:句子长度超过某个阈值后,模型性能快速下降。我记得当时试过把一篇 300 词的新闻压缩成 512 维向量再让解码器还原,还原出来的内容基本只能保留大意,细节全部丢失。

2.3 LSTM 与 GRU:补丁打得再好也还是补丁

RNN 的梯度消失问题催生了 LSTM 和 GRU 两代门控模型。LSTM 的核心思路是引入一个独立的细胞状态 c_t,通过遗忘门、输入门、输出门三个门控结构来控制信息的写入、保留和读取。梯度可以沿着细胞状态的"高速公路"一路畅通地反向传播,因此长距离依赖的建模能力比原始 RNN 提升了一大截。

GRU 是 Cho 等人 2014 年提出的简化版本,把 LSTM 的三个门压缩成了重置门和更新门,参数更少,训练更快,在很多任务上和 LSTM 打个平手。我和很多同行交流过,大家普遍的感受是:在小数据集上 GRU 表现更稳,在大数据集上 LSTM 的上限略高。但这个差距远没有到架构性的程度。

不过,门控机制本质上还是补丁工程。它缓解了梯度问题,但 RNN 的顺序计算特性一点没变。你仍然必须一个 token 一个 token 地处理输入序列,GPU 的并行能力照样被浪费。而且 LSTM 的参数量比 RNN 多了四倍,训练成本更高。当时我就隐约感觉到,这条路是走不长的——补丁打得再好,底子里的顺序依赖问题没解决。

3. 前戏第二幕:注意力机制是怎么登场的

3.1 从"固定向量"到"动态寻址"的思维飞跃

注意力机制不是 Transformer 发明的,这一点经常被混淆。它最早出现在机器翻译领域,是为了解决那个"信息瓶颈"问题。

2015 年,Bahdanau 等人的论文 Neural Machine Translation by Jointly Learning to Align and Translate 提出了注意力机制。核心思路很直白:解码器在生成第 i 个 token 的时候,不要只盯住编码器最后一刻的那个固定向量,而是回头去看编码器的每一个时间步隐状态,计算一个加权和作为"上下文向量"。这个加权和不是均匀分布的,词的权重取决于当前解码位置和该词之间的相关程度——相关程度高的被重点关注,不相关的就靠边站。

你可以把注意力理解为一种"动态寻址":不要把所有信息都打包放进一个固定容器里,而是给每个存储位置打上标签,需要什么信息的时候按标签去取。这个思想后来成了 Transformer 的核心哲学——Attention Is All You Need 这个标题,说的就是这个意思。

3.2 Bahdanau Attention 与 Luong Attention

注意力机制本身也有版本迭代。Bahdanau 那版用的是加性注意力(additive attention),即通过一个两层前馈网络计算对齐分数 e_ij = v^T tanh(W_1 h_j + W_2 s_{i-1})。这个形式通用性强,但计算量偏大,因为要过一个小型 MLP。

2015 年晚些时候,Luong 等人提出了简化方案:直接用点积或者带缩放的点积来计算对齐分数。点积注意力 e_ij = h_j^T s_{i-1},计算简单、速度快,而且效果还更好。后来 Transformer 里用的缩放点积注意力 QK^T / sqrt(d_k),就是从这个思路上发展而来的——加一个 sqrt(d_k) 缩放是为了防止点积结果随维度增大而方差爆炸。

还有个重要的设计区别是注意力信息的使用位置。Bahdanau 版本是把上下文向量和当前解码器输入拼起来一起送入循环单元,叫 input feeding;Luong 版本则把注意力上下文用在预测 output 之前那一层。这个细节在实操中影响不小,我当时在自己的翻译模型里测试过两种风格,Luong 式的收敛更快,但 Bahdanau 式最终的 BLEU 略高一点点。后来我反思了一下,这个差异本质上不是注意力机制本身的问题,而是信息注入位置导致的优化路径不同。

3.3 注意力机制埋下的"去 RNN 化"伏笔

注意力机制出现之后,整个领域的面貌开始悄悄改变。最早大家只是把注意力当作 RNN 编解码器的一个增强模块,用来解决固定向量的瓶颈。但后来逐渐有人在想一个问题:既然解码器的每一步都可以"直接去输入序列里挑选相关信息",那为什么还需要循环神经网络一步步传递信息呢?每一步都跟所有输入位置直接建立连接,这不就是把长距离依赖问题一次性解决了吗?

这个想法是 Transformer 的直接思想来源。自注意力机制其实就是对每个序列元素同时计算其与所有其他元素的关联强度,一步到位,不需要循环层来"接力传递"信息。这也是为什么 Transformer 能把序列建模长度从 RNN 时代的上百 token 直接推到上千甚至上万——路径长度从 O(seq_len) 变成了 O(1)。

当时圈子里讨论这个想法的人不少,但大多数人停留在"理论上可以"的阶段。真正把这条路走通并展示出压倒性效果的是 2017 年那篇 Attention Is All You Need。

4. 前戏高潮:CNN 与并行化的推波助澜

4.1 卷积序列到序列:被低估的先行者

在 Transformer 之前,还有一条被很多人低估的技术路线:卷积序列到序列(ConvS2S),来自 Facebook AI Research 在 2017 年发表的 Convolutional Sequence to Sequence Learning。这个模型用多层卷积网络替代 RNN,每个卷积层能同时处理输入序列的所有位置,天然具备并行性。它通过增加卷积层数来扩大感受野,从而建模长距离依赖。

ConvS2S 在 WMT'14 英德翻译任务上取得了当时最优的成绩,BLEU 超过了同期 LSTM 基线的表现。它还引入了一个简洁有效的创新——非因果卷积的 mask 机制,解码器预测下一个 token 时只能看到当前位置之前的输出,防止未来信息泄漏。

说实话,ConvS2S 的核心设计——堆叠层数扩大感受野、并行计算所有位置——已经和 Transformer 非常接近了。但它有个关键短板:经过 L 层卷积之后,两个位置之间的有效路径长度仍然和它们之间的距离成正相关,距离越远,信息传递路径越长。Transformer 的自注意力则完全打破了这一点,无论两个位置隔多远,都只需要一步计算就能直接建立关联。

4.2 GPU 时代对"并行训练"的刚性需求

2016 到 2017 年那段时间,深度学习的工程环境发生了两个重要变化。第一,GPU 的算力在快速提升,但 RNN 的顺序计算根本吃不到这波红利——你在一张 V100 上训练一个 LSTM 和在一张 K80 上训练,加速比远低于卷积网络。第二,训练数据的规模在快速增长,模型动不动上亿参数,训练一次要跑几周,工程师们对训练效率的敏感度空前高涨。

这时候出现了一个很有意思的现象:很多实验室开始考虑"如何让序列模型也能吃满 GPU"。一种做法是把一个 batch 内的多个序列并行处理,但序列内部仍然顺序计算。另一种做法是直接把序列内部的顺序计算也并行化,ConvS2S 和 Transformer 走的就是这条路。后来大家在技术复盘的时候都承认,LSTM 的表现其实并不差,但训练速度注定它无法走向大规模、大数据量的时代——这不是效果的败局,是效率的败局。

4.3 自注意力:一步到位的全局依赖建模

自注意力(Self-Attention)是 Transformer 的核心组件,但它的逻辑根源其实是对 RNN 和 CNN 两种方案的"扬弃"。RNN 通过循环连接传递信息,路径太长;CNN 通过卷积核堆叠扩大感受野,路径跟距离有关;自注意力则通过直接计算任意两个位置之间的关联权重来建模依赖。

用生活类比来解释:RNN 传递信息就像传话游戏,第一个人说的话要经过 N 个人口头传递才能到达最后一个人,中间信息容易失真;CNN 像是每次只跟周围的邻居交流,想跟远处的邻居说话就得找中间人层层转达;自注意力则像是开了一场全体会议,任何两个人都可以直接对话,不需要中间人传话。Transformer 选择自注意力这件事,本质上是做了一个极端的假设:所有位置之间的依赖关系同等重要,与其费劲设计传递链路,不如让模型自己决定该关注谁。

事实证明,这个"极端假设"是对的。今日之后,序列转导模型正式进入 Transformer 时代,前面那些"前戏"里探索过的方向——门控循环、卷积堆叠、注意力增强——被整合成了一套更简洁、更强大、更可扩展的统一框架。

5. 正式登场:Transformer 的架构拆解与前戏收尾

5.1 Transformer 从"前戏"里继承了什么

很多人觉得 Transformer 是平地起高楼,其实它是把之前所有方向的经验做了一次系统性整合。从 Bahdanau 那里,它继承了注意力机制;从 Luong 那里,继承了缩放点积这种高效实现;从 ConvS2S 那里,继承了并行计算所有位置的基本思路;从 seq2seq 框架那里,继承了 encoder-decoder 的整体结构。

Transformer 的贡献在于三点:第一,把注意力机制从辅助模块提升为唯一核心算子,彻底弃用循环和卷积;第二,提出了多头注意力(Multi-Head Attention),让模型可以在不同表示子空间里并行捕捉不同类型的关联关系;第三,提出了位置编码(Positional Encoding),用数学方式把序列的顺序信息注入模型,弥补自注意力本身"不考虑位置"的缺陷。

5.2 快速拆解:多头注意力、位置编码与前馈网络

Transformer 的基本单元是一层多头注意力加一层前馈网络,外面套一个残差连接和 LayerNorm。多头注意力做的事情,是把输入向量拆成 Q、K、V 三份,各自通过线性变换映射到多个子空间,然后在每个子空间里独立计算注意力,最后合并。用公式表达就是:

import torch import torch.nn.functional as F def scaled_dot_product_attention(Q, K, V, mask=None): d_k = Q.size(-1) scores = torch.matmul(Q, K.transpose(-2, -1)) / (d_k ** 0.5) if mask is not None: scores = scores.masked_fill(mask == 0, -1e9) weights = F.softmax(scores, dim=-1) return torch.matmul(weights, V)

这个缩放因子 1/sqrt(d_k) 是有讲究的。d_k 越大,QK^T 的方差就越大,softmax 分布就越容易变成 one-hot,梯度会变得非常平缓,不利于训练。除以 sqrt(d_k) 是为了把方差拉回 1 附近,保持 softmax 的梯度活跃。

多头注意力的价值在于表达能力的多样性。一个头可能专注意合关系,另一个头可能关注主谓一致,第三个头可能关注语义指代。我在实操中观察过一个训练好的 8 头 Transformer,确实有头会稳定地关注句法角色相近的词,虽然这种"可解释性"并不总是存在。

位置编码用的是正弦函数式编码,每个位置有一个唯一的向量表示,向量里不同维度对应不同频率的正弦波。这个设计的巧妙之处在于可以通过线性变换近似表达相对位置关系——因为有 sin(a+b) = sin(a)cos(b) + cos(a)sin(b) 这个恒等式,模型可以学到"位置 i 和位置 i+k 之间的相对偏移"。

5.3 三大关键设计决策的逻辑推演

第一个决策是去掉循环层。守旧派认为循环结构是序列模型的灵魂,没有它模型就会失去顺序感知能力。但 Transformer 用位置编码回答了这个问题:顺序信息的表达可以外挂在输入表示上,不一定要靠循环结构来隐式传递。

第二个决策是LayerNorm 放在残差之前还是之后。Transformer 原文用的是 post-LN(残差之后再归一化),但后来很多实践中发现 pre-LN(先归一化再进子层)训练更稳定,适合大规模训练。这是工程实践倒逼学术结论的典型例子。

第三个决策是teacher forcing 的使用。训练解码器时,每一步都用真实的目标 token 作为输入,而不是用模型自己上一步的输出。这样训练速度更快、更稳定,但推理时存在曝光偏差(exposure bias)——模型在训练时没见过自己的错误输出,推理时却要基于自己的上一步输出继续生成。这个偏差的缓解方案五花八门,从 scheduled sampling 到强化学习,各有利弊。

6. 实操视角:从老架构迁移到 Transformer 的踩坑清单

6.1 训练策略的巨大转变

如果你是老 RNN 时代过来的,迁移到 Transformer 后最先感受到的不是模型性能的提升,而是训练过程的"娇气"。Transformer 对超参数的敏感度远比 LSTM 高,尤其是学习率和 warmup 步数。

Transformer 论文里建议用 Adam 优化器,beta1=0.9,beta2=0.98,epsilon=1e-9,学习率先用 warmup 阶段线性增加,再按倒数平方根衰减。我复现的时候踩过一个坑:直接照搬默认学习率 1e-3 去跑,结果前 2000 步 loss 就爆炸了。后来把 warmup 步数从 4000 调到 8000,学习率峰值从 1e-3 降到 7e-4,情况才稳定下来。我的经验是,模型规模越大,warmup 步数要越多,峰值学习率要越低。

另一个容易忽视的点是 label smoothing。Transformer 原文用了一个很小的 label smoothing —— 0.1,这看起来微不足道,但对 BLEU 的影响能到 0.5-1 分。原理是让模型不要过度自信,给 softmax 分布注入一点噪声容忍度,间接起到正则化的作用。

6.2 序列长度与位置编码的实战教训

序列长度这块我栽过好几次。Transformer 的自注意力计算量是 O(n^2) 的,n 是序列长度。你以为 1024 长度的序列没什么,算一下:1024 x 1024 的注意力矩阵,每个矩阵里是 float32,约 4MB 显存,但这只是一个头、一层的量。8 个头乘 6 层乘 batch size 32,那数字就很吓人了。

长序列训练时,我强烈建议先减半 batch size 做一次前向传播看看显存占用情况,再逐步调整到目标值。另外,内存碎片也是一个问题,PyTorch 2.x 自带的 memory efficient attention 在这里能派上用场,实测可以把注意力部分显存占用降低 50% 左右。

还有一个大家经常问但少有人聊清楚的问题:位置编码能不能外推到训练时没见过的长度?正弦位置编码理论上可以无限外推,但由于注意力权重在长距离上分布不均,实际外推效果很一般。ALiBi 这类相对位置编码方案在这一点上表现更好,但那是另一个话题了。

6.3 常见问题速查与避坑心得

现象可能原因解决方案
训练前几百步 loss 不降学习率过高或过低调低峰值学习率,加大 warmup 步数
显存 OOM序列过长或 batch 过大缩短序列、减小 batch、用 memory efficient attention
推理结果重复严重曝光偏差或 beam search 参数不当调大惩罚参数,或改用 top-p + top-k 采样
模型对顺序不敏感位置编码权重未充分训练检查位置编码实现,确保学习率覆盖到 embedding 层
长序列推理性能下降明显距离远时注意力分布稀疏尝试相对位置编码,如 ALiBi 或 RoPE

还有一条我每次分享都会强调的经验:不要迷信 base 配置。Transformer 论文里的 base 模型参数是 6 层、512 维、8 头,total 参数量约 65M。很多人拿这个配置去跑自己的小语种翻译,效果往往不如调好参数的 LSTM 模型。原因很简单:Transformer 是数据饥饿型模型,参数量大、吃数据量也大。在你数据量不超过几百万句对的时候,我建议先减少层数和维度,或者直接用预训练模型微调,而不是从零训练一个 base Transformer。

7. 演进复盘与个人体会

7.1 这条演进线教给我们的底层逻辑

回看序列转导模型这几年的演进,最值得玩味的不是某篇论文的某个具体技巧,而是整个演进背后的方法论:瓶颈决定方向。RNN 时代的瓶颈是长距离依赖和信息压缩,于是注意力机制被发明;注意力机制普及后,瓶颈变成训练效率,于是自注意力一步到位取代循环层;再往后,瓶颈又变成模型规模和数据规模的扩展性,于是有了预训练加微调的新范式。

换句话说,每个阶段的"最优架构"都只是那个阶段约束条件下的最优解。LSTM 在 2014 年是王者,但放到 2017 年的硬件条件下就成鸡肋了——不是它变差了,而是约束条件变了。做技术选型时一定要考虑这个时代变量,闭门造车式地守着老架构不忍心换,最后往往会被效率问题拖死。

7.2 关于"transformmr"这个拼写,最后再扯两句

我猜搜索这个词的朋友里,应该有不少是刚看到 Attention Is All You Need 那篇论文、但对领域历史还不太熟的年轻人。如果你正处在这个阶段,我的建议是:不要只读论文正文,去把论文引用那几十篇老文章翻一翻。你会在 Bahdanau 2015 那篇里看到注意力最初的朴素出发点,会在 Sutskever 2014 那篇里看到 encoder-decoder 框架的雏形,会在 ConvS2S 那篇里看到并行化的执着追求。

这些"前戏"不是过时的废料,它们是 Transformer 设计哲学的直接注脚。理解了它们,你就理解了为什么 Transformer 长成今天这个样子,也就更能理解为什么下一代架构如果要超越 Transformer,大概率也是从"当前架构的瓶颈在哪"这个老问题出发,一点一点熬出来的。我自己在读完这些老论文后,最大的收获不是记住了某个公式,而是学会了用"瓶颈-约束-突破"的视角去看待任何新技术。算法圈子迭代太快,真正能沉淀下来的,往往就是这种看问题的角度。