详细解释
Top-K 采样(Top-K Sampling) 与 Top-P(核采样) 并列,是大模型 解码 阶段最常见的两种随机采样策略之一。
模型每一步生成下一个 Token 时,其实会对词表中每一个 Token 输出一个概率(比如 GPT-3.5 词表 100K,每一步就是 100K 个概率值)。如果纯贪婪(Greedy)解码,每次都取概率最大的那个——结果呆板、重复、像机器人。如果对全部 100K 都随机采样,长尾里大量奇怪的词(如生僻字、错拼、乱码)被抽中概率飙升——输出容易”放飞自我”。
Top-K 的做法很直觉:
先把词表按概率从大到小排序,只保留前 K 个,把剩下的全部概率置 0,然后把这 K 个的概率归一化后再采样。
K 的取值:一般取 10(比较确定)、40(OpenAI 旧默认)、50(平衡),极端场景可以取 1(等于 Greedy)或 100 以上(非常发散)。现在主流 SDK 里 Top-K 默认往往关闭(由 Top-P 接管),两者可以叠加生效。
与 Temperature、Top-P 的关系(采样三件套)
| 策略 | 控制目标 | 典型值 | 什么时候开 |
|---|---|---|---|
| Temperature | 概率分布”尖锐度”,T→0 越贪婪,T→∞ 越均匀 | 0.0 – 2.0 | 每次必设,默认 0.7–1.0 |
| Top-P | 累计概率门槛,保留候选到累计概率 ≥ p 为止 | 0.0 – 1.0,默认 0.9–1.0 | 和 Temperature 配合 |
| Top-K | 候选数量上限,不管概率多少最多 K 个 | 1 – 100,常用 10/40/50 | 想”硬卡上限”防止抽到完全无关词 |
三者叠加顺序(按主流框架实现):
- 先过 Temperature 对 logits 做缩放;
- 再过 Top-K 截断长尾;
- 剩下的 Token 再过 Top-P 截断累计概率尾部;
- 最终的小集合做加权采样。
实践建议:如果你已经设了合理的 Top-P(比如 0.9),Top-K 可以不设(或设一个非常大的 K,如 1000 等价于关闭),两者作用重叠,容易过度收敛。唯元智创 对所有接入方的默认参数是
temperature=1.0, top_p=1.0, top_k=0(关闭),推荐你只改 temperature,需要更严格再叠 Top-K。
示例:K=3 时采样过程(假设词表共 5 个候选)
| Token | 原始概率 | Top-K=3 后(保留前 3) | 归一化后实际采样概率 |
|---|---|---|---|
| “今天” | 0.60 | 0.60 ✅ | 0.60 / (0.60+0.25+0.10) = 0.632 |
| “明天” | 0.25 | 0.25 ✅ | 0.263 |
| “昨天” | 0.10 | 0.10 ✅ | 0.105 |
| “前天” | 0.04 | ❌ 被截为 0 | 0 |
| “去年” | 0.01 | ❌ 被截为 0 | 0 |
没有 Top-K 时,“前天”和”去年”虽然概率低,但仍可能被抽中——尤其在 Temperature 很高的情况下。Top-K 相当于给了个硬性数量门槛。
常见问题
Top-K 和 Top-P 我应该用哪个?
为什么 OpenAI 的 Python SDK 里没有 top_k 参数?
temperature + top_p 两个,没有暴露 Top-K。Top-K 在开源推理框架(vLLM、SGLang、HuggingFace generate)里常见。像 唯元智创 这类聚合平台如果接了开源模型供应商,会在兼容层把 Top-K 透传给底层。