想象一下,你趴在一张书桌前,给远方的笔友写回信。桌角放着一张卡片,是助手替你提炼的“原信要点”;你的笔尖正停在信纸中间,左边是一串已经写好的文字,右边是大片空白。规则很简单:你只能看自己已经写下的字,绝不允许偷看还没写出的句子;每写下几句,还要抬头核对那张要点卡,确保没有跑题。写好的每一个字,立即变成你继续写下去的“语境”——这就是 Transformer 解码器的工作方式。 机器翻译、ChatGPT 对话、代码补全……这些你天天在用的 AI 能力,背后都有一个“逐字回信”的引擎。它先把输入变成要点卡(编码器),再让一个只准看过去的作家(解码器)一个字一个字地写下去。本文就用这间“回信工作室”当导游,带你拆解锁在 GPT 等大模型深处的核心机密:因果掩码、交叉注意力与自回归循环。
理解解码器结构,是读懂 GPT、Llama 等生成式大模型的第一步;掌握掩码注意力与自回归原理,能帮你设计、调试和部署序列生成系统,是 NLP 工程师的必修课。
可视化演示
动态演示Transformer解码器的核心机制,通过全局/局部/动态/静态四种模式展示关键概念与交互流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
Transformer解码器:一解码器 一、解码器整体架构与三层子模块 二、掩码自注意力与因果掩码 核心机制可视化 Transformer解码器整体架构与关键组件
解码器全景
走进小明的“回信工作室”:桌上正中间摆着那张“原信要点卡”(编码器的输出),旁边是一沓草稿纸,记录着已经写下的回信内容。工作室的墙上贴着三道光工序的流程图:第一道,检查自己已写的内容(掩码自注意力);第二道,抬头核对原信要点卡(交叉注意力);第三道,对每个字做深度润色加工(前馈网络)。每道工序结束后,还要用一根“安全绳”把新成果绑回原文(残差连接),并整理一遍字迹(层归一化)。
解码器要回答的问题和编码器完全不同。编码器像一位“通读全文”的读者,可以同时看到输入句子的所有词;解码器则像那位“趴在桌上逐字书写”的作家,视野永远被限制在“已经写出的前缀”上。这决定了它生成序列的本质:走一步,看一步,再走一步。
从输入侧看,解码器接收的是“已生成序列”的词嵌入,并叠加位置编码告诉模型每个字的先后顺序。每一层解码器都按“掩码自注意力 → 交叉注意力 → 前馈网络”的顺序加工,再把 N 层堆叠起来。以 GPT 为代表的模型,甚至把互注意力也省掉,只留下一个“自命题作家”。
1. $\mathbf{h}^{(l)}$ 第 l 层输出:解码器经过第 l 层加工后的隐藏状态,携带了到目前为止全部已生成词元的信息。
2. $\mathbf{h}^{(l-1)}$ 上层草稿:上一层输出的“已写内容”,掩码自注意力围绕它展开。
3. $\mathbf{H}_{\text{enc}}$ 编码器上下文:编码器对原信提炼出的要点集合,供交叉注意力随时查阅。
4. $\text{DecoderLayer}^{(l)}$ 解码器层:一次“回信加工”流水线,内部含掩码自注意力、交叉注意力、前馈三道工序。
明白了这间工作室的布局,你就能理解解码器为什么叫“自回归生成的核心引擎”:它天生就是为“逐字产出”而设计的,而不是为“理解全局”设计的。下一节,我们来看那把挡住未来的“隐私尺”。
掩码自注意力
小明的书桌上放着一把奇怪的尺子,正好压在信纸上。这把尺子的形状是三角形的:它允许作家看到自己已经写下的所有字(左上三角),却把右边还没写出的区域涂成黑色。无论作家怎么努力,都“看不见未来”。这把尺子,就是解码器里的因果掩码(causal mask)。
普通自注意力允许序列中任意两个位置互相“偷看”——就像一场讨论课,每个人都能看见所有人的发言稿。但解码器不行,它的任务是生成,如果在第 5 个位置就看到了第 10 个位置的词,那生成过程就变成了作弊。因此,解码器在自注意力打分之后、归一化之前,要往未来位置的分数上加一个极大的负数 $-\infty$,让这些位置在 softmax 之后权重变成 0。
这个掩码在实现上是一个下三角矩阵:矩阵的第 $i$ 行代表“当前正在写的位置 $i$”,第 $j$ 列代表“想去看的位置 $j$”。当 $j \le i$ 时保留分数,当 $j > i$ 时涂黑。因为这个矩阵的形状像字母的右下三角被削去,所以也叫“三角掩码”。
1. $QK^{\top}$ 相关性打分:把所有“已写字”两两配对,计算每对位置之间的关联分数。
2. $\sqrt{d_k}$ 缩放因子:特征维度越大分数越高,除以它防止 softmax 进入梯度消失区。
3. $M_{ij}$ 因果掩码:$j\le i$ 时保留分数(能看到自己及左边),$j>i$ 时设为 $-\infty$(挡住右边未来字)。
4. $\text{softmax}$ 归一化:把分数变成和为 1 的权重,$-\infty$ 处变成 0,未来位置彻底“隐身”。
5. $V$ 加权求和:按权重把“已写字”的信息聚合,得到当前位置的新表示。
有了这把“隐私尺”,作家每次落笔前都只能参考自己写过的内容。可如果只顾自己写,写跑题了怎么办?下一节,那位“抬头核对原信”的动作就要登场了。
交叉注意力
小明写回信有个习惯:每写三五个字,就要抬头看一眼桌角的“原信要点卡”,确认自己正在写的话题没有偏离原信。这个“抬头核对”的动作,在 Transformer 里就是交叉注意力(cross-attention)。它是连接编码器与解码器的桥梁。
交叉注意力的计算公式和普通注意力一模一样,唯一的区别是“谁提供什么”:查询 $Q$ 来自解码器自己——代表“此刻的作家想找什么信息”;而键 $K$ 和值 $V$ 来自编码器的输出——代表“原信要点卡里都有什么、内容是什么”。解码器用自己当前的困惑去检索原信,再把检索到的内容取回来,补充到自己正在写的字上。
为什么需要这一步?因为解码器只靠掩码自注意力的话,就像闭着眼睛凭记忆写信,写着写着就会跑题。交叉注意力让每一个生成位置都能从全局输入中“按需取用”最相关的信息。比如翻译“猫”时,解码器会在“猫”的位置给编码器中“猫”附近的向量很高的注意力权重。
1. $Q_d$ 解码器查询:来自当前“写到一半的信”,表示此刻作家想找什么信息。
2. $K_e, V_e$ 编码器键值:来自原信要点卡;$K_e$ 决定要点如何被检索,$V_e$ 是真正被取走的内容。
3. $Q_d K_e^{\top}$ 跨端打分:把“此刻想找的”和“原信里的”逐一匹配,算对齐分数。
4. $\text{softmax}(\cdot)V_e$ 取回信息:按匹配权重从原信要点中取回最相关内容,拼进当前字。
“回看原信”这个动作让生成内容始终扣题。但真正让解码器能产出整篇文章的,是那个“写一字、喂一字”的循环——也就是自回归。
自回归生成
现在,小明开始真正动笔了。他先写下一个“亲”,然后这封信的“已写部分”就变成了“亲”;他看一眼已写部分和原信要点,写下“爱”;已写部分变成“亲爱的”,再写下“的”……每一步的输出,都被立刻接在序列末尾,变成下一步的输入。这种“自己喂自己”的滚动循环,就叫自回归(autoregressive)。
从概率角度看,自回归把“生成整段序列”这件复杂的事,分解成“逐字预测”的连乘:整封信的概率,等于第一个字的概率乘以“在已知第一个字后第二个字的概率”,再乘以“在已知前两个字后第三个字的概率”……如此一直乘下去。
训练时有个小技巧叫教师强制(teacher forcing):即使模型在训练中预测错了某个字,也把“真实的字”喂给下一步,而不是把错误输出喂回去。这就像练字时老师直接把正确的范字递给你,让你照着写;而到了考试(推理)时没有标准答案,只能靠模型自己写出的字继续。
1. $y_{1:T}$ 完整输出序列:整封回信,由 $T$ 个词元按顺序组成。
2. $y_{<t}$ 已生成前缀:第 $t$ 个字之前写下的所有字,是预测下一个字时唯一能看的“草稿”。
3. $x$ 原信(输入):编码器处理过的上下文,每一步预测都要参考它。
4. $\prod$ 连乘分解:把“写完整封信”拆成“逐字写”,每一步只解决一个条件概率。
这个循环就是 GPT 生成文本的本质:每次只多出一个词,像滚雪球一样越滚越长。但“滚”上几十层之后,数字会变得不稳定——所以每道工序后都需要“安全绳”和“字迹整理”。
残差与归一化
回信写久了,小明开始手酸,字也越写越潦草。工作室里有两样装备帮他保持状态:第一样是一根“安全绳”,每完成一道工序,就把加工后的结果和加工前的草稿绑在一起,即使某一步写歪了,原始信息也不会丢;第二样是一把“字迹尺”,每绑完一次,就把当前的所有字迹重新规整一遍,让字的大小和深浅恢复正常。
在 Transformer 里,这根安全绳叫残差连接(residual connection),做法很简单:子层的输出加上子层的输入,即 $x + f(x)$。它给梯度提供了一条“高速公路”,让误差信号能直接回传到浅层,是训练深层网络不退化、不梯度消失的关键。那把字迹尺叫层归一化(layer normalization),它对每个位置的特征做标准化,让数值分布稳定在均值 0、方差 1 附近。
至于前馈网络,它是每道流程里的“深度加工车间”:对每个位置独立地做两次线性变换,中间夹一个激活函数(比如 ReLU 或 GELU),让模型能捕捉更复杂的非线性关系。编码器和解码器都有这个车间,但在解码器里,它排在三道工序的末尾。
1. $x$ 子层输入:进入一道工序前的“草稿”。
2. $f(x)$ 子层函数:可以是掩码自注意力、交叉注意力或前馈网络。
3. $x + f(x)$ 残差连接:把加工结果和原始草稿逐元素相加,为梯度留一条高速路。
4. $\text{LayerNorm}$ 层归一化:对每个位置的特征重新标准化,稳定数值、加速收敛。
装备齐了,作家终于可以稳定地写完整封信。但“落笔”本身还有讲究:下一个字到底选哪个?这就进入了推理阶段的采样策略。
推理与采样
信写到关键处,小明面前摆着好几个候选词:用最稳妥的“很高兴”,还是稍微文艺一点的“欣喜”,或是更大胆的“心花怒放”?不同的落笔风格,对应着不同的采样策略。最保守的作家每次都选概率最高的词,这叫贪婪搜索;谨慎的作家会同时留住几个候选句子,边写边比,最后挑整体最好的,这叫束搜索;有创造力的作家则会调整“冒险程度”,给冷门词一点机会,这叫温度采样。
温度采样是实践中把“保守”和“随机”拧成旋钮的方法。模型原本会对词表里的每个词打一个分数 $z_i$(logits),温度 $T$ 先把这些分数全部除以 $T$ 再送进 softmax。当 $T<1$ 时,分数之间的差距被放大,好词更好,分布尖锐,生成更确定;当 $T>1$ 时,差距被压缩,分布平坦,冷门词也有机会出场,生成更多样。
GPT 这类模型在对话场景中通常带一个“创造旋钮”,本质上就是调节温度 $T$。除此之外,Top-k 采样只允许概率最高的 k 个词参与竞争,核采样(nucleus)则动态截取概率和达到阈值的那批词,都是为了在“质量”和“惊喜”之间找平衡。
1. $z_i$ 原始分数:模型对词表第 $i$ 个词打出的 logit 分数,尚未归一化。
2. $T$ 温度系数:控制分布的“脾气”;$T<1$ 更保守,$T>1$ 更发散。
3. $z_i / T$ 分数缩放:温度把所有分数同比例放大或缩小,改变相对差距。
4. $p_i$ 采样概率:缩放后经 softmax 得到概率,按它随机落笔。
到此,“回信工作室”的全部机制已经清晰。最后我们把视角从“写回信”拉到“自由创作”——看看 GPT 如何只靠解码器就闯出一片天。
GPT与实战
如果有一天,笔友不再来信,但小明仍然想写点什么,他该怎么办?他可以把那把“交叉注意力”的尺子收起来,只保留“隐私尺”(因果掩码),然后对着自己已经写下的文字,一直往下编故事——这就是 GPT 的日常:没有编码器、没有交叉注意力,只有一堆只含掩码自注意力的解码器层,在纯文本上学习“接着写”。
GPT 的训练目标是“因果语言建模”:给定前面的词,预测下一个词,最小化“没猜中真实词”的负对数似然。这个目标和解码器的自回归天性完全吻合,所以 GPT 系列直接复用了解码器栈,并把它放大到上千亿参数。你在 ChatGPT 里输入的每一条消息,会被拼成一段历史序列,然后模型逐词预测回复,一个字一个字地“回信”给你。
实战中,解码器几乎统治了生成式 AI 的主流赛道:机器翻译用“编码器 + 解码器”把原文变成译文;代码补全工具用“解码器续写”补出整个函数体;对话机器人用“解码器逐词生成”组织回复。理解了本文的因果掩码、交叉注意力和自回归循环,你就掌握了这些系统的“最小公共内核”。
1. $p_\theta$ 模型概率:参数为 $\theta$ 的解码器给出的逐词概率;$\theta$ 就是“作家”的写作习惯。
2. $\log$ 对数:把连乘变成连加,数值更稳定,也便于求导。
3. $-\sum_{t=1}^{T}$ 负求和:把所有位置的“没猜中损失”加起来取负,构成最终要最小化的目标。
从“回信”到“自由创作”,解码器始终在重复同一件事:用过去预测未来。这正是自回归生成的核心引擎——也是今天所有生成式大模型共同的心跳。
AI 应用场景
对话式 AI 客服(ChatGPT 式助手)
阶段:推理与文本生成
解决的问题:传统客服依赖规则模板,回复僵硬、无法覆盖新问题。AI 客服用 GPT 式解码器逐词生成回复,每一步只“看”聊天历史和已经生成的词,同时借解码器内部的注意力机制延续话题,回答自然且不跑题。
具体案例:用户在电商平台问“这个耳机降噪怎么样?”,系统先拼接历史上下文,解码器逐词生成“这款耳机的降噪效果在同价位里属于第一梯队……”每生成一个词就回填到已生成序列,直到输出结束符。整段话是“回信作家”一个字一个字写出来的。
机器翻译(编码器-解码器全流程)
阶段:序列到序列生成
解决的问题:传统短语表翻译不考虑上下文,长句语序经常错乱。解码器在每一步通过交叉注意力“抬头核对原信”,既保持译文的语言通顺,又对齐原意。
具体案例:把中文摘要“提出了一种新的注意力机制”翻译成英文时,编码器先把中文提炼成要点卡,解码器第一步生成“proposes“,第二步结合已生成内容生成”a”,后续每一步都回看要点卡和已写译文,直到输出句号。
代码补全(Copilot 类工具)
阶段:代码生成
解决的问题:手写样板代码耗时,传统 IDE 自动补全只能补语法片段。基于 GPT 式解码器的代码模型把“光标前的代码”当作已生成序列,逐词预测下一个 token,能补全整个函数体甚至单元测试。
具体案例:开发者在 IDE 中输入 def fibonacci(n):,模型续写 if n <= 1: return n 等完整实现;每一步都只能看到自己刚写出的代码,这正是因果掩码保证的“不偷看未来”。
Python 演示
import numpy as np def softmax(x, axis=-1): e = np.exp(x - x.max(axis=axis, keepdims=True)) return e / e.sum(axis=axis, keepdims=True) def attn(q, k, v, mask=None): score = q @ k.T / np.sqrt(q.shape[-1]) if mask is not None: score = np.where(mask == 0, -1e9, score) return softmax(score) @ v class DecoderLayer: """单层迷你解码器:掩码自注意力 + 交叉注意力""" def __init__(self, dim=16): rng = np.random.default_rng(0) self.wq = rng.normal(0, 0.2, (dim, dim)) self.wk = rng.normal(0, 0.2, (dim, dim)) self.wv = rng.normal(0, 0.2, (dim, dim)) self.wo = rng.normal(0, 0.2, (dim, dim)) def forward(self, dec_x, enc_kv): n = len(dec_x) causal = np.tril(np.ones((n, n))) h = attn(dec_x @ self.wq, dec_x @ self.wk, dec_x @ self.wv, causal) @ self.wo h = h + attn(h @ self.wq, enc_kv @ self.wk, enc_kv @ self.wv) return h def generate(layer, enc_kv, emb, bos=0, eos=1, max_len=6): seq = [bos] for _ in range(max_len): x = emb[seq] h = layer.forward(x, enc_kv) logits = h[-1] @ emb.T nxt = int(np.argmax(logits)) seq.append(nxt) if nxt == eos: break return seq if __name__ == "__main__": emb = np.random.rand(8, 16) enc_kv = np.random.rand(4, 16) layer = DecoderLayer() print("生成词元序列:", generate(layer, enc_kv, emb))
causal = np.tril(np.ones((n, n)))生成下三角因果掩码,对角线及以下为 1,表示“只准看自己及左边”score = np.where(mask == 0, -1e9, score)被掩码的未来位置变成极大负数,softmax 后权重为 0h = attn(dec_x @ self.wq, dec_x @ self.wk, dec_x @ self.wv, causal) @ self.wo掩码自注意力:所有 Q、K、V 都来自解码器自己h = h + attn(h @ self.wq, enc_kv @ self.wk, enc_kv @ self.wv)交叉注意力:Q 来自解码器,K/V 来自编码器,并叠加残差x = emb[seq]把已生成序列变成向量表示,作为本轮输入logits = h[-1] @ emb.T只取最后一个位置的表示预测下一个词seq.append(nxt)预测词元回填序列,进入下一轮自回归
常见误区
误区我一开始以为解码器也会先读完整个输出句子,把整句话都“看”进脑子里,再一次性把答案吐出来。
正解解码器被因果掩码严格束缚,第 $t$ 步只能看到位置 1 到 $t$。就像作家被尺子挡住,看不到还没写出的字。编码器是“通读全文的读者”,解码器是“逐字续写的作家”,两者的视野完全不同。
为何常见:因为编码器确实能全局看到输入,初学者很容易把这种“全局视野”想当然地推广到解码器。
误区既然要挡住未来,直接在注意力权重矩阵里把未来位置写成 0 不就行了?
正解不能直接设 0,而是要在 softmax 之前的分数上加 $-\infty$(实现时常用 -1e9)。softmax 是全局归一化的,直接设 0 的元素仍然会被分到概率;加了 $-\infty$ 后,对应项变成 $e^{-\infty}\approx0$,权重才真正归零。
为何常见:掩码加在打分阶段、softmax 之前这一流程比较隐蔽,大多数人只记住了结果(未来不可见),没注意实现的位置。
误区训练时模型怎么跑,推理时就怎么跑——反正都是把上一段的词喂进去。
正解训练用教师强制:即使模型上一步预测错了,也把真实词元喂给下一步,加速收敛;推理没有标准答案,只能把自己预测的词元回填。这就像练字时有老师递正确范字,考试时只能靠自己的笔迹。
为何常见:两者的代码流程几乎相同,都是“输入前序词元”,初学者容易忽略词元来源的差异,而这正是“曝光偏差”问题产生的根源。
误区注意力机制必须编码器和解码器配对出现,GPT 只有解码器,应该没有注意力。
正解GPT 保留了掩码自注意力(也叫自回归注意力),只是去掉了交叉注意力。它依然在每个位置对“已生成的词元”做注意力加权,这正是它续写能力的基础。原信要点卡没了,但“回看自己草稿”的能力还在。
为何常见:教科书通常把注意力放在编码器-解码器框架里介绍,让人误以为注意力是编码器的专属组件。
面试题
Q1. 解码器中因果掩码的核心作用是?
- A.阻止当前位置看到未来词元← 正确答案
- B.降低注意力计算的复杂度
- C.增加模型的参数量
- D.将序列长度压缩一半
答案:A。因果掩码像挡住未来字的“隐私尺”,它把未来位置的分数设为 $-\infty$,使 softmax 后权重为 0,从而保证第 $t$ 步只能看到 $1\sim t$ 的词元。复杂度、参数、压缩长度都不是它的职责。
Q2. 交叉注意力中的键 K 和值 V 来自哪里?
- A.解码器的位置编码
- B.编码器的输出表示← 正确答案
- C.解码器的自注意力输出
- D.词嵌入层的词元向量
答案:B。交叉注意力中,Q 由解码器提供(“此刻想找什么”),K 和 V 来自编码器输出(“原信要点卡”)。它让每个生成位置都能从全局输入中检索相关信息,是连接编码器和解码器的桥梁。
Q3. 训练解码器时使用教师强制的含义是?
- A.用真实的目标词元作为下一步输入← 正确答案
- B.用模型自己预测的词元作为下一步输入
- C.用编码器的输出作为每一步的输入
- D.用随机采样的词元作为下一步输入
答案:A。教师强制是训练技巧:即使模型预测错了,也把真实词元喂给下一步,帮模型快速学会“正确的路”。推理时没有标准答案,只能用自己的预测回填,因此训练和推理存在分布差异。
Q4. 下列哪些属于解码器层内部的子层?
- A.掩码自注意力子层← 正确答案
- B.交叉注意力子层← 正确答案
- C.前馈网络子层← 正确答案
- D.全局池化子层
答案:ABC。解码器层由掩码自注意力、交叉注意力、前馈网络三道工序组成,外加残差连接和层归一化。全局池化常见于 CNN 分类网络,解码器里没有它。
Q5. 自回归生成过程的主要特点是?
- A.一次性并行输出整个序列
- B.逐词生成并将输出回填输入← 正确答案
- C.先生成结尾词再反推开头
- D.每步输出完全独立的词元
答案:B。自回归就是“复读机式写作”:每生成一个词,就把它接在已写序列末尾,作为下一步的输入,循环往复直到输出结束符。每一步都依赖此前生成的全部内容。
Q6. 因果掩码矩阵中 $M_{ij}$ 应设为 $-\infty$ 的条件是?
- A.当 $j \le i$ 时
- B.当 $j > i$ 时← 正确答案
- C.当 $i = j$ 时
- D.当 $i > j$ 时
答案:B。掩码矩阵里行 $i$ 表示“当前正在写的位置”,列 $j$ 表示“想去看的位置”。只有 $j>i$ 即“去偷看未来”时才应设为 $-\infty$;$j\le i$ 时保留分数,允许看自己及过往。
Q7. 关于温度采样,下列描述正确的是?
- A.温度越低分布越尖锐越保守← 正确答案
- B.温度越高生成越随机多样← 正确答案
- C.温度趋近零时接近贪婪搜索← 正确答案
- D.温度为一千时完全确定输出
答案:ABC。温度 $T$ 缩放 logits;$T$ 小则概率集中,$T\to0$ 时退化为贪婪;$T$ 大则分布平坦、随机多样,$T\to\infty$ 时接近均匀分布而非确定输出,所以 D 错误。
Q8. 与编码器相比,解码器多出的关键子层是?
- A.交叉注意力子层← 正确答案
- B.前馈网络子层
- C.位置编码子层
- D.残差连接子层
答案:A。编码器和解码器都有前馈网络、位置编码、残差连接;交叉注意力是解码器独有的“桥梁子层”,负责把编码器产出的要点接进生成过程,这是两者结构上最核心的差异。
Q9. GPT 只保留解码器却能生成文本,原因是?
- A.使用掩码自注意力逐个续写词元← 正确答案
- B.使用双向注意力遍历全文
- C.依赖外部记忆检索工具
- D.解码器可以并行生成全部词元
答案:A。GPT 用掩码自注意力保证因果性,逐词续写,不需要编码器和外部记忆。它像没有原信的自命题作家——只靠“回看自己写过的内容”就能一直写下去;双向注意力和并行生成都会破坏自回归特性。
Q10. 解码器推理阶段可用的采样解码方式有?
- A.贪婪搜索← 正确答案
- B.束搜索← 正确答案
- C.温度采样← 正确答案
- D.梯度下降
答案:ABC。推理阶段用贪婪搜索、束搜索、温度采样等策略从词表里选词;梯度下降是训练阶段更新参数的优化算法,不参与推理采样,所以排除 D。