壁纸神器
122.67M · 2026-04-06
调用 LLM 时,你是否好奇为何同一提示词每次生成的回答不尽相同?决定模型是严谨还是发散的,正是 Temperature(温度) 和 Top-p(核采样) 。
这两个参数直接干预生成时的概率分布,是控制模型输出风格的核心。本文将深入底层原理,拆解它们如何重塑概率分布。掌握这两者,不仅是精准控制模型输出的关键,更是理解 LLM 推理机制的最佳切入点。
附代码库:jiangya-66/python-learn
参考:py-day8.py 采样参数对比:测试temperature和top_p对LLM输出的影响
作用:控制概率分布的平滑程度,影响随机性大小。
简单理解:高温加大“冒险”,低温让模型“保守”。
作用:从累积概率达到 p 的最小词汇集合中采样,动态调整候选词数量。
简单理解:p 越小,可选词越少,输出越确定。
| 参数 | 控制方式 | 候选集变化 | 常用范围 |
|---|---|---|---|
| temperature | 重塑概率分布 | 所有词,但概率权重改变 | 0.1~1.5 |
| top_p | 动态裁剪词汇表大小 | 只保留累积概率前 p 的词 | 0.7~0.95 |
常见组合策略:
temperature=0.1~0.3,top_p=0.1~0.3temperature=0.8~1.2,top_p=0.9~0.95temperature=0.7,top_p=0.9注意:
temperature 和 top_p 不能同时修改,只能调其一(如 OpenAI 旧版建议)。top_p=0.9,然后单独调整 temperature 观察效果;或者反过来。理解概率和概率分布是真正掌握 temperature 和 top_p 的基础。下面我从头拆解。
大模型最后一层输出的不是概率,而是一个分数向量,每个分数对应一个词(token)。这些分数叫 logits。
举例(假设词汇表只有5个词):
词: "猫" "狗" "鸟" "鱼" "虫"
logits: [5.2, 3.1, 2.4, 1.0, -0.5]
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
关键性质:
概率分布的形状决定了采样的行为。
词: "猫" "狗" "鸟" "鱼" "虫"
概率: 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
Temperature 操作是在 softmax 之前:将 logits 除以 T。
新 logits = 原 logits / T
原始 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): ██ █ █ ▏ ▏
核心原理:
极端情况:
Top-p 在 softmax 之后操作,直接作用在概率分布上。
步骤:
原始分布:
词: "猫" "狗" "鸟" "鱼" "虫"
概率: 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)
关键:丢弃“鱼”和“虫”后,它们的概率被按比例重新分配给保留的词。
原始分布: [0.85, 0.10, 0.03, 0.01, 0.01]
p=0.5: 只保留 "猫" (0.85 ≥ 0.5)
结果: 100% 选 "猫"
原始分布: [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.68 ≥ 0.5)
结果: 从 {猫,狗,鸟} 中按 [0.37, 0.34, 0.29] 采样
高温使分布变平坦 → 原始分布 [0.25,0.23,0.20,0.18,0.14]
p=0.95: 保留所有5个词
结果: 多样性最高
| 参数 | 作用时机 | 对概率分布的操作 |
|---|---|---|
| Temperature | Softmax 之前 | 缩放 logits,改变分布的陡峭/平坦程度 |
| Top-p | Softmax 之后 | 裁剪低概率词,改变分布的有效支撑集大小 |
一句话理解:
可视化类比:
不是的。
模型最终只返回 一个词(或者几个词,如果设置了 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:
然后采样:
最终返回:
B
(只有 B,不是 {A, B, C})
如果你设置 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} 等信息,但模型实际输出仍然是采样得到的那一个词。
在 LLM 推理(生成)时,最重要的参数可以分为控制输出形态和控制生成行为两类。
| 参数 | 作用 | 常见范围 | 备注 |
|---|---|---|---|
| temperature | 控制随机性/创造性 | 0 | 越低越确定,越高越随机 |
| top_p | 动态控制候选词池大小 | 0.8~0.95 | 与 temperature 配合使用 |
| max_tokens / max_new_tokens | 限制生成长度 | 视任务而定 | 防止无限生成或超预算 |
| stop | 停止符 | 字符串或列表 | 如 ["n", "。", "Q:"] |
| 参数 | 作用 | 何时使用 |
|---|---|---|
| top_k | 固定候选词数量 | 需要严格限制候选集大小时 |
| frequency_penalty | 降低已出现词的重复概率 | 减少重复循环、增加多样性 |
| presence_penalty | 惩罚已出现过的主题/词 | 鼓励引入新话题(不关注具体频次) |
| n | 生成几个独立候选结果 | 需要多个答案备选时 |
| seed | 固定随机种子 | 需要结果可复现时 |
第一层:基础结构
├── max_tokens(必须设,否则可能无限生成)
└── stop(强烈建议设,控制结束边界)
第二层:随机性控制(核心取舍)
├── temperature(主要控制)
└── top_p(辅助控制,通常固定 0.9 左右)
第三层:多样性增强(按需)
├── frequency_penalty
├── presence_penalty
└── top_k
第四层:调试/复现
└── seed
temperature = 0.1
top_p = 0.3
max_tokens = 适当
stop = ["nn"] 或合适的边界
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 # 固定种子
| 参数 | 作用 | 为什么重要 |
|---|---|---|
| logprobs | 返回每个生成词的对数概率 | 调试、置信度评估、质量监控 |
| echo | 是否在输出中包含输入 prompt | 调试 prompt 效果 |
| best_of(部分 API) | 生成 n 个选最好的 | 提高质量但增加成本 |
| logit_bias | 手动调整特定词的 logits | 禁止某些词或偏向某些词 |
如果你第一次用某个模型:
max_tokens 和 stop(防止跑飞)top_p = 0.9(比较安全的默认值)temperature:
frequency_penalty(如果仍重复)top_k 或 presence_penalty(精细优化)