LLM调参必知:Temperature 与 Top-p 原理解析

0 阅读10分钟

Temperature 与 Top-p 原理解析

  • 调用 LLM 时,你是否好奇为何同一提示词每次生成的回答不尽相同?决定模型是严谨还是发散的,正是 Temperature(温度)Top-p(核采样)

  • 这两个参数直接干预生成时的概率分布,是控制模型输出风格的核心。本文将深入底层原理,拆解它们如何重塑概率分布。掌握这两者,不仅是精准控制模型输出的关键,更是理解 LLM 推理机制的最佳切入点。

  • 附代码库:jiangya-66/python-learn
    参考:py-day8.py 采样参数对比:测试temperature和top_p对LLM输出的影响

1. Temperature(温度)

作用:控制概率分布的平滑程度,影响随机性大小。

  • 低温度(<1.0,如 0.1~0.5):概率分布更陡峭,模型倾向选择高概率词 → 输出更确定、保守、连贯。适合事实问答、代码生成。
  • 高温度(>1.0,如 1.2~2.0):概率分布更平坦,低概率词被更多选中 → 输出更有创造性、意外性,但可能逻辑变差或胡言乱语。
  • temperature=1:保持原始概率分布。
  • temperature→0(实际常用 0.1):近似贪婪解码,几乎总是选最高概率词。

简单理解:高温加大“冒险”,低温让模型“保守”。

2. Top-p(核采样,nucleus sampling)

作用:从累积概率达到 p 的最小词汇集合中采样,动态调整候选词数量。

  • 低 p(如 0.1~0.3):只考虑概率最高的少数词 → 输出更集中、可控
  • 高 p(如 0.9~0.95):考虑更多可能词,保留占概率质量 90% 的词汇集合 → 输出更丰富、多样
  • p=1:考虑所有词,等同于不限制(但仍受概率分布影响)。

简单理解:p 越小,可选词越少,输出越确定。

3. 两者对比与配合

参数控制方式候选集变化常用范围
temperature重塑概率分布所有词,但概率权重改变0.1~1.5
top_p动态裁剪词汇表大小只保留累积概率前 p 的词0.7~0.95

常见组合策略

  • 确定性任务(代码、公式、事实回答):temperature=0.1~0.3top_p=0.1~0.3
  • 创意任务(故事、诗歌、头脑风暴):temperature=0.8~1.2top_p=0.9~0.95
  • 平衡模式temperature=0.7top_p=0.9

注意

  • 一般不要同时极端调低两者(比如 temp=0.1 且 p=0.1),否则输出会极其重复甚至死循环。
  • 有些 API 要求 temperaturetop_p 不能同时修改,只能调其一(如 OpenAI 旧版建议)。
  • 实际使用建议:先固定 top_p=0.9,然后单独调整 temperature 观察效果;或者反过来。

上面的内容太抽象,让人云里雾里? 接下来将拨云见日...

LLM概率以及概率分布

理解概率概率分布是真正掌握 temperaturetop_p 的基础。下面我从头拆解。

一、模型输出的原始东西:Logits

大模型最后一层输出的不是概率,而是一个分数向量,每个分数对应一个词(token)。这些分数叫 logits

Logits 的特点:可以是任意实数(正、负、零),没有上下限,也不满足概率公理(不非负、不加起来为1)。

举例(假设词汇表只有5个词):

词:    "猫"   "狗"   "鸟"   "鱼"   "虫"
logits: [5.2,  3.1,  2.4,  1.0,  -0.5]
  • 数值越大,表示模型认为该词越可能
  • 但这里 5.2 并不是概率(因为 5.2 > 1)

二、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

验证:0.72 + 0.18 + 0.07 + 0.02 + 0.01 = 1.00 ✅

关键性质

  • 较大的 logit → 更大的概率(指数放大差距)
  • 较小的 logit → 极小的概率(负数 logit 会变成很小的正数)
  • 输出是一个概率分布:描述了模型对“下一个词应该是什么”的信念

三、概率分布的形状:陡峭 vs 平坦

概率分布的形状决定了采样的行为。

1. 陡峭分布(高确定性)

词:     "猫"    "狗"    "鸟"    "鱼"    "虫"
概率:    0.85    0.10    0.03    0.01    0.01
  • 一个词(猫)占绝对主导
  • 采样几乎总是选“猫”
  • 出现在:模型非常确定时

2. 平坦分布(高不确定性)

词:     "猫"    "狗"    "鸟"    "鱼"    "虫"
概率:    0.25    0.23    0.20    0.18    0.14
  • 没有明显主导词
  • 多个词都有机会被选中
  • 出现在:模型犹豫不决时(如开放性问题)

3. 中间分布

词:     "猫"    "狗"    "鸟"    "鱼"    "虫"
概率:    0.50    0.25    0.15    0.06    0.04
  • 有主导词,但也有合理的备选

四、Temperature 如何改变概率分布

Temperature 操作是在 softmax 之前:将 logits 除以 T。

logits = 原 logits / T

效果对比(用上面的 logits 例子)

原始 logits: [5.2, 3.1, 2.4, 1.0, -0.5]

Temperature操作新 logits 近似概率分布形状效果
0.5 (低温)除以 0.5 = 乘 2[10.4, 6.2, 4.8, 2.0, -1.0]极陡峭"猫"概率→0.97,其他极低
1.0不变[5.2, 3.1, 2.4, 1.0, -0.5]原始分布0.72, 0.18, 0.07...
1.5 (高温)除以 1.5[3.47, 2.07, 1.60, 0.67, -0.33]变平坦"猫"概率↓0.60,其他↑

可视化理解

低温 (T=0.5):     ████  █     ▏     ▏     ▏
原始 (T=1.0):     ███   ██    ▏     ▏     ▏
高温 (T=1.5):     ██    █     █     ▏     ▏

核心原理

  • T < 1:放大 logits 之间的差距(强者更强)
  • T = 1:不变
  • T > 1:缩小 logits 之间的差距(趋向均匀)

极端情况

  • T → 0:只有最大 logit 对应的词概率 → 1(贪婪解码)
  • T → ∞:所有词概率相等(均匀分布,完全随机)

五、Top-p 如何基于概率分布裁剪

Top-p 在 softmax 之后操作,直接作用在概率分布上。

步骤

  1. 将词按概率从大到小排序
  2. 从最大的开始累加概率
  3. 当累积概率 ≥ p 时停止
  4. 保留这些词,丢弃其他词
  5. 在保留的词中重新归一化概率(和为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.90

重新归一化

猫的新概率 = 0.50 / 0.90 ≈ 0.556
狗的新概率 = 0.25 / 0.90 ≈ 0.278
鸟的新概率 = 0.15 / 0.90 ≈ 0.166
(总和=1.00)

关键:丢弃“鱼”和“虫”后,它们的概率被按比例重新分配给保留的词。


六、两个例子看懂 Temperature + Top-p 的协同

场景 A:陡峭分布 + 低 p

原始分布: [0.85, 0.10, 0.03, 0.01, 0.01]
p=0.5:    只保留 "猫" (0.850.5)
结果:    100% 选 "猫"
  • top_p 的“裁剪”在陡峭分布下几乎没影响(反正只留一个词)

场景 B:平坦分布 + 低 p

原始分布: [0.25, 0.23, 0.20, 0.18, 0.14]
p=0.5:    保留 "猫"+"狗" (0.25+0.23=0.48 < 0.5? 需要加下一个)
          保留 "猫"+"狗"+"鸟" (0.25+0.23+0.20=0.680.5)
结果:    从 {猫,狗,鸟} 中按 [0.37, 0.34, 0.29] 采样
  • 平坦分布 + 低 p 会强制截断很多合理的候选词

场景 C:高温 + 高 p

高温使分布变平坦 → 原始分布 [0.25,0.23,0.20,0.18,0.14]
p=0.95:   保留所有5个词
结果:    多样性最高

七、总结:概率分布视角

参数作用时机对概率分布的操作
TemperatureSoftmax 之前缩放 logits,改变分布的陡峭/平坦程度
Top-pSoftmax 之后裁剪低概率词,改变分布的有效支撑集大小

一句话理解

Temperature 决定了概率分布是“尖峰”还是“丘陵”,Top-p 决定了你是从整个山脉中采样,还是只从主峰群采样。

可视化类比

  • 原始分布 = 一座山,主峰高,周围有小丘
  • 低温 = 山变得更尖,只有主峰突出
  • 高温 = 山变平缓,多个山峰高度接近
  • 低 p = 只画主峰群,砍掉远处的孤立小山包
  • 高 p = 画整个山脉

模型最终返回所有的“保留的词”吗?

不是的

模型最终只返回 一个词(或者几个词,如果设置了 n > 1),而不是返回所有“保留的词”。

让我把这个过程讲清楚:


完整流程

1. 模型计算 logits(所有词的分数)
         ↓
2. 应用 temperature(缩放 logits)
         ↓
3. Softmax 得到概率分布(所有词都有概率)
         ↓
4. Top-p 裁剪(保留部分词,丢弃其余)
         ↓
5. 【关键】从保留的词中【随机采样】一个词
         ↓
6. 返回这个被选中的词

Top-p 的裁剪只是中间步骤,目的是限定“采样池”,而不是最终输出所有池中的词。


详细例子

假设经过 softmax 后得到分布:

词:      A     B     C     D     E
概率:   0.40  0.30  0.20  0.07  0.03

设置 p=0.8

  • 累积:A(0.40) → B(0.70) → C(0.90) 已经超过 0.8
  • 保留池 = {A, B, C}
  • 重新归一化:A=0.40/0.90≈0.444, B≈0.333, C≈0.223

然后采样

  • 随机抽一个,概率按 44.4%、33.3%、22.2%
  • 假设抽到 B

最终返回

B

(只有 B,不是 {A, B, C})


特殊情况:n > 1

如果你设置 n=3(生成 3 个候选结果),模型会独立重复这个过程 3 次,返回 3 个词(或 3 段文本)。

返回:
[
  "B",    # 第一次采样
  "A",    # 第二次采样  
  "C"     # 第三次采样
]

但每次采样仍然只返回一个词,不是返回整个池。


为什么会有这个误解?

可能把 Top-p 和 Top-k 展示(如 logprobs 参数)混淆了。

参数作用返回内容
top_p控制采样池的大小最终只返回 1 个词
logprobs要求返回前 k 个词的概率返回前 k 个词 + 它们的概率(仅用于查看,不作为输出)

示例(OpenAI API):

{
  "logprobs": True,
  "top_logprobs": 3  # 返回概率最高的 3 个词供查看
}

这会额外返回 {"token": "A", "logprob": -0.91} 等信息,但模型实际输出仍然是采样得到的那一个词。


一句话总结

Top-p 决定“从哪些词里抽”,但不改变“只抽一个词”的结果。
保留池是内部的候选集,不是输出内容。最终输出只有一个词(除非明确设置 n>1 生成多个独立结果)。

LLM中最重要的参数有哪些

在 LLM 推理(生成)时,最重要的参数可以分为控制输出形态控制生成行为两类。

一、最核心的 4 个参数(几乎每次调用都会用到)

参数作用常见范围备注
temperature控制随机性/创造性01(或 02)越低越确定,越高越随机
top_p动态控制候选词池大小0.8~0.95与 temperature 配合使用
max_tokens / max_new_tokens限制生成长度视任务而定防止无限生成或超预算
stop停止符字符串或列表["\n", "。", "Q:"]

这四个参数几乎每个生产级 LLM API 都支持。


二、次重要但常用的参数

参数作用何时使用
top_k固定候选词数量需要严格限制候选集大小时
frequency_penalty降低已出现词的重复概率减少重复循环、增加多样性
presence_penalty惩罚已出现过的主题/词鼓励引入新话题(不关注具体频次)
n生成几个独立候选结果需要多个答案备选时
seed固定随机种子需要结果可复现时

三、参数的作用层次(理解优先级)

第一层:基础结构
├── max_tokens(必须设,否则可能无限生成)
└── stop(强烈建议设,控制结束边界)

第二层:随机性控制(核心取舍)
├── temperature(主要控制)
└── top_p(辅助控制,通常固定 0.9 左右)

第三层:多样性增强(按需)
├── frequency_penalty
├── presence_penalty
└── top_k

第四层:调试/复现
└── seed

四、最常见的最佳实践组合

1. 确定性任务(代码、公式、事实问答)

temperature = 0.1
top_p = 0.3
max_tokens = 适当
stop = ["\n\n"] 或合适的边界

2. 创意任务(故事、诗歌、头脑风暴)

temperature = 0.8~1.2
top_p = 0.9
frequency_penalty = 0.3~0.5
presence_penalty = 0.3~0.5

3. 平衡对话/通用场景

temperature = 0.7
top_p = 0.9
frequency_penalty = 0.1~0.2
(其他默认)

4. 可复现的调试场景

temperature = 0.7
top_p = 0.9
seed = 42  # 固定种子

五、容易被忽略但重要的参数

参数作用为什么重要
logprobs返回每个生成词的对数概率调试、置信度评估、质量监控
echo是否在输出中包含输入 prompt调试 prompt 效果
best_of(部分 API)生成 n 个选最好的提高质量但增加成本
logit_bias手动调整特定词的 logits禁止某些词或偏向某些词

六、一个实际建议的调试顺序

如果你第一次用某个模型:

  1. 固定 max_tokensstop(防止跑飞)
  2. 固定 top_p = 0.9(比较安全的默认值)
  3. 调整 temperature
    • 太重复/无聊 → 升高 temperature
    • 太乱/逻辑错 → 降低 temperature
  4. 按需调整 frequency_penalty(如果仍重复)
  5. 最后调 top_kpresence_penalty(精细优化)

一句话总结

temperature 和 top_p 控制“怎么选词”,max_tokens 和 stop 控制“什么时候停”,这 4 个是最不可缺的参数。
频率惩罚类参数在需要多样性时再加入,seed 只在需要可复现时用。