LLM学习笔记-文本生成解码策略

 

前言

GPT类模型本质上是自回归语言模型,通过预测下一个词来逐步生成文本。不同的解码策略会显著影响生成文本的质量、多样性和创造性。


一、GPT-2 的核心流程

1.1 基本工作流程

text

输入 → 预测下一个词 → 拼接到输入 → 重复直到完成

1.2 生成案例

生成5个词的过程:

text

输入:"I have a dream"
↓
第1次预测 → "about"    → "I have a dream about"
第2次预测 → "my"       → "I have a dream about my"  
第3次预测 → "future"   → "I have a dream about my future"
第4次预测 → "in"       → "I have a dream about my future in"
第5次预测 → "the"      → "I have a dream about my future in the"

1.3 关键特性

特点 说明
自回归 每次生成1个词,依赖前面所有词
贪心 每次都选概率最高的词(基本策略)
递推 新词立即加入上下文,继续预测

1.4 理论基础

理论上,预测下一个词需要计算所有已知序列的联合概率

text

P(w₁w₂...wₙ) = P(w₁) × P(w₂|w₁) × P(w₃|w₁w₂) × ... × P(wₙ|w₁...wₙ₋₁)

GPT的简化机制:

  • 最后一个token的隐藏状态已经编码了所有前面token的信息
  • 预测时只需使用最后一个token的表示,无需重新处理整个序列
  • 这大幅提升了计算效率

二、解码策略详解

核心思想

每次从词表(vocab)中选择概率最大的一个token,只考虑当前步的局部最优。

示例流程

步骤 输入 最可能的token
Step 1 “I have a dream” ” of”
Step 2 “I have a dream of” ” being”
Step 3 “I have a dream of being” ” a”
Step 4 “I have a dream of being a” ” doctor”
Step 5 “I have a dream of being a doctor” ”.”

优缺点

优点 缺点
计算速度快 短视问题:只考虑局部最优,忽略全局
实现简单 容易产生重复、平庸的文本
确定性输出 缺乏创造力,无法生成多样化内容

核心问题

每一步选择概率最高的词,但概率最高的单步选择不一定导致全局最优的句子

示例:

  • 第1步:”a” 的概率 0.5 vs “the” 的概率 0.45
  • 贪心选”a”,但后续”beautiful”概率很高 → “a beautiful…”
  • 但如果选”the”,后续”most important”概率极高 → “the most important…”
  • 贪心选择了当下的0.5,错失了未来的更高概率组合

核心思想

维护K个最优候选路径(K = beam size),每一步都保留K个最可能的token组合,最终选择联合概率最高的完整序列。

工作原理

text

Beam Size = 2 的示例:

第1步:从所有token中选概率最高的2个
        "I have a" → "dream"(0.4), "vision"(0.3)
        
第2步:每条路径各扩展2个候选,共4条路径
        路径1: "dream" → "about"(0.3), "of"(0.25)
        路径2: "vision" → "for"(0.2), "of"(0.15)
        排序后保留综合概率最高的2条
        保留: "dream about"(0.12), "dream of"(0.10)
        
第3步:继续扩展,重复直到结束
        最终从所有路径中选择得分最高的完整序列

路径数量对比

时间步 Greedy路径数 Beam Search路径数(beam=2)
第1步 1 2
第2步 1 4 (2²)
第3步 1 8 (2³)
第k步 1 2ᵏ

优缺点

优点 缺点
考虑全局最优,比贪心更优 计算成本高(2ᵏ倍)
能找到概率更高的序列 仍然倾向于重复、无创造力的文本
适合翻译、摘要等任务 无法产生多样性,容易陷入”平庸陷阱”

2.3 Top-k 采样

核心思想

引入随机性,打破确定性选择,提升生成文本的创造力和多样性。

工作流程

text

Step 1: 计算所有token的概率
Step 2: 按概率排序,只保留概率最高的k个token
Step 3: 对保留的k个token重新归一化(重新计算概率)
Step 4: 从重归一化后的分布中随机采样

具体案例(k=5)

假设原始概率分布:

Token 原始概率 排名
“the” 0.45 1
“a” 0.25 2
“an” 0.12 3
“my” 0.08 4
“our” 0.05 5
“some” 0.03 6 ← 丢弃
“any” 0.02 7 ← 丢弃

重新归一化后:

Token 原始概率 重归一化概率
“the” 0.45 0.45/0.95 ≈ 0.474
“a” 0.25 0.25/0.95 ≈ 0.263
“an” 0.12 0.12/0.95 ≈ 0.126
“my” 0.08 0.08/0.95 ≈ 0.084
“our” 0.05 0.05/0.95 ≈ 0.053

关键效果:

  • 原本概率很小的token(如”our” 0.05 → 0.053)概率略微提升
  • 所有保留的token都有机会被选中,而不是只选最大的

随机采样

python

# 使用 torch.multinomial 根据概率随机选择
next_token = torch.multinomial(probabilities, 1)
# 概率高的被选中的概率大,但不保证一定被选中

优缺点

优点 缺点
引入随机性,输出更丰富 k值选择主观,没有统一标准
避免完全重复和平庸 k值固定,不能自适应
比贪心更有创造力 可能偶尔选到不合理的词(如果k设太大)

k值的影响:

  • k太小 → 确定性高,多样性不足
  • k太大 → 可能选到低质量token,文本质量下降

2.4 核采样(Nucleus Sampling / Top-p Sampling)

核心思想

不固定选择前k个token,而是动态选择累积概率超过阈值p的最小token集合,从这组token中采样。

为什么优于Top-k?

Top-k的问题 Nucleus的解决方案
k值固定,无法自适应 根据概率分布动态调整候选集大小
概率集中时,k可能太大(包含不合理词) 自动缩小候选集
概率分散时,k可能太小(漏掉合理词) 自动扩大候选集

详细工作流程

text

Step 1: 按概率降序排序所有token
Step 2: 计算累积概率
Step 3: 找到累积概率首次超过p的位置,作为截断点
Step 4: 只保留截断点之前的token
Step 5: 对保留的token重新归一化
Step 6: 从新分布中随机采样

完整案例(p=0.7)

场景:概率集中分布

排名 Token 概率 累积概率 是否保留
1 “the” 0.50 0.50 ✅ 保留 (0.50 < 0.7)
2 “a” 0.25 0.75 ❌ 停止 (0.75 > 0.7)

结果:只保留1个token,”the”被选中概率≈100%,几乎变成贪心。


场景:概率分散分布

排名 Token 概率 累积概率 是否保留
1 “the” 0.20 0.20 ✅ 保留 (0.20 < 0.7)
2 “a” 0.18 0.38 ✅ 保留 (0.38 < 0.7)
3 “an” 0.15 0.53 ✅ 保留 (0.53 < 0.7)
4 “my” 0.12 0.65 ✅ 保留 (0.65 < 0.7)
5 “our” 0.10 0.75 ❌ 停止 (0.75 > 0.7)

结果:保留4个token,候选集自动扩大,保持多样性。


重归一化和采样

保留token后,重新归一化并随机采样:

python

# 重新归一化
new_probs = original_probs[top_p_indices] / sum(original_probs[top_p_indices])

# 随机采样
next_token = torch.multinomial(new_probs, 1)

参数影响

参数 p=0.9(大) p=0.3(小)
候选集大小 较大(包含更多token) 较小(只包含最高概率token)
多样性
确定性
风险 可能选到不合理词 可能过于保守

常用设置:

  • 创意写作:p=0.9-0.95,temperature=0.8-1.0
  • 事实性任务:p=0.5-0.7,temperature=0.6-0.8

三、策略对比总结

策略 选择方式 多样性 质量 计算成本 适用场景
贪心搜索 选最大概率 极低 中等(可能重复) 最低 确定性任务
Beam Search 保留K条最优路径 高(但可能平庸) 翻译、摘要
Top-k 从Top-k中随机采样 中等 中等 中等 故事生成
Nucleus 动态选择累积概率<p的token 较高 创意写作、对话

四、Temperature的作用

Temperature影响所有采样策略的概率分布平滑度:

python

logits = logits / temperature
probabilities = softmax(logits)
Temperature 效果 适用场景
T < 1 概率分布更集中,高概率token概率更高 需要确定性的任务
T = 1 保持原始分布 标准采样
T > 1 概率分布更平坦,低概率token概率提升 需要创造力的任务

示例(Top-k=3):

Token 原始概率 T=0.5后 T=1.5后
“the” 0.50 0.75 0.40
“a” 0.30 0.22 0.33
“an” 0.20 0.03 0.27

五、实用经验

  1. 起点用贪心:先跑贪心,看模型的基本输出质量
  2. 逐步增加随机性:从Top-k开始,再尝试Nucleus
  3. 温度配合使用:temperature+Top-p是工业界最常用组合
  4. 根据任务调整
    • 新闻/事实 → 低温度 + 小p值
    • 故事/创意 → 高温度 + 大p值
  5. 多样性惩罚:可额外使用repetition_penalty减少重复