首页 / 第三部分 · 大语言模型是怎么长出来的 / 第 10 篇

第 10 篇 · 第三部分 · 大语言模型是怎么长出来的

采样策略:temperature、top-k、top-p 到底在改什么

同一个模型、同一个提示,只改变采样参数,输出就可能从通顺可靠变成语无伦次。这件事刚接触时颇令人困惑:模型明明没变,只是把某个参数设为 0.9,输出风格为何判若两样?原因并不复杂——模型每一步产出的只是一张概率表,选哪个字由另一套规则决定。这篇就把这套规则逐一拆解说明。

一、模型的输出其实是一张概率表

大模型生成文字,不是一次输出一整句。它是一步一步进行的:每生成一步,模型读完前面所有内容,输出一个向量,这个向量经过末端的线性层,变成一张盖在整张词表上的概率表。

词表有多大?常见的英文分词器 5 万上下,中文或多语种能到 10 万、15 万。也就是说,模型每生成一个 token,实际上是在给这十几万个候选各算出一个分数,softmax 之后变成加起来恰好等于 1 的概率。

举个例子。给一句"今天天气真",模型下一步给出的概率表可能是这样:

候选字概率
好0.38
不错0.17
热0.11
舒服0.07
糟糕0.03
……其余十几万项合计 0.24

表出来之后,还剩一个动作没人替模型做:到底挑哪个。挑法不同,出来的句子可以天差地别。这套挑法,就是我们说的采样策略(decoding strategy)。

顺便说明,这张表不是凭空产生的。模型的每一层都在做矩阵乘法,到末端那一层把隐藏向量映射到词表大小的维度上,得到一排原始分数(logit),softmax 再把它们压成概率。所以"改采样"改的其实不是模型本身,而是拿到这张表之后的那一步挑法——模型算出来的东西一点没变。

二、贪心解码:永远选最大的那个,句子为什么会变呆

最简单的挑法叫贪心解码(greedy decoding):每一步都选概率最大的那个,上面例子里就是"好"。不掷骰子,不犹豫,输入一样,输出永远一样。

它的问题是"只看眼前一步"。语言不是每个词各自最优就能拼成好句子——很多时候得敢让第二步不那么高概率,第三步才有更好的收尾。贪心每步都抓局部最高的那个,几条局部最优的路叠起来,结果是越走越窄。

具体问题很直观:句子容易重复,像"这里真的很美很美很美";也容易循环往复,陷入刻板的套话。对于翻译、摘要这类答案基本唯一、以准确率(比如 BLEU 分数)评价的任务,贪心尚可使用。用于创作则明显不合适,它写不出让人意外的句子。

它还有个副作用容易被忽略:贪心是确定性的,温度设成 0,同一个输入跑一百遍,结果一模一样。调试时这样很方便,上线做创意类产品时却显得呆板——用户变换提问方式,模型却反复给出同一段话。

三、束搜索:多留几条路(翻译适合,聊天不适合)

束搜索(beam search)不满足于一条路。它同时保留 B 条候选(B 叫束宽,常见 4 到 10),每生成一步,把每一条的候选都往下扩展,算出累积的对数概率,再从中选出最有希望的 B 条继续走。

这里的分数是"对数概率之和",因为概率连乘会越来越小,取对数变成求和,数值上更稳也更好比较。可它带来一个新麻烦:连加的项越多分数越低,于是模型偏爱短句子,句子没写完就急着结束。所以束搜索一般要配一个长度惩罚来抵消这个倾向。

Freitag 和 Al-Onaizan 那篇 2017 年的文章,就是专门研究这些调法的:长度惩罚怎么加、要不要按句长做归一化。

束搜索在翻译任务上应用很广,因为参考答案通常就那么一个,追求的是"整句概率最高"。但把它用于开放式聊天就会失效:它挑出来的总是四平八稳的那种句子,又短又安全又重复,读起来像一份写得很拘谨的公文。聊天不需要唯一答案,需要的是有个性、有变化的表达。

想知道为什么会这样,可以观察束宽这个旋钮。束宽从 4 调到 10,模型确实能找到整句概率更高的路径,可这些路径往往长得很像,都是最"安全"的那几条。有人试过在开放生成里把束宽拉到几十,结果反而更糟——句子开始互相抄袭,翻来覆去还是同一个意思。

四、temperature:给概率分布升降温

温度大概是所有参数里最出名的一个。它的操作简单到只有一行:在做 softmax 之前,先把每个 logit 除以一个数 T。

pi = softmax( zi / T )

这里 z 是模型输出的原始分数(logit),T 就是温度。理解它不用死记公式,想象手里这张概率表被加热或者降温,每种温度下它的表现并不相同:

  • T 小于 1,降温。分数被放大,差距拉开,概率分布变得更尖锐、更自信。T = 0.1 时几乎等于贪心。
  • T 等于 1,不升不降,用的就是模型原本的那张表。
  • T 大于 1,升温。分数被压平,原本很低的候选也被拉上来,分布变得平坦、随机。

温度其实是在调节分布的"熵"。熵高,模型对下一步没有把握;熵低,模型十分确定。有人拿这个性质反过来做检测:如果某一步的熵突然升高,往往说明模型开始不确定、开始编造内容。温度调高,相当于人为把熵抬高,这也是它为什么更容易带来"通顺但没内容"的原因。

常用的对话温度在 0.7 左右。想让它更稳定,就往下调;想让它更发散,就往上调。T 超过 1.5 时,模型经常输出语法通顺但逻辑断裂的句子——这不是模型损坏,而是低概率分支被一并放大了。

五、top-k:只在前 k 个里抽签

纯按温度采样有个隐患:词表十几万项,尾部那许多概率只有万分之几的词也都有机会被抽中。偶尔抽中一个极不合理的词,整句话就会偏离原意。

top-k 的思路是划一条硬线:只看概率最高的 k 个候选,其余一律归零,然后在这 k 个里面重新归一化、再抽签。k 常见取 50 或者 100。

k 等于 1 时它退化成贪心。k 太大(比如等于词表大小)就失去了筛选作用;k 太小,比如 k = 3,候选池一直很小,模型又会变得死板。Fan 等人 2018 年在做故事生成时提出了 top-k 采样,当时解决的就是"采样太散、句子不连贯"这个问题。

它的局限在于 k 是个固定值,无法判断当前这一步该开放还是该保守。有时分布很尖,前 10 个就占了九成概率,保留 50 个完全没有必要;有时分布很平,留 50 个又舍弃了太多有希望的候选。

六、top-p:让候选池动态伸缩

top-p(也叫核采样,nucleus sampling)把那条线从"按个数"改成"按概率质量"。做法是:把候选按概率从高到低排好,一个个往下累加,累计概率刚超过 p 就停,停止点之前的那批词就是候选池。

它的巧妙之处在于候选池会自动伸缩。分布尖的时候,可能头两个词就凑够 0.9,池子就只有两个;分布平的时候,要纳入几十个词才能凑够 0.9,池子自动变大。翻译时收紧、创作时放开,同一个 p 能应付两种局面。

Holtzman 等人那篇著名的 The Curious Case of Neural Text Degeneration(2019)就是在批评纯采样:他们说概率分布那条长长的尾巴会让模型越写越乱,然后给出 top-p 作为解法。这篇现在基本是所有推理框架默认配置的来源。

常用取值 p 在 0.9 到 0.95。p 等于 1 就是不做截断,回到纯采样。

七、重复惩罚和其他调味料

光调温度和截断还不够,模型有时会陷入重复。于是有了一批专门抑制重复的旋钮:

  • 重复惩罚(repetition penalty):已经出现过的 token,下一步它的 logit 被直接除以一个大于 1 的系数,等于扣分。常见 1.1 到 1.3。
  • 频率惩罚(frequency penalty):出现次数越多,惩罚越重,按次数线性地扣。
  • 出现惩罚(presence penalty):只要出现过,不管几次,统一施加一次惩罚,鼓励引入新词。
  • 禁止重复 n-gram:直接规定任意长度为 n 的片段不许出现第二次,专门针对"我爱我爱我爱"。

这些参数的作用位置都在采样那一步,不涉及模型权重,改起来零成本。但它们处理的是症状而非根源——模型反复重复,多半是因为训练数据里这类片段太多,或者提示词始终没有提供新信息,模型只能把已知内容反复重述。

这些参数不宜调得过度。重复惩罚调到 1.5 以上,模型会开始刻意避开常用词,句子变得生硬甚至出现语法错误——因为像"的""了"这种高频虚词也被一起压制了,可它们本来就该反复出现。

八、一份实用的调参清单

各家框架里参数名字五花八门,归纳下来其实分场景就那么几组:

场景temperaturetop-p备注
事实问答 / 抽取0 到 0.31(关掉)要的是稳定和复现
代码生成0 到 0.21 或很接近错了就是错了,不容侥幸
日常对话0.70.9最通用的一组
创意写作 / 头脑风暴0.9 到 1.10.95允许偶尔偏离

几条经验:top-k 和 top-p 一般只保留一个作为主控,两个都调到极端,候选池会被削减得毫无道理。要复现结果就固定随机种子(seed)。同一个 prompt 运行三次结果不一样,多半就是温度没设成 0。

还有一点容易被忽略:温度、top-p 这些参数调不出知识。模型不知道的事,任何采样参数都无法创造出来;它只能在已知的分布里决定"更稳定还是更发散"。指望靠调温度提升准确率,方向就错了。

九、同一句话在不同参数下的样子

拿"用一句话介绍上海"当例子,感受一下差别:

  • 温度 0:上海是中国最大的经济中心城市,位于长江入海口。 —— 稳,像词典条目。
  • 温度 0.7:上海是座很有烟火气的城市,外滩的灯火和弄堂里的小笼包都挺出名。 —— 有细节,读着自然。
  • 温度 1.3:上海啊,一座把时间折成地铁线路的城市,黄浦江边风一吹,连梦都在排队过闸机。 —— 有韵味,但已经开始飘忽,再写几句大概率无法连贯。

三句话没有绝对的优劣,只取决于你想要什么。要准确,选第一条;要自然一些,选第二条;要新鲜感,第三条,代价是稳定性大幅下降。

采样策略这事,本质上是在"确定性"和"多样性"之间调节一个平衡点。理解每个旋钮调节的是哪一部分,比记住一组推荐值有用得多——毕竟同一套参数,换个模型、换个任务,效果可能完全不同。

参考资料

  1. Ari Holtzman, Jan Buys, Li Du, Maxwell Forbes, Yejin Choi, The Curious Case of Neural Text Degeneration, ICLR 2020. arXiv:1904.09751(top-p 核采样的出处)
  2. Angela Fan, Mike Lewis, Yann Dauphin, Hierarchical Neural Story Generation, ACL 2018. arXiv:1805.04833(top-k 采样的提出)
  3. Markus Freitag, Yaser Al-Onaizan, Beam Search Strategies for Neural Machine Translation, 2017. arXiv:1708.00762(束搜索与长度惩罚)
  4. Patrick von Platen, How to generate text: using different decoding methods for language generation with Transformers, Hugging Face Blog, 2020. huggingface.co/blog/how-to-generate(各采样方法的可运行对照)