本文主要简单介绍 LLM 推理时的生成方式(偏简单记录)
整体说明
- 本文是简单记录了一些重点参数
- 关于 vLLM 的详细说明可以参考:NLP——vLLM使用相关笔记
Greedy-search
- 说明:每一时间步都选择概率最大的词
- 参数设置:
do_sample = False, num_beams = 1 - 缺点:生成文本可能出现重复现象
- 此时,生成结果仅一条,若
num_return_sequences参数大于1,代码会报错,说 Greedy Search 不支持这个参数大于 1 - 注意:当
do_sample=False时,temperature、top_k、top_p等采样相关参数均不会生效- 因为这些参数的作用是 “调整概率采样的规则”,而
do_sample=False本质是完全跳过 “概率采样” 流程,直接采用贪心搜索(每一步仅选概率最高的 token),自然无需依赖这些采样参数 - 记忆:
do_sample是生成策略的 “总开关”,其优先级远高于temperature/top_k/top_p
- 因为这些参数的作用是 “调整概率采样的规则”,而
Beam-search
- 说明:表示每一时刻均保留得分最高的 k 个序列,然后下一时刻用这 k 个序列继续生成
- 参数设置:
do_sample = False, num_beams = N(N > 1) - 缺点:仍然可能出现重复现象;会耗费更多算力
- 此时,会生成多条结果
Multinomial sampling
- 说明:多项式采样 ,每一个时间步,根据概率分布随机采样字(每个概率>0的字都有被选中的机会)
- 参数设置:
do_sample = True, num_beams = 1 - 优点:解决了生成重复的问题
- 缺点:可能会出现生成的文本不准守基本的语法
Beam-search multinomial sampling
- 说明:Beam-search和Multinomial sampling的结合体,每个时间步从num_beams个字中采样
- 参数设置:
do_sample = True, num_beams = N(N > 1) - 优点:解决了重复生成的问题;效果相对num_beams=1效果也更好
- 缺点:会耗费更多算力
- 此时会同时生成多个结果,可通过参数
num_return_sequences控制返回数量
惩罚重复:repetition_penalty
说明:在每步时对之前出现过的词的概率做出惩罚,即降低出现过的字的采样概率,让模型趋向于解码出没出现过的词
参数设置:
repetition_penalty(float,取值范围>0)。默认为1,即代表不进行惩罚。值越大,即对重复的字做出更大的惩罚代码实现逻辑:
1
score = torch.where(score < 0, score*penalty, score/penalty)
- 一般来说:
penalty>1.0, 所以以下结论: - 如果字的概率
score<0, 则score = score*penalty, 概率会越低; - 如果字的概率
score>0, 则score = score/penalty, 同样概率也会变低
- 一般来说:
惩罚重复:presence_penalty
presence_penalty是大模型里用来调节文本生成多样性的参数,presence_penalty作用机制是:如果某个 token 已经在已生成的文本中出现过,就给它的 logits 减去一个固定值(由presence_penalty控制)- 这样,模型会更倾向于选择那些还没出现过的新 token,从而减少重复、增加内容的新颖度
- 取值范围:通常在 0 到 2 之间。0 表示不做任何惩罚,值越大越鼓励引入新概念
- 经验值:从 0.5 开始尝试,若发现内容重复严重,可逐步提高到 1.0 左右;
- 若希望更保守,可设为 0.1-0.3
- 需结合
temperature和top_p等其他参数一起调优 - 问题:为什么范围规定为 0-2?理论上可以把
presence_penalty设到 2 以上,但实际没必要,原因主要有三点:- 边际效应递减 :随着值增大,对已出现 token 的惩罚强度线性增加,但带来的“新信息”增量却越来越小。超过 2 之后,几乎不会再显著提升多样性,反而容易让文本变得跳跃、不连贯
- 稳定性风险 :大模型本身对 logits 的微小变化就比较敏感。值过大(>2)会剧烈扭曲概率分布,导致生成结果不可控,甚至出现语法错误或逻辑断裂
- 经验验证上限 :主流框架(如 OpenAI、vLLM 等)在大量实验中发现,0–2 这个区间已经能覆盖从“轻微去重”到“强创新”之间的全部常用需求,因此把 2 设为硬上限,避免用户误用极端值
惩罚 n-gram:no_repeat_ngram_size
- 说明:限制n-gram在生成结果中出现次数
- 参数设置:
no_repeat_ngram_size- 限制n-gram不出现2次。 (no_repeat_ngram_size=6即代表:6-gram不出现2次)
- 用于控制重复词生成,默认是0,如果为
N>0,则相应N-gram只出现一次
- 要非常慎重使用
Temperature
- 说明:通过温度,控制每个字的概率分布曲线。温度越低,分布曲线越陡峭,越容易采样到概率大的字。温度越高,分布曲线越平缓,增加了低概率字被采样到的机会
- 参数设置:
temperature(取值范围:0-1)设的越高,生成文本的自由创作空间越大;温度越低,生成的文本越偏保守 - 本质是对softmax函数前的数据进行降温
$$
p_i = \frac{e^{\frac{y_i}{temperature}}}{\sum_i e^{\frac{y_i}{temperature}}}
$$
Top-K 采样
- 说明:每个时间步,会保留topK个字,然后对topk个字的概率重新归一化,最后在重新归一化后的这K个字中进行采样
- 参数设置:
top_k - 缺点:在分布陡峭的时候仍会采样到概率小的单词,或者在分布平缓的时候只能采样到部分可用单词
top_k=0(或 -1):不限制,包含所有 token
Top-P 采样(又称 Nucleus Sampling)
- 说明:每个时间步,按照字出现的概率由高到底排序,当概率之和大于top-p的时候,就不取后面的样本了。然后对取到的这些字的概率重新归一化后,进行采样
- 参数设置:
top_p(取值范围:0-1) - top-P采样方法往往与 top-K 采样方法结合使用,每次选取两者中最小的采样范围进行采样,可以减少预测分布过于平缓时采样到极小概率单词的几率
长度惩罚:length_penalty
说明:长度惩罚,
Exponential penalty to the length that is used with beam-based generation.仅在Beam Search的数量大于1时生效
常规的Beam Search句子的得分为概率取对数再求和,是一个负数(由对数单调性可知选择更大的得分对应的序列)
$$
sumLogProbs = \sum_{t=1}^{T} \log P(y_t|y_0,y_1,\cdot,y_{t-1})
$$进一步地,经过长度惩罚的分数修正如下:
$$
seqScore = \frac{sumLogProbs}{tokenLen^{length\_penalty}}
$$所以
length_penalty大于0时分母大于1且随长度单调递增,从而得分也随长度单调递增,等价于鼓励生成长文本。反之,鼓励生成短文本代码实现如下:
1
seq_score = sum_log_probs / len(hyp) ** self.length_penalty
参数设置:
length_penalty, 默认是1.01
2
3
4length_penalty=1.0 # beam search分数会受到生成序列长度的惩罚
length_penalty=0.0 # 无惩罚
length_penalty<0.0 # 鼓励模型生成短句子
length_penalty>0.0 # 鼓励模型生成长句子