设想一场高规格的跨国技术峰会。台上,一位工程师正用流利的英文演讲;台下,观众戴着同传耳机,耳机里精准流畅的中文,出自一位翻译官——我们就叫他阿杰。 阿杰的工作方式有个耐人寻味的特点:他从不会「听到一个词就译一个词」。当演讲者说出 "Our model achieved unprecedented accuracy……" 时,阿杰不会急着开口——他会先让这串音流在脑中「存一下」,等到关键信息出现,甚至听到后半句还会推翻自己对前半句的理解。他真正做的,是听完一段意思完整的话,在脑海中凝练出一个「核心意思」,再基于这个核心意思,用中文重新组织语言,一句一句地讲出来。 这个「先听懂、再重新表达」的过程,正是 Seq2Seq(sequence-to-sequence,序列到序列)模型的工作范式。而它的骨架,就是本文的主角——编码器-解码器(Encoder-Decoder)架构:编码器负责「听懂」,把变长的输入序列浓缩成语义向量;解码器负责「表达」,把这个向量一步步展开为变长的目标序列。机器翻译、文本摘要、对话系统……今天无数AI应用的底层,都站着这套架构。 本文我们将跟随阿杰的视角,拆解编码器如何逐词消化输入、上下文向量如何储存语义、解码器如何逐步生成输出,以及注意力机制如何为长序列补上关键短板。
理解编码器-解码器架构,是进入 NLP 序列建模世界的「第一块敲门砖」。它让你在面对翻译、摘要、对话等任务时,能一眼看穿模型的骨架与瓶颈,为后续学好 Transformer 和各类大模型奠定扎实的直觉基础。
可视化演示
展示操作系统进程在新建、就绪、运行、等待、终止五种状态间的转换过程,支持自动播放与手动步进控制。
本节配有交互动效(进入视口后自动加载,约 3KB)。
进程五状态模型 新建状态:进程刚创建,等待被系统 admit 就绪状态:已准备好执行,等待 CPU 分配 状态转换由调度器和事件驱动 当前进程处于新建状态,等待进入就绪队列
架构总览
阿杰每天的工作可以简化为两次「点头」:第一次,他侧耳倾听,从头到尾听完发言人的一整句话;第二次,他面向观众,开始用另一种语言讲述同一个意思。中间的间隙,他的大脑飞快地完成了对源语言的「压缩」与对目标语言的「展开」。编码器-解码器架构正是把这两次点头背后的机制,显式地建模成了两个可学习的神经网络组件。
在 Seq2Seq 这个大家族里,输入和输出都是变长序列。机器翻译是典型例子:英文句子可能是 9 个 token,中文对应句可能是 7 个 token。编码器-解码器架构让模型无需人为定义输入与输出的对齐关系,而是通过「理解-表达」两个阶段完成转换。编码器(Encoder)读取整个输入序列,解码器(Decoder)根据前者的总结逐步生成输出序列。
这种端到端的学习方式,使从原始语料到最终翻译的整个过程可以被统一优化。传统方法往往把翻译拆成分词、调序、线性化等多个子模块;Seq2Seq 则把这一串流程折叠进一个模型里,只靠一个损失函数驱动。架构层面的核心连接点,是一个称为「上下文向量」(context vector)的张量——它承载了源序列的语义,充当编码器与解码器之间唯一的通道。
把阿杰的故事放进这个框架:输入序列是他听到的英文单词流,编码器是他的听觉-理解系统,上下文向量是他闭眼一瞬脑中的完整意思,解码器则是他开口组织中文的语音系统。四个角色各司其职,构成了序列转换任务最通用的一张蓝图。
- 输入序列$x_1, x_2, \ldots, x_T$ 是变长的源句子,例如英文 "I love you" 的三个词。
- 编码过程编码器从左到右逐词读取,输出一个浓缩了整句语义的向量。
- 语义向量$c$ 是固定维度的上下文向量,不随源句长度变化,相当于阿杰脑中的「核心意思」。
- 解码过程解码器从 $c$ 出发,逐词生成目标序列的第一个词、第二个词……
- 输出序列$y_1, \ldots, y_{T'}$ 是变长的目标句子,长度可以不同于源句,这正是 Seq2Seq 灵活性的来源。
编码器机制
很多人以为翻译官是「人肉词典」,听到一个词就报一个词。真实的阿杰恰恰相反:他听每句话时,都会在脑中维护一张不断涂改的「理解草稿」。听到 'not',他会把草稿中的肯定判断划掉;听到 'but',他会预感到转折即将到来。每听一个词,草稿就更新一次——这正是 RNN 编码器的核心行为。
在编码器中,这个「理解草稿」被称为隐藏状态(hidden state),记作 $h_t$。初始时 $h_0$ 是一个全零向量(阿杰脑中一片空白);随后每读取一个输入词 $x_t$,模型就通过一个非线性变换,把上一步的隐状态与新词的嵌入向量融合,得到新的隐状态 $h_t$。这个变换由循环神经网络(RNN)单元完成,最常见的形式如下:
值得强调的是,单向 RNN 的 $h_t$ 只能看到 $x_t$ 及其左侧的历史信息。为了让模型「看到未来」,工程师们设计了双向 RNN(BiRNN):一个普通 RNN 从左往右读,另一个从右往左读,再把两个方向的隐状态拼接,作为每个位置最终的编码结果。这相当于阿杰在听完整句话后,快速回溯一遍之前的每个词,确保转折、否定等关键信息没有被遗漏。
有了双向编码,阿杰脑中的「理解草稿」就不再只是从前往后的线性笔记,而是一张正反两面都写满批注的大纸——这正是双向 Seq2Seq 在翻译、摘要等任务上普遍优于单向版本的原因。
- 上一步隐状态$h_{t-1}$ 是阿杰听完前 $t-1$ 个词后脑中的阶段性理解。
- 旧信息延续$W_{hh} h_{t-1}$ 将旧草稿线性变换,决定旧信息多大程度被保留。
- 新词注入$W_{xh} x_t$ 将当前词 $x_t$ 映射到语义空间,相当于阿杰听到的第 $t$ 个词。
- 信息合并新旧信息相加再加上偏置 $b_h$,完成一次「笔记更新」。
- 非线性压缩$\tanh$ 把合并结果压到 $(-1, 1)$,保证数值稳定并引入非线性表达力。
上下文向量
当发言人说完最后一个词,阿杰会用零点几秒的时间「定稿」——把整个句子的意思凝练成一条不带冗余措辞的核心命题。这个命题不是某个词的字面翻译,而是一份高度压缩的语义快照。在 Seq2Seq 中,这份快照就是上下文向量 $c$。
编码器把所有时刻的隐状态收集起来后,需要通过一个聚合函数 $q$ 生成这个向量。最简单的做法是直接取最后时刻的隐状态 $c = h_T$,相当于阿杰只保留读完整个句子后那一刻的终态记忆;也可以通过平均池化、注意力加权等方式对全部隐状态做汇总。
无论哪种方式,上下文向量的维度都是固定的——这是它的硬约束,也是它的软肋。设想阿杰听到一句 50 词的复杂长句,却必须把它全部装进一个 256 维的向量里。词数越多,压缩率越高,开头和中间的信息就越容易被末尾覆盖。这正是早期 Seq2Seq 模型著名的「信息瓶颈」问题:固定长度的向量成了长句翻译质量的天然天花板。
在早期的神经机器翻译系统(如 2014 年的 Seq2Seq 模型)中,$c = h_T$ 曾是主流选择。它训练简单、实现方便,但研究者很快发现:源句越长,翻译质量下滑越严重。这就像阿杰在掌心记笔记——短句时应付自如,长句时字迹越来越挤,最终难以辨认。上下文向量的「容量天花板」,直接催生了下一章要讲的进化方案。
- 全部隐状态$h_1, \ldots, h_T$ 是编码器在每个位置留下的阶段性理解,覆盖整条源序列。
- 聚合函数$q(\cdot)$ 把这些隐状态「拧成一股绳」,输出一个固定维度的向量。
- 最终向量$c$ 就是上下文向量,维度固定,不随 $T$ 变化。
- 最简形式直接取最后一个隐状态当作 $c$,实现最简单,但长序列信息易丢失。
解码器机制
定稿之后,阿杰开始说话。他不会一口气输出整句中文,而是先说出第一个词,停一停,感觉自己说得是否通顺,再决定第二个词。每说出一个词,这个新词本身又成为下一轮决策的语境——这就是解码器的自回归本质。
解码器(Decoder)是另一个 RNN,维护自己的隐藏状态 $s_{t'}$。它与编码器最大的不同在于:它每一步的输入,是上一步生成的目标词 $y_{t'-1}$,而初始状态则来自编码器传来的上下文向量 $c$。也就是说,解码器的「创作条件」= 源句语义 + 已经产出的前缀。
在每一步 $t'$,解码器先更新自己的状态,再通过一个线性层将状态映射到词表大小,最后用 softmax 归一化为词表上的概率分布:
此外,训练与推理时序列的终止由专门的结束符 <EOS>(End of Sequence)控制。解码器一旦生成了 <EOS>,生成过程便画上句号,就像阿杰说完「以上就是我的翻译」——听众知道这句话结束了。训练阶段的每条目标句子都会被补上 <EOS>,让模型学会在恰当的位置收口。
逐步生成、自回归、终止符——解码器像一位一丝不苟的演说家:每一句都基于前一句的落点,最后用固定的方式宣告完结。
- 上一步表达状态$s_{t'-1}$ 是解码器已经说出的内容形成的语言惯性。
- 上一步生成的词$y_{t'-1}$ 作为输入重新进入循环,让模型知道自己刚才说了什么。
- 注入核心意思$W_{cs}\, c$ 把上下文向量融入当前状态,时刻提醒阿杰不要偏离主题。
- 状态更新三路信息相加经 $\tanh$ 压缩,得到新的表达状态 $s_{t'}$。
- 概率输出$W_o s_{t'} + b_o$ 映射为词表得分,$\mathrm{softmax}$ 归一化得到每个词的生成概率。
注意力机制
第一次参加超长会议后,阿杰吃了亏:一句话 60 个词,他翻译到后半段时已经忘了前面某个关键数字。从此他养成一个习惯——手边放一沓源文笔记,讲到哪个词,就快速扫一眼源文对应位置,把目光停留在最相关的几个词上。这就是注意力(Attention)的雏形。
注意力机制的核心思想:解码器生成第 $t'$ 个词时,不再只看一个固定向量 $c$,而是重新访问编码器的全部隐状态 $h_1, \ldots, h_T$,为它们计算一组权重,再求加权和作为这一步的动态上下文向量 $c_{t'}$。权重越大,代表源文中对应位置的词对当前输出词越重要。
权重的计算通常分为三步:先算解码器上一步状态 $s_{t'-1}$ 与每个编码器隐状态 $h_t$ 的匹配分数 $e_{t',t}$;再对分数做 softmax 归一化得到权重 $\alpha_{t',t}$;最后按权重对 $h_t$ 求和:
注意力的引入一举打破了固定长度上下文向量的瓶颈:即使源句很长,解码器也可以在每一步精准「回看」到相关位置,把长距离依赖显式地建模为短距离的「查找」。这份工作最早由 Bahdanau 等人于 2015 年引入中英机器翻译,让 Seq2Seq 对长句的翻译质量有了质的提升,也点燃了后来用注意力取代循环结构的思想火花。
从「靠脑内记忆」到「随查随看」,阿杰的翻译生涯从此迈入新阶段:笔记不再是压缩版的掌心词条,而是一份可以随时翻阅、按需取用的完整档案——这正是注意力带给 Seq2Seq 的进化。
e_{t',t} = v^\top \tanh(W_s\, s_{t'-1} + W_h\, h_t), \qquad\alpha_{t',t} = \frac{\exp(e_{t',t})}{\sum_{k=1}^{T} \exp(e_{t',k})}, \qquadc_{t'} = \sum_{t=1}^{T} \alpha_{t',t}\, h_t- 匹配打分$e_{t',t}$ 衡量「当前翻译需求」与「源文第 $t$ 个词」的匹配程度,分数越高越相关。
- 归一化权重对整句的分数做 softmax,把分数变成和为 1 的注意力权重。
- 加权求和按权重汇总所有隐状态,得到这一步专用的上下文向量。
训练推理模式
阿杰所在的翻译公司有两位新手:一位是实习生小陈,一位是转正的正式员工。带小陈时,阿杰会在他每译完一个词后告诉他这个位置的标准译法;而正式员工独立工作时,没有人给参考答案,只能用自己的上一个输出继续翻译。训练与推理阶段的解码器,恰好处在这两种截然不同的模式中。
训练阶段,解码器使用「教师强制」(Teacher Forcing):即便模型上一步预测错了,仍然把真实的目标词喂给下一步。这样做的优点是训练信号清晰、收敛快;缺点是模型在推理时从未见过自己的错误输出,一步错可能导致后面连环错。这种「曝光偏差」(exposure bias)是训练与推理不一致的根源。
在训练中,目标是最小化所有词位置的平均负对数似然。假设第 $i$ 个样本的源序列为 $x^{(i)}$,目标词为 $y_1^{(i)}, \ldots, y_{T'}^{(i)}$,整体损失函数写为:
推理阶段则完全不同:没有标准答案,解码器从 <SOS> 开始,逐个用 argmax 选择概率最高的词并把它当作下一步输入。为了弥补这种「贪心」的短视,工程上常用束搜索(Beam Search):每一步不只保留概率最高的 1 条路径,而是保留得分最高的 $k$ 条候选路径,最后在序列结束时选择整体评分最优的一条。$k$ 通常取 4~8,像阿杰在口译时同时组织两三个版本的译法,挑最顺口的说出来。
教师强制是有人纠正的刻意练习,自回归是独自上阵的临场发挥,束搜索则是在脑内多留几个备选方案。这三种模式的转换,正是 Seq2Seq 从课堂走向实战的关键。
- 条件概率$P_{\theta}(y_{t'} \mid y_{<t'}, c)$ 是模型在给定前缀和上下文时预测该词的概率。
- 取对数$\log$ 把连乘的概率变成连加,避免浮点数下溢。
- 双重求和对所有训练样本 $i$、所有词位置 $t'$ 累积误差,覆盖整句翻译的每个词。
- 负号与平均取负号使得「最大化概率」变成「最小化损失」,除以 $N$ 便于不同批量大小间比较。
典型应用场景
会议翻译并不是阿杰唯一的工作。他能做英译中,也能把长文档改写成一段 140 字的会议纪要,还能在客服电话里充当人机沟通的桥梁。编码器-解码器架构同样如此——只要任务可以抽象成「一堆序列进去,另一堆序列出来」,它就是通用的装配线。
Seq2Seq 最早一鸣惊人的场景是神经机器翻译(NMT)。输入源语言句子,输出目标语言句子,编码器-解码器以端到端方式学习翻译。与传统的统计机器翻译相比,NMT 不再需要单独维护短语表、调序模型等复杂模块,一套架构即可覆盖整个翻译流程。
更广义地看,这类任务都可以用「给定源序列,最大化目标序列概率」来描述:
第二个高频场景是文本摘要:把一篇长新闻当作输入序列,把一句或几句话的摘要当作输出序列,模型学习的是「去粗取精」的压缩能力。第三个场景是对话系统:把用户的消息作为输入序列,把候选回答作为输出序列;大型聊天机器人的早期雏形,很多就是在这种架构上预训练的。三者共享同一个骨架,差异主要在数据形态和序列长度上。
无论阿杰穿的是同传耳机、编辑马甲还是客服工服,他解决问题的底层逻辑始终如一:听懂、提炼、表达。编码器-解码器架构也因此在翻译、压缩、对话等众多序列转换任务中,成为当之无愧的通用基石。
- 联合概率左边是给定源句时,生成一整句目标语的条件概率。
- 链式分解把整句概率拆成每个词条件概率的乘积,串行生成的本质。
- 历史条件每一步都以已生成前缀为条件,模型像阿杰一样「一边说一边想」。
局限与发展
随着会议越来越长,阿杰的老搭档 RNN 的疲惫显而易见:必须按顺序听完才能理解,长句记不住,还要逐词等待。终于有一天,公司请来了一位叫 Transformer 的新同事——他不再逐词听,而是把整页文稿同时摊在桌上看,让每一个词直接与其他所有词对话。
RNN 时代的编码器有两个先天局限:一是长程依赖问题——信息沿时间步逐级传递,距离过远时梯度容易消失,模型记不住开头的关键内容;二是顺序计算瓶颈——第 $t$ 个隐状态依赖第 $t-1$ 个,无法并行,训练速度在大语料上捉襟见肘。注意力机制虽然缓解了前者,却仍在 RNN 骨架上运行。
Transformer 的答案是用自注意力(Self-Attention)彻底取代循环结构。它让序列中的每个词同时作为 Query 去「查询」其他所有词的 Key,再对 Value 做加权求和,从而在一步之内捕捉全序列依赖:
从架构关系看,Transformer 依然保留了编码器-解码器的宏观骨架:它的 Encoder 负责对输入序列做自注意力编码,Decoder 负责对已生成前缀做掩码自注意力,并通过交叉注意力(Cross-Attention)接入编码器的输出。所以,编码器-解码器架构不仅没有过时,反而在 Transformer 时代以更强大的形态延续着「先理解、再生成」的基因。
阿杰的新同事 Transformer 的办公方式改变了,但公司的工作流程没变:仍要有人先读懂材料,再整理成会议纪要。编码器-解码器架构正是这个流程的永恒骨架——它定义了「先听懂、再表达」这一认识世界的通用范式。
- 查询矩阵$Q$(Query)表示「我要找什么信息」,每个词都发起一次查询。
- 键与值$K$(Key)表示「我能匹配什么」,$V$(Value)是真正携带信息的表示。
- 点积相似度$Q K^\top$ 计算每对词的匹配分数。
- 缩放除以 $\sqrt{d_k}$ 防止分数过大导致梯度消失,相当于对热度做「降温」。
- 加权聚合softmax 归一化成权重后乘 $V$,得到每个词融合全句信息的新表示。
AI 应用场景
神经网络机器翻译系统
阶段:模型训练与推理部署
解决的问题:传统统计机器翻译需要人工维护短语表、调序模型和语言模型,模块多、级联误差大。基于编码器-解码器的 NMT 把「翻译」建模为「源序列到目标序列的条件概率估计」,一套端到端模型直接完成,工程师不再需要为每种语言对单独设计规则。
具体案例:某出海电商平台要支持中英日韩四语商品描述互译。团队用 Transformer 编码器-解码器在平行语料上训练翻译模型,线上服务时对每一句商品文案先编码、再束搜索解码,最终把人工审核成本降低了 60%,长描述翻译的 BLEU 值比旧系统提升 8 个点。
新闻文本自动摘要
阶段:数据预处理与模型微调
解决的问题:新闻 APP 的编辑每天要手工把数百篇长文压缩成摘要,耗时且标准不一。编码器-解码器架构天然支持「长序列进、短序列出」,通过端到端训练学会判断哪些句子承载核心信息,并将它们重组为通顺的摘要。
具体案例:某资讯平台在 50 万篇「新闻-摘要」对上微调了一个基于编码器-解码器的摘要模型。编码器读入整篇文章的 token 流,解码器用束搜索生成不超过 140 字的摘要。上线后摘要生产的吞吐量提高了 20 倍,人工编辑只需做最终润色。
Python 演示
import torchimport torch.nn as nnimport torch.optim as optim class Encoder(nn.Module): def __init__(self, vocab_size, emb_dim, hid_dim): super().__init__() self.embedding = nn.Embedding(vocab_size, emb_dim) self.rnn = nn.GRU(emb_dim, hid_dim) def forward(self, src): embedded = self.embedding(src) outputs, hidden = self.rnn(embedded) return hidden class Decoder(nn.Module): def __init__(self, vocab_size, emb_dim, hid_dim): super().__init__() self.embedding = nn.Embedding(vocab_size, emb_dim) self.rnn = nn.GRU(emb_dim, hid_dim) self.fc = nn.Linear(hid_dim, vocab_size) def forward(self, trg, hidden): embedded = self.embedding(trg) output, hidden = self.rnn(embedded, hidden) pred = self.fc(output) return pred, hidden class Seq2Seq(nn.Module): def __init__(self, encoder, decoder): super().__init__() self.encoder = encoder self.decoder = decoder def forward(self, src, trg): hidden = self.encoder(src) output, hidden = self.decoder(trg, hidden) return output def train(): model = Seq2Seq(Encoder(10, 16, 32), Decoder(10, 16, 32)) optimizer = optim.Adam(model.parameters()) loss_fn = nn.CrossEntropyLoss() for epoch in range(50): src = torch.randint(1, 10, (5, 4)) trg = torch.randint(1, 10, (5, 4)) pred = model(src, trg) loss = loss_fn(pred.reshape(-1, 10), trg.reshape(-1)) optimizer.zero_grad() loss.backward() optimizer.step() if epoch % 10 == 0: print(f"epoch {epoch}, loss {loss.item():.3f}") if __name__ == "__main__": train()
self.rnn = nn.GRU(emb_dim, hid_dim)定义一个 GRU 循环网络,它是编码器的「记忆单元」,相当于阿杰脑中的笔记板。outputs, hidden = self.rnn(embedded)将整条输入序列一次性送入 GRU,返回每个时刻的隐状态和最终隐状态。return hidden只把最终的隐状态(也就是上下文向量 c)传给解码器。output, hidden = self.rnn(embedded, hidden)解码器以编码器传来的 hidden 作为初始状态,逐时间步生成输出。pred = self.fc(output)通过一个线性层把隐状态映射为词表大小的得分,softmax 后就得到词的概率分布。loss = loss_fn(pred.reshape(-1, 10), trg.reshape(-1))用交叉熵比较预测分布与真实目标词,得到「翻译错误程度」。optimizer.zero_grad()` / `loss.backward()` / `optimizer.step()梯度清零、反向传播、参数更新,这就是训练套娃的小三轮。
常见误区
误区我总以为 Seq2Seq 里的编码器和解码器必须是一对孪生兄弟——都用 LSTM 就都用 LSTM,用 GRU 就都用 GRU,否则模型会「不匹配」。
正解编码器与解码器在结构上完全独立,它们只需要通过上下文向量对接即可。编码器可以用双向 LSTM,解码器可以用单向 GRU;甚至在 Transformer 时代,编码器是 Self-Attention 堆叠、解码器是 Masked-Attention 堆叠,结构不同但协作默契。就像阿杰的「听觉系统」和他的「发声系统」本来就是两套不同的器官,只要共享同一个语义接口就行。
为何常见:因为教科书示例中 Encoder 和 Decoder 往往都是同一种 RNN cell,看起来像「配对出场」,让人误以为结构必须对称。
误区我觉得 c 就是 h_T,因为很多入门教程的图里都画着「最后一个 hidden 直接连到解码器」。这是唯一正确的取值方式吧?
正解$c = h_T$ 只是最简单的一种聚合方式。你完全可以用平均池化、最大池化、或者注意力加权求和来聚合所有隐状态。事实上,现代 Seq2Seq 几乎不再使用单一的 $h_T$,而是用注意力机制为每一步生成动态的 $c_{t'}$。固定取最后一位,就像让阿杰只听清句尾就断定全句意思,显然不是最优策略。
为何常见:因为早期经典论文和教学图为了直观,常把「最后一个 hidden」画成唯一的传递箭头,简化成了共识。
误区编码器-解码器不是叫「神经机器翻译」吗?那它应该只能处理一种语言到另一种语言的翻译吧?
正解Seq2Seq 的定位是「序列到序列」的通用框架,翻译只是它最出名的应用。文本摘要(长序列→短序列)、对话生成(用户消息→回复)、语音识别(音频帧序列→文本序列)、甚至代码生成(注释序列→代码序列)都属于序列转换任务,都能套用编码器-解码器骨架。凡是「一堆东西进去、另一堆东西出来」的任务,它都有用武之地。
为何常见:Seq2Seq 最早在 2014 年因机器翻译论文走红,「机器翻译」这个标签被贴得太响,掩盖了它作为通用架构的本质。
误区我训练时解码器输入是上一步生成的结果,那推理时肯定也是同样的,反正模型就是一个 RNN 往前跑,没什么区别。
正解训练时用的是「教师强制」——即便模型输出了错误词,我们仍然把真实目标词喂给下一步;推理时没有老师在场,只能用模型自己上一步生成的词继续。两者的输入分布不一致,这会产生「曝光偏差」:训练时模型没见过自己的错误,推理时一步错就可能导致连环错。这也是为什么很多系统会加入计划采样(Scheduled Sampling)来让训练更贴近推理。
为何常见:因为单向看模型结构确实都是「上一步输出进入下一步输入」,但忽略了训练数据流中「谁来提供上一步输入」这个关键差异。
误区双向编码只是把两个方向的隐状态拼在一起,应该只影响编码器本身吧?反正上下文向量最后都会传给解码器,是否双向无所谓。
正解双向编码让每一个源位置的隐状态同时包含「左侧」和「右侧」的上下文信息,这些更丰富的隐状态正是注意力机制要查询的对象。解码器在做对齐时,会为每个源词计算权重;如果 $h_t$ 只是单向的,模型对位于句子后半段的词就缺乏前文线索,对齐质量会明显下降。阿杰翻译时能准确抓住一个跨越全句的否定词,靠的正是双向理解带来的全局视野。
为何常见:人们容易把编码器看成「一个黑盒压缩器」,忽略隐状态本身是注意力查询的目标,从而低估了双向编码对下游解码的影响。
面试题
Q1. 编码器-解码器架构中,编码器的主要职责是?
- A.对输出序列进行随机采样
- B.理解输入序列并编码语义← 正确答案
- C.计算输出词表的概率分布
- D.负责对序列做束搜索
答案:B。编码器负责把输入序列「听懂」并浓缩成语义表示,对应阿杰的听觉-理解系统。A 是采样策略,C 是解码器的输出层职责,D 是推理阶段的搜索策略,都不属于编码器的核心职责。
Q2. 最简单的上下文向量 c 通常取编码器的哪个值?
- A.编码器的第一个隐状态
- B.所有隐状态的随机采样
- C.编码器的最后一个隐状态← 正确答案
- D.解码器的最后隐状态
答案:C。最简单的聚合方式是 $c = h_T$,即取编码器读完整个源句后的最终隐状态。取第一个隐状态会丢失几乎全部信息,随机采样更不正确,解码器的隐状态则属于生成阶段而非编码阶段的产物。
Q3. 关于「教师强制」(Teacher Forcing)训练策略,正确的理解有?
- A.训练时用真实目标词作为解码器输入← 正确答案
- B.推理时用模型自生成词作为解码器输入← 正确答案
- C.教师强制能完全消除训练与推理的差异
- D.教师强制可提升训练稳定性← 正确答案
答案:ABD。教师强制在训练时用真实词喂给解码器,让学习更稳定;推理时没有真值,只能用自生成词,因此训练与推理必然存在「曝光偏差」,C 正确说法不成立。
Q4. 注意力机制中,Softmax 权重的主要作用是什么?
- A.让所有注意力权重之和为 1← 正确答案
- B.让权重值变成 0 或 1
- C.随机打乱源词的排列顺序
- D.增加解码器模型参数
答案:A。softmax 把匹配分数归一化为概率分布,使所有源位置的权重和为 1,便于做加权求和。它不会把权重变成 0/1 硬选择,也不涉及乱序或加参。
Q5. 解码器逐个生成目标词时,模型需要执行的核心操作是?
- A.计算上下文与源词的距离
- B.在词表上产生分布并选词← 正确答案
- C.对源序列进行随机排序
- D.让编码器重新读一遍
答案:B。解码器每一步通过线性层和 softmax 在词表上产生概率分布,再按策略(贪心或束搜索)选词,然后作为下一步输入。A、C、D 都不是解码器的工作方式。
Q6. 关于 Seq2Seq 的信息瓶颈问题,下列表述正确的有?
- A.固定长度向量难以承载长句信息← 正确答案
- B.注意力机制缓解了信息瓶颈← 正确答案
- C.双向编码彻底解决了该问题
- D.长句中早期信息容易在末尾丢失← 正确答案
答案:ABD。固定长度的上下文向量是容量瓶颈,长句的早期信息经多步传递后容易被覆盖。注意力通过动态加权求和让解码器直接访问所有源位置,显著缓解瓶颈。双向编码只丰富了隐状态,不能彻底解决问题。
Q7. 束搜索(Beam Search)与贪心解码的本质区别是?
- A.束搜索每步只留一条最优路径
- B.束搜索每步保留 k 条候选路径← 正确答案
- C.贪心解码会做全局最优搜索
- D.两种方式数学上完全等价
答案:B。贪心解码每步只取当前概率最高的词,是短视的局部最优;束搜索每步保留得分最高的 k 条候选路径,最终选整体最优的一条。这是解码质量与计算开销之间的权衡。
Q8. 推理阶段解码器每一步的输入中,必须包含?
- A.上一步生成的目标词← 正确答案
- B.下一个源词的向量
- C.编码器的全部输出
- D.预先设定的噪声词
答案:A。推理时没有标准答案,解码器只能把自己上一步生成的词作为下一步输入,形成自回归闭环。B、C、D 都不是推理时解码器输入的必要组成部分。
Q9. 关于编码器-解码器架构与注意力机制,下列表述正确的是?
- A.编码器可由 Transformer 担任← 正确答案
- B.解码器必须是循环神经网络
- C.自注意力可捕捉全序列依赖← 正确答案
- D.注意力最早成功用于机器翻译← 正确答案
答案:ACD。编码器可以由 RNN、CNN 或 Transformer 担任,解码器同样可以用 Transformer(其内部是自回归生成),因此 B 错误。自注意力一次计算任意词对关联,确实能捕捉全序列依赖;注意力机制最早在 2015 年的中英机器翻译任务上取得突破。
Q10. 下面哪个任务最不适合用编码器-解码器架构建模?
- A.英译中机器翻译
- B.新闻长文自动摘要
- C.图像像素值分类← 正确答案
- D.聊天机器人对话生成
答案:C。图像像素值分类是把每个像素映射到离散标签,输入输出是「一对一」的逐点分类,没有明显的「序列到序列」转换结构。翻译、摘要、对话都是典型的序列转换任务,非常适合 Seq2Seq。