Transformer解码器如何生成文本 — 从因果掩码到解码

Dev.to ML 2026-06-23T15:16:18.052562

Transformer解码器如何生成文本 — 从因果掩码到解码

Transformer解码器不会一次性生成整个句子。
它只预测一个词元(token)。
然后将该词元反馈回来,再预测下一个。
这个简单的循环就是现代LLM(大语言模型)生成的核心。

核心理念

Transformer解码器是为自回归生成而构建的。
这意味着:
之前的词元 → 下一个词元预测 → 重复

解码器生成隐藏表示(hidden representations)。
LM Head(语言模型头)将这些表示转换为词汇表分数。
解码策略(decoding strategy)选择实际的下一词元。

这一点很重要,因为生成质量不仅仅取决于模型。
它还取决于词元的选择方式。

关键结构

一个简化的生成流水线如下所示:

输入上下文(Input Context)
→ 解码器层(Decoder Layers)
→ 隐藏状态(Hidden State)
→ LM Head
→ Logits(logits)
→ Softmax
→ 解码策略(Decoding Strategy)
→ 下一词元(Next Token)

更紧凑地:
文本生成 = 解码器表示 + 词汇表评分 + 词元选择

解码器回答:
下一个表示应该是什么?

LM Head回答:
哪些词汇表词元是可能的?

解码策略回答:
我们实际上应该输出哪个词元?

伪代码视角

自回归解码看起来像这样:

context = prompt_tokens
while not stop:
    hidden = decoder(context)
    logits = lm_head(hidden[-1])
    probs = softmax(logits / temperature)
    next_token = decode(probs)
    context.append(next_token)

关键循环是:
预测 → 追加 → 重复

这就是为什么LLM推理是顺序的。
即使训练可以并行化,生成仍然一次只能产生一个词元。

Transformer解码器结构

一个Transformer解码器层通常包含:
- 掩码自注意力(Masked Self-Attention)
- 交叉注意力(Cross-Attention)
- 前馈网络(Feed-Forward Network)

掩码自注意力让解码器只能查看之前的词元。
交叉注意力让解码器在有输入序列时查看编码器输出。
前馈网络对每个词元表示进行变换。

对于仅解码器的LLM,交叉注意力通常被移除。
模型只从当前上下文继续生成。

因果掩码(Causal Masking)

解码器不能作弊。
当预测第5个词元时,它不能查看第6个词元。
这就是因果掩码的作用。

生成概率可以写成:
P(y₁, y₂, ..., yₜ | x) = Π P(yₜ | y₁, ..., yₜ₋₁, x)

每个词元只依赖于之前的输出词元和输入。
这一点很重要。
没有因果掩码,模型在训练期间可能会看到未来的答案。
那样在实际生成时就会失败。

具体示例

目标句子:
I love you

在训练期间,解码器输入是右移的:

输入:
I love

目标:
I love you

因此模型学习:
→ I
I → love
I love → you

在推理时,没有目标句子。
模型必须使用自己之前的输出。
这就是为什么在生成过程中错误会累积。

教师强制(Teacher Forcing)

在训练期间使用教师强制。
我们不把模型的错误预测反馈到下一步,而是输入正确的上一词元。
这使得训练更加稳定。

训练:
输入 = 正确的之前词元

推理:
输入 = 模型生成的之前词元

这个差异很重要。
一个模型在训练期间可能表现良好,但在生成期间发生漂移。
这就是为什么解码策略和评估在实际系统中很重要。

LM Head 和 Logits

解码器输出隐藏向量。
但隐藏向量并不是词元。
LM Head将隐藏向量映射到词汇表大小的分数。
这些分数被称为logits。

如果词汇表大小为50,000,LM Head输出50,000个分数。
每个分数对应一个可能的下一词元。

Logits还不是概率。
Softmax将它们转换为概率。

流水线是:
隐藏状态 → logits → 概率 → 选定的词元

温度缩放(Temperature Scaling)

温度控制概率分布变得尖锐或平坦的程度。
公式是:

pᵢ(τ) = exp(zᵢ / τ) / Σ exp(zⱼ / τ)

较低温度:
- 更尖锐的分布
- 更确定性的输出
- 更少的随机性

较高温度:
- 更平坦的分布
- 更多样化的输出
- 更多的随机性

示例:
对于logits [2, 1, 0]:
temperature = 0.5 使顶部词元更强。
temperature = 2 使排名较低的词元更有可能。

这在实践中很重要。
温度是控制创造力的最简单方法之一。

解码的含义

解码意味着从概率中选择下一个词元。
模型给出一个分布。
解码算法做出一个选择。

这个选择影响:
- 正确性
- 创造力
- 重复性
- 多样性
- 确定性
- 延迟

因此解码不是一个小的细节。
它是生成行为的一部分。

贪心解码(Greedy Decoding)

贪心解码总是选择最可能的词元。
如果概率是:
A = 0.70
B = 0.20
C = 0.10
贪心总是选择A。

它简单且快速。
但可能重复。
也可能选择一个局部好的词元,导致更差的完整句子。

束搜索(Beam Search)

束搜索保留多个候选序列。
不是只保留最好的下一个词元,而是保留最好的k条路径。
如果束大小 = 3,模型跟踪三个候选延续。

这可以改善结构化生成。
但也会减少多样性。
当k = 1时,束搜索变成贪心解码。

Top-k采样(Top-k Sampling)

Top-k采样只保留最可能的k个词元。
然后从那个较小的集合中采样。

示例:
k = 3
只能选择top 3的词元。
这防止模型选择极不可能的词元。
但仍然允许一些随机性。
Top-k在需要受控多样性时很有用。

Top-p采样(Top-p Sampling)

Top-p采样也称为核采样(nucleus sampling)。
不是保留固定数量的词元,而是保留累积概率超过p的最小集合。

示例:
词元概率:
honeycomb = 0.45
gingerbread = 0.20
donut = 0.12
cupcake = 0.04

如果p = 0.6:
honeycomb + gingerbread = 0.65
所以只有这两个词元进入采样集合。

Top-p适应模型的置信度。
这使得它比固定的Top-k更灵活。

确定性解码与随机解码

确定性解码:
- 贪心解码
- 束搜索
- 相同输入通常给出相同输出
- 适用于可预测的任务

随机解码:
- Top-k采样
- Top-p采样
- 可以生成不同的输出
- 适用于创造性任务

差异很简单:
确定性 = 选择看起来最好的路径
随机 = 从可能的路径中采样

对于编码任务,确定性设置通常很有用。
对于头脑风暴,随机设置通常更好。

编码器-解码器模型与仅解码器模型

编码器-解码器模型同时使用输入理解和输出生成。
它们适用于翻译等任务。
编码器读取源序列。
解码器生成目标序列。

仅解码器模型只使用生成堆栈。
它们根据之前的上下文预测下一个词元。
大多数GPT风格的LLM都是仅解码器。
这种架构对于开放式文本生成更简单。

实现视角

在实际推理中

查看原文