← 文章 / AI技术
Chip Huyen 2小时前 · 2026-08-31 13:52:25 · 0 阅读

生成参数详解:Temperature、Top-k、Top-p 与推理时算力

机器学习模型本质上是概率性的。假设你想知道世界上最好的 cuisine(菜系)是什么。如果问一个人这个问题,哪怕间隔一分钟问两次,得到的答案应该是一致的。但如果你问模型同样的问题,两次得到的答案可能不同。模型可能会认为越南菜有 70% 的概率被评为最佳,意大利菜有 30%,那么它就会在 70% 的情况下回答"越南菜",30% 的情况下回答"意大利菜"。

这种概率特性让 AI 在创意类任务上表现出色。创造力不就是探索常规之外的可能性、跳出固有思维框架的能力吗?

但另一方面,这种概率特性也带来了不一致和幻觉问题。对于依赖事实准确性的任务来说,这是致命的。最近我翻阅了一家我担任顾问的 AI 创业公司三个月的客户支持请求记录,发现其中五分之一的问题都源于用户不理解或不善于处理这种概率特性。

要理解 AI 的回答为什么具有概率性,我们需要了解模型是如何生成回答的,这个过程称为采样(也叫解码)。本文将分为三个部分。

  1. 采样:采样策略及采样相关变量,包括 temperature、top-k 和 top-p。
  2. 推理时算力(Test time compute):通过为推理分配更多算力(例如采样多个输出)来提升模型表现。
  3. 结构化输出:如何让模型按特定格式生成内容。

采样

给定一个输入,神经网络首先计算所有可能取值的概率,然后据此生成输出。对于分类模型来说,可能取值就是预设的类别。举例来说,如果一个模型被训练用于判断邮件是否为垃圾邮件,那么它只有两个可能的取值:垃圾邮件和正常邮件。模型会分别计算这两个取值的概率,比如垃圾邮件为 90%,正常邮件为 10%。

在生成下一个 token 时,语言模型会先计算词表中所有 token 的概率分布。

Sampling the next token based on token probabilities 对于垃圾邮件分类这类任务,输出概率最高的类别即可。如果一封邮件有 90% 的概率是垃圾邮件,那就把它归为垃圾邮件。但对于语言模型来说,总是选择最可能的 token(即**贪心采样**)会让输出变得索然无味。想象一下,无论你问什么问题,模型总是用最常见的词来回答。 我们可以不总是选最可能的下一个 token,而是根据所有可能 token 上的概率分布来采样。给定上下文 `My favorite color is ...`,如果 `red` 有 30% 的概率成为下一个 token,`green` 有 50% 的概率,那么 `red` 会被选中 30% 的次数,"green" 会被选中 50% 的次数。

温度(Temperature)

按概率分布采样下一个 token 的问题之一是,模型的创造性会受限。在上面的例子里,像 `red`、`green`、`purple` 这类常见颜色词的概率最高。于是语言模型的回答听起来像五岁小孩: `My favorite color is green.` 因为 `the` 的概率很低,模型生成诸如 `My favorite color is the color of a still lake on a spring morning.` 这类更有创意的句子的概率就很小。 温度是一种对各可能取值概率进行重新分配的方法。直观上,它会压低常见 token 的概率,从而提升稀有 token 的概率,使模型能够产生更有创意的回答。 要理解温度的工作原理,我们先退一步,看看模型是如何计算概率的。给定一个输入,神经网络会处理该输入并输出一个 logit 向量,每个 logit 对应一个可能的取值。对于语言模型来说,每个 logit 对应模型词表中的一个 token。logit 向量的长度等于词表大小。
根据 token 概率采样下一个 token

logit 越大,对应的概率越高,但 logit 本身并不是概率。logit 的总和不一定等于 1,甚至可以是负数;而概率必须是非负的。通常会用一个 softmax 层把 logit 转换成概率。假设模型的词表大小为 N,logit 向量为 \([x_1, x_2, ..., x_N]\),第 \(i\) 个 token 的概率 \(p_i\) 计算如下:

\[p_i = \text{softmax}(x_i) = \frac{e^{x_i}}{\sum_j e^{x_j}}\]

温度(temperature)是一个常量,用于在 softmax 变换之前对 logit 做调整:把每个 logit 除以温度。对于给定的温度 \(T\),第 \(i\) 个 token 的调整后 logit 为 \(\frac{x_i}{T}\)。然后对这个调整后的 logit 而不是原始的 \(x_i\) 应用 softmax。

下面用一个简单的例子说明温度对概率的影响。假设模型只有两种结果:A 和 B,最后一层输出的 logit 为 [1, 3],其中 A 的 logit 为 1,B 的 logit 为 3。

  • 不使用温度(等价于 temperature = 1)时,softmax 概率为 [0.12, 0.88],模型有 88% 的概率选 B。
  • temperature = 0.5 时,概率为 [0.02, 0.98],模型有 98% 的概率选 B。
  • temperature = 2 时,概率为 [0.27, 0.73],模型有 73% 的概率选 B。

温度越高,模型越不倾向于选最明显的那个值(logit 最大的那个),输出会更有创造性,但可能不太连贯。温度越低,模型越倾向于选最明显的那个值,输出更稳定,但可能更平淡。

下图展示了不同温度下,token B 的 softmax 概率变化情况。随着温度趋近于 0,模型选中 token B 的概率也越来越接近 1。在本例中,当温度低于 0.1 时,模型几乎总是输出 B。模型服务商通常将温度限制在 0 到 2 之间;如果你使用的是自己的模型,则可以使用任意非负温度。温度 0.7 常被推荐用于创意类场景,因为它在创造性和确定性之间取得了不错的平衡,但建议你多做实验,找到最适合自己的温度值。

Sampling the next token based on token probabilities using temperature

常见的做法是将温度设为 0,以让模型的输出更稳定。从原理上讲,温度不能真正等于 0——logit 不能除以 0。实际使用时,当我们把温度设为 0 时,模型会直接选择 logit 值最大的 token(即执行 argmax),跳过 logit 缩放和 softmax 计算。

在使用 AI 模型时,一个常见的调试技巧是观察模型针对给定输入计算出的概率分布。比如,如果概率看起来毫无规律,说明模型几乎没有学到有用的东西。OpenAI 会把模型生成的概率作为 logprobs 返回。Logprobs 即概率的对数(log probabilities),也就是取对数后的概率。在神经网络中使用对数概率,是因为它有助于缓解下溢问题:语言模型的词表大小可达 100,000,其中很多 token 的概率小到机器无法精确表示,可能被直接舍入为 0,而对数尺度能有效缓解这一现象。

Sampling the next token based on token probabilities using logprobs

Top-k

Top-k 是一种采样策略,用于在不过度牺牲模型回答多样性的前提下降低计算开销。回顾一下,为了计算所有可能取值上的概率分布,需要使用 softmax 层。Softmax 需要对所有可能取值进行两轮计算:一轮计算指数和 \(\sum_j e^{x_j}\),另一轮对每个取值计算 \(\frac{e^{x_i}}{\sum_j e^{x_j}}\)。对于词汇量很大的语言模型来说,这个过程的计算成本很高。

为了解决这个问题,在模型计算出 logits 之后,我们只取出排名前 k 的 logits,只对这 k 个 logits 做 softmax。根据应用对多样性的需求,k 可以从 50 到 500 不等,远小于模型的词汇量。模型随后从这 top k 个取值中采样。k 越小,生成的文本越可预测,但也越无趣,因为模型只能从一个较小的候选词集合中选取。

Top-p

在 top-k 采样中,候选值的数量固定为 k。但这个数量其实应该根据情境而变化。例如,给定提示 Do you like music? Answer with only yes or no.,候选值应该只有两个:yesno。而给定提示 What's the meaning of life?,候选值就应该多得多。

Top-p 也称为核采样(nucleus sampling),它允许更动态地选取采样的候选值。在 top-p 采样中,模型将最可能的下一个取值按概率降序累加,直到累计概率达到 p 为止,只保留累计概率范围内的取值。语言模型中 top-p(核采样)的常用取值通常在 0.9 到 0.95 之间。例如,top-p 为 0.9 意味着模型会考虑累计概率超过 90% 的最小候选集合。

假设所有 token 的概率如下图所示。若 top_p = 90%,则只有 yesmaybe 会被纳入考虑,因为它们的累计概率已超过 90%。若 top_p = 99%,则 yesmaybeno 都会被纳入考虑。

基于 top-p 的 token 概率采样下一个 token

与 top-k 不同,top-p 不一定能减少 softmax 的计算量。它的优势在于:只关注每个上下文中相关性最高的那组 token,因而输出在语境上更贴切。理论上,top-p 采样的好处似乎并不明显。但在实践中,top-p 表现很好,因此越来越受欢迎。

停止条件

自回归语言模型通过逐个生成 token 来产生序列。输出序列过长不仅更耗时、花费更多算力(费用),有时也会让用户感到烦扰。我们可以设定一个条件,让模型在满足条件时停止生成。

一种简单的方法是要求模型在生成到固定数量的 token 后停止。缺点是输出很可能在句子中间被截断。另一种方法是使用停止 token。例如,可以让模型在遇到 "<EOS>" 时停止生成。设定停止条件有助于降低延迟和成本。

测试时计算(Test Time Compute)

提升模型性能的一种简单方法是生成多个输出,然后挑选最好的那一个。这种方法叫做test time compute(也叫test time sampling)。

你可以把多个输出展示给用户,让他们自行挑选最合适的,也可以设计一种自动选择机制。如果你希望模型的回答保持一致,那就需要固定所有采样参数;反过来,如果你想生成多个输出并从中挑选最佳,就不应改动采样参数。

一种选择方法是挑出概率最高的输出。语言模型的输出是一串 token 序列,每个 token 都有一个由模型计算出的概率。整个输出序列的概率就是其中所有 token 概率的乘积。

考虑下面的 token 序列 [I, love, food]:

  • I 的概率为 0.2
  • I 之后生成 love 的概率为 0.1
  • Ilove 之后生成 food 的概率为 0.3

那么该序列的概率为:0.2 × 0.1 × 0.3 = 0.006。

这一过程可以用数学公式表示如下:

\[p(\text{I love food}) = p(\text{I}) \times p(\text{love}|\text{I}) \times p(\text{food}|\text{I, love})\]

实际计算时,通常使用概率的对数值更方便。乘积的对数等于对数之和,因此一个 token 序列的总对数概率,就是该序列中所有 token 对数概率的总和。

\[\text{logprob}(\text{I love food}) = \text{logprob}(\text{I}) + \text{logprob}(\text{love}|\text{I}) + \text{logprob}(\text{food}|\text{I, love})\]

由于求和的特性,更长的序列总对数概率天然偏低(log(1) = 0,而小于 1 的正数取对数后均为负值)。为了避免模型偏向输出短文本,我们用总和除以序列长度,得到平均对数概率。多次采样后,选取平均对数概率最高的那个结果。截至本文撰写时,OpenAI API 用的正是这个方法。你可以把 best_of 参数设为一个具体值(比如 10),让 OpenAI 模型从 10 个不同输出中挑出平均对数概率最高的那一个返回给你。

另一种做法是用奖励模型给每个输出打分,这在前面一节已经讨论过。前文提到的 Stitch FixGrab 都会让奖励模型或验证器给输出打分,然后挑选得分高的结果。OpenAI 也训练了验证器来辅助模型挑选数学题的解题方案(Cobbe et al., 2021)。他们发现,采样更多输出确实能带来更好的表现,但这种提升存在上限——在他们的实验中,这个拐点是 400 个输出。超过这个数量之后,性能反而开始下降,如下图所示。他们推测,随着采样数量的增加,能骗过验证器的对抗性输出出现的概率也会上升。虽然这项实验很有趣,但我并不认为会有任何生产系统真的为每个输入采样 400 个不同的输出——成本实在是太高了。

你也可以根据应用需求选择启发式策略。例如,如果你的应用需要更短的回复,就挑最短的那条;如果应用是自然语言转 SQL 查询,就挑合法且最高效的那条 SQL。 对那些需要精确答案的任务,采样多条输出很有用。比如给定一道数学题,可以让模型多次作答,再把出现次数最多的答案作为最终结果。同样地,对于选择题,模型可以挑输出最频繁的那个选项。Google 在 用 MMLU 评估 Gemini 模型时就是这么做的:他们对每道题采样 32 条输出。这种做法虽然帮 Gemini 在该基准上拿到了高分,但仅凭这种采样方式获得的成绩,很难说 Gemini 就比那些每题只生成一条输出却得分更低的模型更强。 模型越不稳定,多条采样的收益就越大。不过,对一个不稳定的模型来说,最优解其实是直接换一个。对某个项目来说,我们用 AI 从产品图片中提取特定信息。结果发现,对同一张图,模型只有一半的概率能读出来,另一半情况下它会抱怨图片太糊或文字太小看不清。于是我们对每张图最多查询三次,直到模型能成功提取为止。 虽然多条采样通常能带来一定的性能提升,但代价不菲——平均来说,生成两条输出大约是生成一条成本的两倍。

结构化输出

在实际生产中,我们常常需要模型按指定格式生成文本。结构化输出在以下两种场景中至关重要:
  1. 输出需要符合特定语法。例如,文本转 SQL 或文本转正则的任务,输出必须是合法的 SQL 语句或正则表达式;分类任务中,输出必须是合法的类别。
  2. 输出结果会被下游应用解析的任务。例如,如果用 AI 模型来撰写商品描述,你希望只提取出商品描述本身,而不要包含「这是描述内容」或「作为一个语言模型,我无法……」之类的多余文字。理想情况下,针对这类场景,模型应当直接生成结构化输出(例如带有指定键名的 JSON),方便解析。

OpenAI 是首家在文本生成 API 中引入 JSON mode 的模型厂商。需要注意的是,他们的 JSON mode 只保证输出的是合法 JSON,并不保证 JSON 内部内容的正确性。截至撰写本文时,OpenAI 的 JSON mode 尚不支持视觉模型,不过我想这只是时间问题。

生成的 JSON 也可能因为模型的停止条件而被截断,例如达到了最大输出 token 长度。如果 max token 设置得太短,输出的 JSON 会被截断,导致无法解析;如果设置得太长,模型的响应又会变得既慢又贵。

guidanceoutlines 这样的独立工具,可以让你对部分模型的输出进行结构化约束。下面是用 guidance 将输出限制在指定选项集合或正则表达式范围内的两个示例。

结构化输出采样

如何生成结构化输出

可以在 AI 技术栈的不同层面对模型输出进行约束:提示(prompting)、采样(sampling)以及微调(finetuning)。目前提示是最简单但效果最差的方式——你可以指示模型按照特定 schema 输出合法 JSON,但并不能保证模型一定会遵循这个指令。

目前,微调(finetuning)是让模型按照你期望的风格和格式生成输出的首选方案。微调可以改变模型架构,也可以不改变。比如,你可以用带有目标输出格式的样本来微调模型。虽然这并不能百分之百保证模型始终按预期格式输出,但比单纯靠提示(prompting)可靠得多。此外,微调还有一个额外好处:假设你不再需要在提示中重复格式说明和示例,那么推理成本也会随之降低。

对于某些任务,可以通过修改模型架构来保证输出格式。例如,分类任务中,你可以在基础模型的架构上添加一个分类头(classifier head),从而确保模型只输出预定义的类别之一。微调时,可以重新训练整个架构,也可以只训练这个分类头。

基于 token 概率采样下一个 token

采样和微调技术之所以同时被需要,是因为我们默认模型本身还无法做到这些。随着模型能力不断增强,我们可以期待它们在遵循指令方面越来越好。我猜测,未来用极简的提示就能让模型精确输出我们需要的内容,这些技术的重要性也会随之降低。

约束采样

约束采样(constraint sampling)是一种将文本生成引导至特定约束条件下的技术。最简单但成本也最高的方法,就是不断生成输出直到找到符合约束的结果,这一点在前文 Test Time Compute 一节中讨论过。

约束采样也可以在 token 采样阶段进行。我没能找到太多关于业界目前如何实现这一技术的公开资料。以下内容基于我个人的理解,可能存在错误,欢迎大家反馈和指正!

从高层来看,生成一个 token 时,模型会在所有满足约束的值中进行采样。回顾一下 token 生成过程:模型首先输出一个 logit 向量,每个 logit 对应一个可能的取值。在约束采样中,我们对这个 logit 向量进行过滤,只保留满足约束的值,然后再从这些有效值中采样。

根据 token 概率采样下一个 token

上面的例子中,约束条件很容易过滤。但在大多数情况下并没有这么简单:我们需要一套语法规则,明确指定每一步允许出现什么、不允许出现什么。例如 JSON 语法规定,在 { 之后不能再出现另一个 {,除非它作为字符串的一部分出现,例如 {"key": ""}

构建这套语法并将其融入采样过程并非易事。我们需要为每种期望的输出格式单独编写语法:JSON、正则表达式、CSV,等等。一些人反对约束采样,他们认为与其把资源花在约束采样上,不如用来训练模型,让模型更擅长遵循指令。

总结

我认为,对于任何希望借助 AI 解决问题的人来说,理解 AI 模型如何采样输出至关重要。概率既神奇又令人困惑。写这篇文章的过程充满乐趣,让我有机会深入探究许多好奇已久的概念。

一如既往,欢迎反馈。感谢 Han LeeLuke Metz 欣然成为我的第一批读者。

Sampling the next token based on token probabilities
原始来源: Chip Huyen

评论 (0)