内容概要
- 调用 LLM 时,你是否好奇为何同一提示词每次生成的回答不尽相同?决定模型是严谨还是发散的,正是 Temperature(温度) 和 Top-p(核采样)。
- 这两个参数直接干预生成时的概率分布,是控制模型输出风格的核心。本文将深入底层原理,拆解它们如何重塑概率分布。掌握这两者,不仅是精准控制模型输出的关键,更是理解 LLM 推理机制的最佳切入点。
- 附代码库:jiangya-66/python-learn
参考文件:py-day8.py —— 采样参数对比:测试 temperature 和 top_p 对 LLM 输出的影响
下篇:LLM调参必知:max_tokens + stop参数详解
1. 核心参数概览
1.1 Temperature(温度)
作用:控制概率分布的平滑程度,影响随机性大小。
- 低温度(<1.0,如 0.1~0.5):概率分布更陡峭,模型倾向选择高概率词 → 输出更确定、保守、连贯。适合事实问答、代码生成。
- 高温度(>1.0,如 1.2~2.0):概率分布更平坦,低概率词被更多选中 → 输出更有创造性、意外性,但可能逻辑变差或胡言乱语。
- temperature=1:保持原始概率分布。
- temperature→0(实际常用 0.1):近似贪婪解码,几乎总是选最高概率词。
简单理解:高温加大“冒险”,低温让模型“保守”。
1.2 Top-p(核采样,nucleus sampling)
作用:从累积概率达到 p 的最小词汇集合中采样,动态调整候选词数量。
- 低 p(如 0.1~0.3):只考虑概率最高的少数词 → 输出更集中、可控。
- 高 p(如 0.9~0.95):考虑更多可能词,保留占概率质量 90% 的词汇集合 → 输出更丰富、多样。
- p=1:考虑所有词,等同于不限制(但仍受概率分布影响)。
简单理解:p 越小,可选词越少,输出越确定。
1.3 两者对比与配合
| 参数 | 控制方式 | 候选集变化 | 常用范围 |
|---|---|---|---|
| temperature | 重塑概率分布 | 所有词,但概率权重改变 | 0.1~1.5 |
| top_p | 动态裁剪词汇表大小 | 只保留累积概率前 p 的词 | 0.7~0.95 |
常见组合策略:
- 确定性任务(代码、公式、事实回答):
temperature=0.1~0.3,top_p=0.1~0.3 - 创意任务(故事、诗歌、头脑风暴):
temperature=0.8~1.2,top_p=0.9~0.95 - 平衡模式:
temperature=0.7,top_p=0.9
注意:
- 一般不要同时极端调低两者(如 temp=0.1 且 p=0.1),否则输出会极其重复甚至死循环。
- 有些 API 要求
temperature和top_p不能同时修改,只能调其一(如 OpenAI 旧版建议)。 - 实际使用建议:先固定
top_p=0.9,然后单独调整temperature观察效果;或者反过来。
2. 从概率分布理解 Temperature 与 Top-p
理解概率和概率分布是真正掌握
temperature和top_p的基础。
2.1 模型输出的原始东西:Logits
大模型最后一层输出的不是概率,而是一个分数向量,每个分数对应一个词(token)。这些分数叫 logits。
- 特点:可以是任意实数(正、负、零),没有上下限,也不满足概率公理(不非负、不加起来为1)。
示例(假设词汇表只有5个词):
词: "猫" "狗" "鸟" "鱼" "虫"
logits: [5.2, 3.1, 2.4, 1.0, -0.5]
数值越大,表示模型认为该词越可能,但 5.2 并不是概率。
2.2 Softmax:从 Logits 到概率分布
Softmax 函数将 logits 转换为概率分布(所有值在 0~1 之间,且和为 1)。
公式:P(词_i) = e^(logit_i) / Σ e^(logit_j)
对上面例子计算(示意值):
词: "猫" "狗" "鸟" "鱼" "虫"
logits: 5.2 3.1 2.4 1.0 -0.5
概率: 0.72 0.18 0.07 0.02 0.01
关键性质:
- 较大的 logit → 更大的概率(指数放大差距)
- 较小的 logit → 极小的概率
- 输出是一个概率分布,描述模型对“下一个词应该是什么”的信念
2.3 概率分布的形状:陡峭 vs 平坦
- 陡峭分布(高确定性):一个词占绝对主导,如
[0.85, 0.10, 0.03, 0.01, 0.01] - 平坦分布(高不确定性):多个词概率接近,如
[0.25, 0.23, 0.20, 0.18, 0.14] - 中间分布:有主导词但存在合理备选,如
[0.50, 0.25, 0.15, 0.06, 0.04]
2.4 Temperature 如何改变概率分布
操作时机:在 softmax 之前,将 logits 除以 T:新 logits = 原 logits / T
效果对比(原始 logits: [5.2, 3.1, 2.4, 1.0, -0.5]):
| Temperature | 新 logits 近似 | 概率分布形状 | 效果 |
|---|---|---|---|
| 0.5(低温) | [10.4, 6.2, 4.8, 2.0, -1.0] | 极陡峭 | “猫”概率→0.97,其他极低 |
| 1.0 | 不变 | 原始分布 | 0.72, 0.18, 0.07... |
| 1.5(高温) | [3.47, 2.07, 1.60, 0.67, -0.33] | 变平坦 | “猫”概率↓0.60,其他↑ |
核心原理:
- T < 1:放大 logits 差距(强者更强)
- T = 1:不变
- T > 1:缩小 logits 差距(趋向均匀)
极端情况:
- T → 0:只有最大 logit 对应的词概率 → 1(贪婪解码)
- T → ∞:所有词概率相等(均匀分布,完全随机)
2.5 Top-p 如何基于概率分布裁剪
操作时机:在 softmax 之后,直接作用在概率分布上。
步骤:
- 将词按概率从大到小排序
- 从最大的开始累加概率
- 当累积概率 ≥ p 时停止
- 保留这些词,丢弃其他词
- 在保留的词中重新归一化概率(和为1)
详细示例(p=0.9):
原始分布: [0.50, 0.25, 0.15, 0.06, 0.04]
累积: [0.50, 0.75, 0.90, 0.96, 1.00]
保留 保留 保留 丢弃 丢弃
候选集 = {猫, 狗, 鸟},重新归一化后概率约为 [0.556, 0.278, 0.166]
2.6 Temperature + Top-p 协同示例
| 场景 | 分布 | 参数 | 结果 |
|---|---|---|---|
| 陡峭分布 + 低 p | [0.85, 0.10, 0.03, 0.01, 0.01] | p=0.5 | 只保留“猫”,100% 选“猫” |
| 平坦分布 + 低 p | [0.25, 0.23, 0.20, 0.18, 0.14] | p=0.5 | 保留 {猫,狗,鸟},按 [0.37,0.34,0.29] 采样 |
| 高温 + 高 p | 平坦分布 | p=0.95 | 保留所有词,多样性最高 |
2.7 总结:概率分布视角
| 参数 | 作用时机 | 对概率分布的操作 |
|---|---|---|
| Temperature | Softmax 之前 | 缩放 logits,改变分布的陡峭/平坦程度 |
| Top-p | Softmax 之后 | 裁剪低概率词,改变分布的有效支撑集大小 |
一句话理解:Temperature 决定了概率分布是“尖峰”还是“丘陵”,Top-p 决定了你是从整个山脉中采样,还是只从主峰群采样。
可视化类比:
- 原始分布 = 一座山,主峰高,周围有小丘
- 低温 = 山变得更尖,只有主峰突出
- 高温 = 山变平缓,多个山峰高度接近
- 低 p = 只画主峰群,砍掉远处的孤立小山包
- 高 p = 画整个山脉
3. 常见误区:模型会返回所有“保留的词”吗?
不会。 模型最终只返回一个词(或设置 n > 1 时返回多个独立结果)。
完整流程
1. 模型计算 logits(所有词的分数)
2. 应用 temperature(缩放 logits)
3. Softmax 得到概率分布(所有词都有概率)
4. Top-p 裁剪(保留部分词,丢弃其余)
5. 【关键】从保留的词中【随机采样】一个词
6. 返回这个被选中的词
示例
- 保留池 = {A, B, C},概率归一化后为
[0.444, 0.333, 0.223] - 随机采样抽中 B
- 最终返回:
B(不是{A, B, C})
特殊情况:n > 1
- 模型独立重复上述过程 n 次,返回 n 个独立结果(每个仍是单个词或文本)
为什么会有这个误解?
可能混淆了 Top-p 与 Top-k 展示(如 logprobs 参数):
top_p:控制采样池大小,最终只返回 1 个词logprobs+top_logprobs:返回前 k 个词及其概率(仅用于查看,不作为输出)
4. LLM 中最重要的参数全景
4.1 最核心的 4 个参数(几乎每次调用都用)
| 参数 | 作用 | 常见范围 | 备注 |
|---|---|---|---|
| temperature | 控制随机性/创造性 | 0 | 越低越确定,越高越随机 |
| top_p | 动态控制候选词池大小 | 0.8~0.95 | 与 temperature 配合使用 |
| max_tokens / max_new_tokens | 限制生成长度 | 视任务而定 | 防止无限生成或超预算 |
| stop | 停止符 | 字符串或列表 | 如 ["\n", "。", "Q:"] |
4.2 次重要但常用的参数
| 参数 | 作用 | 何时使用 |
|---|---|---|
| top_k | 固定候选词数量 | 需要严格限制候选集大小时 |
| frequency_penalty | 降低已出现词的重复概率 | 减少重复循环、增加多样性 |
| presence_penalty | 惩罚已出现过的主题/词 | 鼓励引入新话题 |
| n | 生成几个独立候选结果 | 需要多个答案备选时 |
| seed | 固定随机种子 | 需要结果可复现时 |
4.3 参数的作用层次(优先级)
第一层:基础结构
├── max_tokens(必须设,否则可能无限生成)
└── stop(强烈建议设,控制结束边界)
第二层:随机性控制(核心取舍)
├── temperature(主要控制)
└── top_p(辅助控制,通常固定 0.9 左右)
第三层:多样性增强(按需)
├── frequency_penalty
├── presence_penalty
└── top_k
第四层:调试/复现
└── seed
4.4 最佳实践组合
| 任务类型 | 推荐配置 |
|---|---|
| 确定性任务(代码、公式、事实问答) | temperature=0.1, top_p=0.3, 设置合适的 stop |
| 创意任务(故事、诗歌、头脑风暴) | temperature=0.8~1.2, top_p=0.9, frequency_penalty=0.3~0.5, presence_penalty=0.3~0.5 |
| 平衡对话/通用场景 | temperature=0.7, top_p=0.9, frequency_penalty=0.1~0.2 |
| 可复现的调试场景 | temperature=0.7, top_p=0.9, seed=42 |
4.5 实际调试顺序建议
- 固定
max_tokens和stop(防止跑飞) - 固定
top_p = 0.9(比较安全的默认值) - 调整
temperature:- 太重复/无聊 → 升高 temperature
- 太乱/逻辑错 → 降低 temperature
- 按需调整
frequency_penalty(如果仍重复) - 最后调
top_k或presence_penalty(精细优化)
一句话总结:
temperature和top_p控制“怎么选词”,max_tokens和stop控制“什么时候停”,这 4 个是最不可缺的参数。频率惩罚类参数在需要多样性时再加入,seed只在需要可复现时使用。