解码循环的最后一步:概率分布怎么变成一个字?温度、top-k、top-p、min-p 各截掉了什么?
岔路课 · 挂在第 1 课旁边。第 1 课讲的是解码循环里最贵的那一格(读权重);这一课讲最后一格:算出 logits 之后,怎么挑出一个字。第 3 课的投机解码会用到这里的结论——它保证不变的,正是「调过温度、截过尾巴」之后的那个分布。
本课一问:每一步模型给出整个词表的 logits。一直挑最大的那个行不行?不行的话,按概率抽又会出什么事?温度、top-k、top-p、min-p 各自截掉了什么?
这一课先不碰:beam search(只在 Dig 里说一句);重复惩罚、频率惩罚这类改 logits 的技巧;投机解码(第 3 课)。
从已有出发
decode 循环每走一圈,lm_head 都吐出一整排 logits(锚点是 248,320 个)。softmax 把它们变成概率,剩下的问题只有一个:这一步输出哪个 token。
这一课为什么换例子。采样要看的是一个真模型在真前缀上给出的完整分布。锚点 27.8B 在浏览器里跑不动,我们也不下载它的权重;贯穿例句「小明把苹果给了小王」是现代白话,而我们项目的小模型只学过《三國志演義》(C3 的实验里「苹」「给」都不在它的词表里)。所以换成我们自己训练的 ref_baseline(3,688,704 个参数,验证 loss 4.640542)在古文提示后的真实 logits——提示和项目实验 exp_c13_inference.py 用的是同一组,实验课里能逐项对上。
先自己设计:每次挑概率最大的那个
最省事的规则是贪心(温度 0):永远选 logit 最大的。结果确定、可复现。
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
贪心生成(ref_baseline,提示「孔明曰:「」,128 个 token 里的开头一段):
孔明曰:「孔明有計,孔明必不用兵,卻教他去取了。」孔明曰:「孔明令孔明,先去取了城池,如何不識?吾料孔明有計,卻教他去取了城池,卻教他來降。」孔明曰:「吾已知吾計,如何不聽我?」孔……
按概率抽(温度 1、种子固定):
孔明曰:「向日交苦不戰時,霸業不恨,某自去政脫甲士卒,長然橫郎將袁軍,一同往前請降,再放汝。」左右曰:「汝恢不壓土,不可輕出,共遺借害。」 ↵ 何不準備去,在正夏侯惇忽衛弒城檄閉角上,……
重复率降到 0%、distinct-2 0.988。可你已经能读出问题:句子开始不通。下一节看为什么。
贪心的问题不是「选错了某一个」,而是每一步都选最可能的,整段就会收敛到一个最可能的循环。按概率抽能跳出循环,却带来另一个问题——长尾。
新的失败:长尾
提示「孔明曰:「」之后(温度 1),最可能的 token「孔明」概率只有 10.1%;而概率低于 0.1% 的 token 有 1,871 个,它们加起来占 20.2%。也就是说,每生成一个 token,都有约五分之一的机会抽到其中某一个几乎不可能的 token;生成 100 个 token,几乎一定会抽到好几个。一个离谱的 token 进了上下文,后面的分布全被它带偏——上面那段「通而不顺」的文字就是这么来的。
所以要做两件事:改分布的形状(温度),以及把尾巴截掉(top-k、top-p、min-p)。
截断有三种思路,都在温度之后做、截完重新归一化:
- top-k(Fan et al. 2018 用 k = 10):只留概率最高的 k 个。问题是 k 是固定的——分布很尖时第 k 名可能已经离谱,分布很平时又砍掉很多合理的候选 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条论文用例子说明固定 k 在尖和平两种分布下各自出问题;这是论证,不是证明。 出处Holtzman et al. 2019 §3.2(需联网) ↗需联网 。
- top-p(Holtzman et al. 2019):从大到小累加,留到累计概率刚好达到 p 的最小集合。留几个由分布决定。
- min-p(Nguyen et al. 2024):门槛 = p_base × 最高概率,低于门槛的全部截掉。模型越有把握,门槛越高。
试四件事(先保持第一个提示):① 拖温度,盯住左边的 logits:它一根都不动;中间的概率条和右边的熵一起变。② 点预设「贪心」,再点「纯采样 T=1」,读右栏「截掉的原始概率」与熵,再点「按这个分布抽 20 次」。③ 点预设「T=1.3 + top-p 0.9」:保留 664 个 token;再点「T=1.3 + min-p 0.1」:只保留 34 个。看下面那张小图:蓝线(top-p)随温度往上窜,绿线(min-p)涨得慢得多。④ 换到「玄德」这个提示:最可能的是一个半字(显示成 <E6 82>,它和下一个字节拼成一个汉字),这时 top-k = 1 会发生什么?
把第一个提示下的数字列成表(python 在同一组 logits 上现算,组件里对照打 ✓):
| 温度 | 熵(不截断,nats) | top-p 0.9 保留 | min-p 0.1 保留 |
|---|---|---|---|
| 0.5 | 2.15 | 16 | 2 |
| 1.0 | 5.40 | 352 | 17 |
| 1.3 | 6.20 | 664 | 34 |
| 2.0 | 6.97 | 1108 | 175 |
温度一高,分布变平,「凑够 90% 的概率」需要的 token 数暴涨,top-p 就把一整段尾巴放了进来;min-p 的门槛跟着最高概率一起降,可降得慢,留下的仍是相对像样的候选。这正是 min-p 论文想解决的「高温下既要多样又要通顺」 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条论文用人评与基准比较质量与多样性,推荐 p_base 0.05–0.1;只在它的模型与任务上成立。本页的保留个数是我们模型上的计数,不是质量结论。 出处Nguyen et al. 2024(ICLR 2025,需联网) ↗需联网 。
⚠ 常见误解
「温度改变了模型的判断。」logits 一个没变,T > 0 时排序也不变。温度只改分布的形状,也就是「第二名、第三名还有多少机会」。
「T = 0 的输出最好,因为每一步都最可能。」每一步最可能,不等于整段最好:我们的模型贪心生成时 47% 的 4-gram 在重复。
「top-p = 0.9 就是保留 90% 的词。」保留的是「累计概率刚好到 0.9 的最小集合」,个数完全由分布决定:同一个提示,T = 0.5 时 16 个,T = 2 时 1108 个。
真数据:我们项目的实测
项目实验在同一个 checkpoint、同一个提示上扫了温度 × top-p,还让 4 个提示各生成 8 条 × 128 个 token 统计重复率(读 c13-inference.json):
🔍 beam search 呢?
beam search 同时保留几条得分最高的候选序列,每步扩展、再按累计对数概率留下最好的几条。它是「确定性地找高概率序列」,和贪心同一类,所以开放式生成里同样容易重复;翻译、摘要这类答案比较确定的任务里常用。vLLM 能在 beam 之间共享 KV 块,省下的显存比并行采样还多(第 2 课)。
在演进地图上的位置
- 每一步把整段重新喂进模型
- KV cache
- 批处理:一次解码多个请求
- 连续批处理(迭代级调度)
- PagedAttention:KV 分块按需分配
- 投机解码:草稿猜、目标一次验
- 让模型自己当草稿:MTP 与专用草稿器
- 量化:每个权重少读几位
- 按 TTFT / TPOT / goodput 调度:分块 prefill、P/D 分离
- 采样:温度 → top-k → top-p → min-p
- 少存 KV:GQA / MLA / 线性注意力
证据三问
| 问 | 本课的回答 |
|---|---|
| ① 它解决什么问题? | 贪心会陷入重复循环;纯采样会被长尾带偏。温度与截断在「多样」和「通顺」之间调 |
| ② 数学上为什么? | 温度不改排序、截断后重新归一化,都是定义上的事实 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条exp(z/T) 对 z 单调;保留集合上的概率按比例放大。 出处待补 ;top-p 与 min-p 的保留个数随温度怎么变,是计数(上表) |
| ③ 实验上呢? | 哪种截断「生成得更好」只能靠实验:Holtzman 2019 用人评与统计指标支持 top-p,min-p 论文报告高温下更好 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条结论依赖模型、任务与评测方式;我们的小模型只能比重复率,不能比质量。 出处Holtzman 2019;Nguyen 2024(需联网) ↗需联网 |
一句话
温度改分布的形状,截断决定尾巴里多少 token 还有机会;top-p 看累计概率,高温时会放进一长串,min-p 跟着最高概率自适应。
回到主线
成百上千个请求一起解码,KV cache 在显存里怎么放、怎么排? → 第 2 课
第 3 课的投机解码会回到这里:它保证「输出分布不变」,这个分布指的就是目标模型经过同样的温度与截断之后的分布。
你可能会问
这一课还没有收到真实提问;你的提问会记到 05-问答记录/C13-B1.md。
- 「API 里 temperature 默认 1、top_p 默认 1,是不是就等于不截断?」 是。各家模型卡常会给推荐值(例如思考模式与非思考模式用不同的温度与 top-p),那是厂商在自己的评测上选出来的,属于实验结论。
- 「温度可以大于 2 吗?」 可以,只是分布越来越接近均匀:我们的模型在 T = 2 时熵约 6.97 nats,已经接近 ln 2048 ≈ 7.62 的上限。