Seq2Seq:机器翻译中的编码器-解码器经典解读
本文是一篇原创中文论文解读,参考 Dive into Deep Learning 1.0.3 中的 “Sequence-to-Sequence Learning for Machine Translation” 章节,并结合 Cho et al. 2014、Sutskever et al. 2014 的序列到序列学习思想进行梳理。本文不是逐段翻译,而是围绕模型结构、训练目标、推理方式和历史影响做结构化讲解。原文与图片遵循 D2L 开源书许可:正文与图示为 Creative Commons Attribution-ShareAlike 4.0 International License,示例代码为 modified MIT license。
为什么 Seq2Seq 是经典
在深度学习进入机器翻译之前,翻译系统通常依赖复杂的短语表、对齐模型和大量人工特征。Seq2Seq 的关键转折在于:它把“输入一句话、输出另一句话”抽象成一个端到端的条件序列建模问题。
给定源语言序列:
x1,x2,…,xTx_1, x_2, \ldots, x_Tx1,x2,…,xT
模型要学习目标语言序列的条件概率:
P(y1,y2,…,yT′∣x1,x2,…,xT)P(y_1, y_2, \ldots, y_{T'} \mid x_1, x_2, \ldots, x_T)P(y1,y2,…,yT′∣x1,x2,…,xT)
这件事今天看起来很自然,因为 Transformer、BART、T5、GPT 式生成模型都把“上下文条件下的逐 token 生成”当作基本接口。但在 2014 年前后,Seq2Seq 的贡献是把可变长输入和可变长输出统一进一个神经网络框架:编码器先读完源序列,解码器再逐步生成目标序列。

图示来自 D2L:英文句子 “They are watching . ” 被编码后,解码器以 <bos> 作为起点,逐步生成法语序列 “Ils regardent . ”。这里最值得注意的是两个特殊符号:<bos> 告诉解码器“开始生成”,<eos> 告诉系统“这句话结束了”。
编码器:把变长输入压成上下文
最朴素的 RNN Seq2Seq 编码器做一件事:按顺序读入源句子的 token,把每一步的词向量和前一时刻隐藏状态合并成新的隐藏状态。
可以写成:
ht=f(xt,ht−1)\mathbf{h}_t = f(\mathbf{x}_t, \mathbf{h}_{t-1})ht=f(xt,ht−1)
其中,xt\mathbf{x}_txt 是第 ttt 个 token 的嵌入向量,ht\mathbf{h}_tht 是编码器到当前位置为止积累的状态。读完整个句子后,编码器用某个函数 qqq 把全部隐藏状态汇总为上下文变量:
c=q(h1,…,hT)\mathbf{c} = q(\mathbf{h}_1, \ldots, \mathbf{h}_T)c=q(h1,…,hT)
在 D2L 的基础实现里,最直接的选择是取最后一个隐藏状态 hT\mathbf{h}_ThT 作为上下文。这个设计很优雅,也很残酷:整句话必须被压进一个固定形状的向量。短句时它工作得不错;句子变长后,早期信息容易被压缩损失,这也是后来注意力机制登场的直接动机之一。

从层次看,编码器通常是 Embedding -> Recurrent,解码器是 Embedding -> Recurrent -> FC。Embedding 把离散词表索引变成连续向量,循环层负责时间维度上的状态传递,最后的全连接层把解码器隐藏状态映射到目标词表上的概率分布。
解码器:条件语言模型
如果暂时忘掉编码器,解码器本质上就是一个语言模型:根据前面已经出现的 token 预测下一个 token。Seq2Seq 的不同之处在于,解码器还要看编码器给出的上下文 c\mathbf{c}c。
在第 t′t't′ 个解码步,解码器状态可写成:
st′=g(yt′−1,st′−1,c)\mathbf{s}_{t'} = g(y_{t'-1}, \mathbf{s}_{t'-1}, \mathbf{c})st′=g(yt′−1,st′−1,c)
随后通过 softmax 得到下一个 token 的分布:
P(yt′∣y1,…,yt′−1,c)P(y_{t'} \mid y_1, \ldots, y_{t'-1}, \mathbf{c})P(yt′∣y1,…,yt′−1,c)
这就是“翻译”被神经网络化后的核心形态:不是一次性吐出整句话,而是在源句上下文约束下,一个 token 一个 token 地采样或选择。
D2L 的实现还有一个重要细节:它把编码器最终隐藏状态用来初始化解码器隐藏状态,并且在每个解码步都把上下文变量拼接进输入。这相当于不断提醒解码器:“你现在生成的词,必须服从那句源语言的语义。”
Teacher Forcing:训练和推理为什么不一样
Seq2Seq 训练时通常使用 teacher forcing。做法是:解码器第 t′t't′ 步的输入不使用模型自己上一步预测出的 token,而使用真实目标序列里前一个 token。
例如目标句子是:
<bos> Ils regardent . <eos>
训练时输入给解码器的是:
<bos> Ils regardent .
要求模型预测的是:
Ils regardent . <eos>
这种“右移一位”的训练方式和语言模型非常相似。它的好处是收敛更快、梯度更稳定,因为模型不会在训练初期被自己错误的预测带偏。代价是训练和推理存在分布差异:推理时真实答案不可见,模型只能把自己上一步的输出再喂回去。
这个差异后来被称为 exposure bias。它解释了很多生成模型的常见现象:训练损失看起来不错,但一旦开头几步生成错了,后续错误会逐步累积。
掩码损失:不要让 <pad> 参与学习
机器翻译训练通常按 minibatch 处理句子。为了让一个 batch 里的句子长度一致,需要在短句末尾补 <pad>。但 <pad> 只是占位符,不是实际语言内容。如果把 <pad> 也纳入交叉熵损失,模型就会被迫学习“预测填充符”,训练目标会被污染。
因此需要 masked loss。简化伪代码如下:
loss = cross_entropy(predicted_tokens, target_tokens)
mask = sequence_mask(valid_lengths)
loss = loss * mask
loss = loss.sum() / mask.sum()
这个设计看似工程细节,其实很关键:Seq2Seq 的目标不是让矩阵形状好看,而是让模型只在真实 token 上接受监督。今天在 Transformer、语音识别、多模态序列建模里,mask 仍然是序列模型的基本工具。
推理:从 <bos> 到 <eos> 的逐词生成
训练时有 teacher forcing;推理时没有。Seq2Seq 推理流程通常是:
1. 编码器读完整个源句,得到上下文 c
2. 解码器以 <bos> 作为第一个输入
3. 预测下一个 token
4. 把预测 token 再喂回解码器
5. 重复,直到生成 <eos> 或达到最大长度

最简单的策略是 greedy decoding:每一步都选概率最大的 token。这种方法实现容易,但不一定全局最优。比如某一步贪心选择的词局部概率最高,却可能让后续句子变得别扭。D2L 在下一节引出 beam search,正是为了缓解这种局部贪心问题。
BLEU:翻译质量如何量化
Seq2Seq 输出的是一句话,不能只用分类准确率评价。机器翻译里常见指标是 BLEU。它的核心思想是比较预测句子和参考句子之间的 n-gram 重合程度,同时惩罚过短输出。
可以把 BLEU 理解成两个部分:
- 精确率:预测句子里的 1-gram、2-gram、3-gram、4-gram 有多少能在参考句子中找到。
- 长度惩罚:如果模型只输出很短的片段,不能因为少犯错就拿高分。
D2L 给出的形式可概括为:
BLEU=exp(min(0,1−lenlabellenpred))∏n=1kpn1/2n\text{BLEU} = \exp\left(\min\left(0, 1 - \frac{\text{len}_{label}}{\text{len}_{pred}}\right)\right) \prod_{n=1}^{k} p_n^{1/2^n}BLEU=exp(min(0,1−lenpredlenlabel))n=1∏kpn1/2n
其中 pnp_npn 是 n-gram 精确率。这个指标并不完美,它不能真正理解语义,也可能低估合理但不同措辞的译文。但在神经机器翻译早期,BLEU 提供了一个可重复比较的共同标尺。
它的局限恰好指向下一代模型
经典 RNN Seq2Seq 最大的瓶颈是固定长度上下文。源句越长,最后状态越难保留所有细节。解决方向主要有三条:
- 注意力机制:不再要求编码器把所有信息压进一个向量,而是允许解码器在每一步动态查看源序列不同位置。
- 更强的搜索策略:用 beam search 等方法减少逐步贪心带来的全局错误。
- 并行架构:Transformer 去掉循环结构,通过自注意力和位置编码在并行计算中建模长距离依赖。
从历史脉络看,Seq2Seq 不是被 Transformer 简单替代,而是提供了序列生成任务的基本语言:encoder、decoder、context、teacher forcing、autoregressive decoding、mask、BLEU。这些概念今天仍然在大模型训练和推理里反复出现。
读这篇经典方法,应该抓住什么
Seq2Seq 的价值不只在机器翻译。它提出了一种通用接口:把一个序列映射成另一个序列。后来很多任务都能放进这个框架:
- 摘要:长文输入,摘要输出。
- 对话:历史上下文输入,回复输出。
- 语音识别:声学特征序列输入,文本输出。
- 代码生成:自然语言或代码上下文输入,代码 token 输出。
- 多模态生成:图像、语音、文本等不同模态之间的序列转换。
如果只记住一句话:Seq2Seq 把“结构化预测”变成了“条件生成”。这一步让深度学习从分类器走向可生成、可翻译、可对话的模型体系。
参考来源与许可说明
本文主要参考:
- Dive into Deep Learning 1.0.3, “Sequence-to-Sequence Learning for Machine Translation”:https://d2l.ai/chapter_recurrent-modern/seq2seq.html
- Cho et al., 2014, “Learning Phrase Representations using RNN Encoder-Decoder for Statistical Machine Translation”:https://arxiv.org/abs/1406.1078
- Sutskever, Vinyals, Le, 2014, “Sequence to Sequence Learning with Neural Networks”:https://arxiv.org/abs/1409.3215
- Papineni et al., 2002, “BLEU: a Method for Automatic Evaluation of Machine Translation”:https://aclanthology.org/P02-1040/
许可说明:D2L 英文开源书 README 的 License Summary 声明,书籍正文按 Creative Commons Attribution-ShareAlike 4.0 International License 发布,示例和参考代码按 modified MIT license 发布。本文为原创中文解读,保留来源链接、作者归属和许可说明;所用 D2L 图示已下载备份并转换为 PNG 以便 CSDN 展示。

512

被折叠的 条评论
为什么被折叠?



