Transformer解码机制基础:自回归生成与采样概述
聊Transformer解码,得先搞清楚一个核心问题——它是怎么一个词一个词往外蹦的。你想想看,我们训练完一个语言模型,给它一个“今天天气真”的提示,它要输出“好”还是“棒”?这里的关键就是解码策略。
我当年刚开始做文本生成时,以为直接选概率最大的词就行,结果模型反复输出“很好的很好的很好的”。嗯,那种体验就像复读机卡带。后来才明白,这是贪心解码的锅,它缺乏多样性。
自回归生成:一个词一个词地猜
Transformer的解码器本质是一个自回归模型。什么意思?
- 每一步只生成一个 token。
- 把新生成的 token 追加到输入序列末尾。
- 再拿这个新序列去预测下一个 token。
- 直到遇到
<eos>或达到最大长度才停。
简单说,就是用自己前面生成的词,来猜后面的词。我在优化一个对话模型时,就经常盯着这个循环看——它能直接决定回答是流畅还是卡顿。
关键点:每一步的条件概率都基于整个已生成序列,而不是只靠上一步。
下面这段伪代码很直观:
input = "今天天气真"
while True:
logits = model(input)
next_token = sample_from(logits) # 采样策略
if next_token == <eos>:
break
input = input + next_token
return input
那个 sample_from(logits) 就是整节课要聊的核心——采样策略。不同的策略会让同一个模型输出完全不同的回答。
采样策略家族:一张表看清区别
| 策略名称 | 核心行为 | 优点 | 缺点 |
|---|---|---|---|
| 贪心解码 | 每次都选概率最高的 token | 速度快,确定性高 | 严重重复,缺乏多样性 |
| Top-K 采样 | 只从概率最高的 K 个 token 中重新归一化采样 | 避免长尾词,可控 | K 值需要调参,对分布变化不敏感 |
| Top-P (nucleus) 采样 | 从累积概率超过 p 的最小集合中采样 | 自适应截断,分布更合理 | p 值也需要试 |
| 温度采样 | 用 temperature 缩放 logits 后再 softmax | 平滑控制随机性 | 温度太低≈贪心,太高≈乱来 |
我个人习惯把温度 + Top-P 组合起来用。比如做创意文案生成,温度设到 0.8,p 设 0.9,效果往往不错。
经验之谈:如果你在做机器翻译这类“确定性”任务,用贪心就够。但聊天、写故事,一定得上采样策略。
一次糟糕的项目经历
我曾经在做一个摘要生成模型时,直接用了默认的贪心解码。结果模型输出的摘要全是“然后然后然后”,跟流水账似的。后来换成 Top-P 采样,p=0.8,立马生动多了。你看,同一个模型,采样策略一换,品质天差地别。
解码流程全景图
下面这张 SVG 图把自回归生成的全流程画出来了。你可以看到模型、采样器、终止条件三者如何配合。
注意:自回归生成每步都要重新计算整个序列的注意力。如果输入序列很长,解码阶段可能成为性能瓶颈。批量推理时可以缓存 Key-Value(后面章节会细讲)。
采样策略的“软参数”
除了表里的硬策略,还有几个“软参数”你绝对不能忽略:
- 温度(temperature):大于1让分布变平(更随机),小于1让分布变尖(更确定)。我通常用 0.7~1.0 作为安全区间。
- 重复惩罚(repetition penalty):对已生成的 token 的 logits 进行衰减。我遇到过一个故事模型,不加惩罚时总是重复“他笑了一下”,加了惩罚就好多了。
- top_k 与 top_p 的组合:先截断 top_k,再对剩下的做 top_p 截断。这是我个人做长文本生成时最喜欢的组合。
你看,这些参数就像烹饪时的火候和调料——同一个菜谱,火候不同,味道完全不同。
调试建议:先从贪心开始跑通流程,然后逐步引入温度、top_p。每次只改一个参数,记录生成结果,你就能慢慢摸清每个参数的味道。
总结一下本章核心
- Transformer 解码是自回归过程:前一步输出作为后一步输入。
- 采样策略直接影响生成结果的多样性和质量。
- 常见策略有贪心、Top-K、Top-P、温度,它们各有优劣。
- 实际项目里往往需要组合使用多个策略和惩罚项。
- 调试时要一步步来,从确定性策略开始,再引入随机性。
好了,这一章我们先把解码框架搭好。接下来我会带你手把手调采样参数,告诉你哪些坑我踩过,哪些组合最稳——继续往下,别停。