Top-K vs Top-P:生成式模型中的采样策略与 Temperature 的影响

在之前的文章中我们探讨了 Beam Search 和 Greedy Search。

现在来聊聊 model.generate() 中常见的三个参数: top-k, top-p 和 temperature。

代码文件下载

在线链接:Kaggle | Colab


在生成文本时,模型为每个可能的下一个词汇分配一个概率分布,选择下一个词汇的策略直接决定了输出的质量和多样性。以下是几种常见的选择方法:

  • Greedy Search(贪心搜索): 每次选择概率最高的词汇。
  • Beam Search(束搜索): 保留多个候选序列,平衡生成质量和多样性。
  • Top-K 采样: 限制候选词汇数量。
  • Top-P 采样(Nucleus Sampling): 根据累积概率选择候选词汇,动态调整词汇集。

为了直观叙述,假设我们当前的概率分布为:

词汇概率
A A A 0.4 0.4 0.4
B B B 0.3 0.3 0.3
C C C 0.2 0.2 0.2
D D D 0.05 0.05 0.05
<eos> \texttt{<eos>} <eos> 0.05 0.05 0.05

Top-K 采样详解

工作原理

Top-K 采样是一种通过限制候选词汇数量来增加生成文本多样性的方法。在每一步生成过程中,模型只考虑概率最高(Top)的 K 个词汇,然后从这 K 个词汇中根据概率进行采样。K=1 就是贪心搜索。

步骤:

  1. 获取概率分布: 模型为每个可能的下一个词汇生成一个概率分布。
  2. 筛选 Top-K: 选择概率最高的 K 个词汇,忽略其余词汇。
  3. 重新归一化: 将筛选后的 K 个词汇的概率重新归一化,使其总和为 1。
  4. 采样: 根据重新归一化后的概率分布,从 Top-K 词汇中随机采样一个词汇作为下一个生成的词。

数学表述

V V V 为词汇表, P ( y ∣ Y ) P(y|Y) P(yY) 为在给定上下文 Y Y Y 下生成词汇 y y y 的概率。

  1. 筛选出概率最高的 K 个词汇,记为 V k V_k Vk

  2. 重新计算这些词汇的概率(归一化):

P ′ ( y ∣ Y ) = P ( y ∣ Y ) ∑ y ′ ∈ V k P ( y ′ ∣ Y ) P'(y|Y) = \frac{P(y|Y)}{\sum_{y' \in V_k} P(y'|Y)} P(yY)=yVkP(yY)P(yY)

  1. V k V_k Vk 中根据 P ′ ( y ∣ Y ) P'(y|Y) P(yY) 进行采样。

代码示例

我们假设 K=3

import numpy as np

# 概率分布
probs = np.array([0.4, 0.3, 0.2, 0.05, 0.05])
words = ['A', 'B', 'C', 'D', '<eos>']

# 设置 Top-K
K = 3

# 获取概率最高的 K 个词汇索引
top_indices = np.argsort(probs)[-K:]

# 保留这些 K 个词汇及其概率
top_k_probs = np.zeros_like(probs)
top_k_probs[top_indices] = probs[top_indices]

# 归一化保留的 K 个词汇的概率
top_k_probs = top_k_probs / np.sum(top_k_probs)

# 打印 Top-K 采样的结果
print("Top-K 采样选择的词汇和对应的概率:")
for i in top_indices:
    print(f"{words[i]}: {top_k_probs[i]:.2f}")

输出:

Top-K 采样选择的词汇和对应的概率: 
C: 0.22
B: 0.33
A: 0.44

Top-P 采样详解

工作原理

Top-P 采样(又称 Nucleus Sampling)是一种动态选择候选词汇的方法。与 Top-K 采样不同,Top-P 采样不是固定选择 K 个词汇,而是选择一组累计概率达到 P 的词汇集合(即从高到低加起来的概率)。这意味着 Top-P 采样可以根据当前的概率分布动态调整候选词汇的数量,从而更好地平衡生成的多样性和质量。

步骤:

  1. 获取概率分布: 模型为每个可能的下一个词汇生成一个概率分布。
  2. 排序概率: 将词汇按照概率从高到低排序。
  3. 累积概率: 计算累积概率,直到达到预设的阈值 P。
  4. 筛选 Top-P: 选择累积概率达到 P 的最小词汇集合。
  5. 重新归一化: 将筛选后的词汇概率重新归一化。
  6. 采样: 根据重新归一化后的概率分布,从 Top-P 词汇中随机采样一个词汇作为下一个生成的词。

数学表述

V V V 为词汇表, P ( y ∣ Y ) P(y|Y) P(yY) 为在给定上下文 Y Y Y 下生成词汇 y y y 的概率。

  1. 将词汇按照概率降序排列,得到排序后的词汇列表 V s o r t e d V_{sorted} Vsorted

  2. 选择最小的词汇集合 V p ⊆ V s o r t e d V_p \subseteq V_{sorted} VpVsorted,使得:

∑ y ∈ V p P ( y ∣ Y ) ≥ P \sum_{y \in V_p} P(y|Y) \geq P yVpP(yY)P

  1. 重新计算这些词汇的概率:

P ′ ( y ∣ Y ) = P ( y ∣ Y ) ∑ y ′ ∈ V p P ( y ′ ∣ Y ) P'(y|Y) = \frac{P(y|Y)}{\sum_{y' \in V_p} P(y'|Y)} P(yY)=yVpP(yY)P(yY)

  1. V p V_p Vp 中根据 P ′ ( y ∣ Y ) P'(y|Y) P(yY) 进行采样。

代码示例

我们假设 P=0.6

import numpy as np

# 概率分布
probs = np.array([0.4, 0.3, 0.2, 0.05, 0.05])
words = ['A', 'B', 'C', 'D', '<eos>']

# 设置 Top-P
P = 0.6

# 对概率进行排序
sorted_indices = np.argsort(probs)[::-1]  # 从大到小排序
sorted_probs = probs[sorted_indices]

# 累积概率
cumulative_probs = np.cumsum(sorted_probs)

# 找到累积概率大于等于 P 的索引
cutoff_index = np.where(cumulative_probs >= P)[0][0]

# 保留累积概率达到 P 的词汇及其概率
top_p_probs = np.zeros_like(probs)
top_p_probs[sorted_indices[:cutoff_index + 1]] = sorted_probs[:cutoff_index + 1]

# 归一化保留的词汇的概率
top_p_probs = top_p_probs / np.sum(top_p_probs)

# 打印 Top-P 采样的结果
print("\nTop-P 采样选择的词汇和对应的概率:")
for i in np.where(top_p_probs > 0)[0]:
    print(f"{words[i]}: {top_p_probs[i]:.2f}")
Top-P 采样选择的词汇和对应的概率: 
A: 0.57
B: 0.43

Temperature 的作用

Temperature(温度) 是控制生成文本随机性的参数。

工作原理

在进行采样前,模型实际上会对概率分布应用温度调整:

P ′ ( y ∣ Y ) = P ( y ∣ Y ) 1 / temperature ∑ y ′ P ( y ′ ∣ Y ) 1 / temperature P'(y|Y) = \frac{P(y|Y)^{1/\text{temperature}}}{\sum_{y'} P(y'|Y)^{1/\text{temperature}}} P(yY)=yP(yY)1/temperatureP(yY)1/temperature

Temperature 通过改变概率分布的“锐度”来控制生成的随机性。具体来说:

  • Temperature → 0 时, P ′ ( y ∣ Y ) P'(y|Y) P(yY) 趋近于一个 one-hot 分布,即总是选择概率最高的词汇。
  • Temperature = 1 时, P ′ ( y ∣ Y ) P'(y|Y) P(yY) 保持原始概率分布。
  • Temperature > 1 时, P ′ ( y ∣ Y ) P'(y|Y) P(yY) 分布更加均匀,相对增加原本低概率词汇的选择概率。

代码示例

这里将展示 Temperature 对概率的影响。

import numpy as np
import matplotlib.pyplot as plt

# 概率分布
probs = np.array([0.4, 0.3, 0.2, 0.05, 0.05])
words = ['A', 'B', 'C', 'D', '<eos>']

# 设置 Top-K
K = 5

# 设置不同的 Temperature 值
temperatures = [0.5, 1.0, 1.5]

# 创建一个图表
plt.figure(figsize=(10, 6))

# 遍历不同的温度
for temp in temperatures:
    # 使用 Temperature 调整概率
    adjusted_probs = probs ** (1.0 / temp)
    adjusted_probs = adjusted_probs / np.sum(adjusted_probs)  # 归一化
    
    # 打印当前 Temperature 的概率分布
    print(f"\n--- Temperature = {temp} ---")
    for i, prob in enumerate(adjusted_probs):
        print(f"{words[i]}: {prob:.2f}")
    
    # 绘制概率分布图
    plt.plot(words, adjusted_probs, label=f"Temperature = {temp}")

# 绘制原始概率分布的对比
plt.plot(words, probs, label="Original", linestyle="--", color="black")

# 添加图表信息
plt.xlabel("Word")
plt.ylabel("Probability")
plt.title("Effect of Temperature on Top-K Probability Distribution")
plt.legend()

# 显示图表
plt.show()

输出:

--- Temperature = 0.5 ---
A: 0.54
B: 0.31
C: 0.14
D: 0.01
<eos>: 0.01

--- Temperature = 1.0 ---
A: 0.40
B: 0.30
C: 0.20
D: 0.05
<eos>: 0.05

--- Temperature = 1.5 ---
A: 0.34
B: 0.28
C: 0.21
D: 0.08
<eos>: 0.08

温度影响

观察图片可以直观看到:

  • temperature < 1 时,概率分布变得更加尖锐,高概率词更可能被选择,适用于需要高确定性的任务,如生成技术文档或代码。
  • temperature > 1 时,概率分布变得更加平坦,使得低概率词也有更多机会被选中,适用于需要创造性和多样性的任务,如写作或对话生成。

在大模型中的应用

Top-K 和 Top-P 采样是否可以一起使用?

可以,通过同时设置 top_ktop_p 参数,模型会首先应用 Top-K 筛选,限制候选词汇数量,然后在这有限的词汇中应用 Top-P 采样,动态调整词汇集合。

使用 Hugging Face Transformers 库的简单示例:

import warnings
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

# 忽略 FutureWarning 警告
warnings.filterwarnings("ignore", category=FutureWarning)

# 指定模型
model_name = "distilgpt2"

# 加载分词器和模型
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)

# 将模型移动到设备
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)

# 输入文本
input_text = "Hello GPT"

# 编码输入文本
inputs = tokenizer.encode(input_text, return_tensors="pt").to(device)
attention_mask = torch.ones_like(inputs).to(device)

# 设置 Top-K 和 Top-P 采样
top_k = 10
top_p = 0.5
temperature = 0.8

# 生成文本,结合 Top-K 和 Top-P 采样
with torch.no_grad():
    outputs = model.generate(
        inputs,
        attention_mask=attention_mask,
        max_length=50,
        do_sample=True,
        top_k=top_k,                # 设置 Top-K
        top_p=top_p,                # 设置 Top-P
        temperature=temperature,    # 控制生成的随机性
        no_repeat_ngram_size=2,     # 防止重复 n-gram
        pad_token_id=tokenizer.eos_token_id
    )

# 解码生成的文本
generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
print("结合 Top-K 和 Top-P 采样生成的文本: ")
print(generated_text)

输出示例:

结合 Top-K 和 Top-P 采样生成的文本: 
Hello GPT.

The first time I heard of the G-E-X-1, I was wondering what the future holds for the company. I had no idea what it was. It was a very big company, and it had

参数解释:

  • top_k=10: 首先限制候选词汇为概率最高的 10 个。
  • top_p=0.5: 在这 10 个词汇中,从高到低,选择累积概率达到 0.5 的词汇归一化后进行采样。
  • temperature=0.8: 控制生成的随机性,较低的温度使模型更倾向于高概率词汇。

如果我只想使用 Top-K 或者 Top-P 应该怎么办?

对于只使用 Top-K:

top_p 设置为 1(表示不使用 Top-P 采样)。

outputs = model.generate(
  inputs,
  max_length=50,
  do_sample=True,
  top_k=top_k,                # 设置 Top-K
  top_p=1.0,                  # 不使用 Top-P
  temperature=temperature,    # 控制生成的随机性
  no_repeat_ngram_size=2,     # 防止重复 n-gram
  eos_token_id=tokenizer.eos_token_id
)

对于只使用 Top-P:

top_k 设置为 0(表示不使用 Top-K 采样)。

outputs = model.generate(
  inputs,
  max_length=50,
  do_sample=True,
  top_k=0,                    # 不使用 Top-K
  top_p=top_p,                # 设置 Top-P
  temperature=temperature,    # 控制生成的随机性
  no_repeat_ngram_size=2,     # 防止重复 n-gram
  eos_token_id=tokenizer.eos_token_id
)

参考链接

<think>嗯,用户问的是Top-p和Top-k有什么区别,之前他遇到了本地部署模型识别表格不完整的问题,现在转向了生成式模型中的参数设置问题。这可能意味着他在调整模型参数时遇到了生成效果的问题,或者想优化生成结果。需要先回顾一下Top-p和Top-k的定义,以及它们在生成过程中的作用。 首先,Top-k是选择概率最高的前k个词作为候选,然后从中按概率分布抽样。比如k=50,模型会从概率最高的50个词里选。而Top-p(核采样)则是累积概率超过p的最小词集合,比如p=0.9,就选概率从高到低加起来刚好超过90%的那些词,然后从中抽样。两者的主要区别在于选择候选词的方式不同:Top-k固定数量,Top-p动态调整数量。 用户可能在使用本地模型生成回答时,发现结果不够准确或不连贯,调整了温度参数后,可能还想通过Top-p和Top-k来优化生成效果。需要解释两者的应用场景,比如Top-k适合需要稳定性的情况,而Top-p更灵活,能根据上下文调整候选词数量。 另外,用户之前遇到的是表格识别问题,现在转问生成参数,可能是在尝试优化模型生成表格内容时的效果。这时候可能需要结合两者的特点,建议在需要多样性的场景用Top-p,需要限制输出范围时用Top-k,或者同时使用两者来控制生成质量。 还需要考虑用户的背景,可能有一定的技术基础,但需要清晰的对比和实际例子帮助理解。可能需要举例说明,比如当使用Top-k=50时,不管上下文如何都选前50,而Top-p=0.9则会动态调整候选词数量,可能有时多有时少,从而平衡生成多样性和准确性。 最后,要确保回答结构清晰,分点说明区别,可能还要提到两者可以结合使用,以及温度参数的影响,帮助用户全面理解如何调整这些参数来优化模型输出。</think>在生成式模型(如LLM)的输出控制中,**Top-p(核采样)**和**Top-k(截断采样)**是两种常用的概率筛选策略,它们的核心区别在于选择候选词的方式: --- ### **1. Top-k 采样** - **原理**: 仅保留**概率最高的前k个词**作为候选池,其他词直接排除。 例如设置`k=50`时,模型只从概率最高的50个词中抽样。 - **特点**: ✅ **确定性高**:始终固定候选词数量 ❌ **灵活性差**:可能忽略低概率但更合理的词 ❌ **极端情况**:若前k个词全是低质量候选,输出必然受限 - **适用场景**: 需要严格限制输出范围时(如客服问答需精准控制回答方向) --- ### **2. Top-p(核采样)** - **原理**: 动态选择**累积概率超过p的最小词集合**作为候选池。 例如设置`p=0.9`时,按概率从高到低累加,直到总和≥90%时停止,仅从这些词中抽样。 - **特点**: ✅ **动态调整**:候选词数量随上下文变化(可能多也可能少) ✅ **平衡质量多样性**:既排除极低概率词,又保留合理候选 ❌ **参数敏感**:p值设置需反复调试(一般推荐0.7-0.95) - **适用场景**: 需要平衡生成质量多样性时(如创意写作、开放式对话) --- ### **3. 直观对比示例** 假设模型预测下一个词的概率分布如下(已排序): ``` [ ("人工智能", 0.4), ("深度学习", 0.3), ("神经网络", 0.15), ("大数据", 0.1), ("云计算", 0.05) ] ``` | 策略 | 参数设置 | 候选词集合 | 说明 | |--------------|--------------|------------------------------------|----------------------------------------------------------------------| | **Top-k** | k=3 | 人工智能, 深度学习, 神经网络 | 固定选前3个词,排除后2个 | | **Top-p** | p=0.85 | 人工智能, 深度学习, 神经网络, 大数据 | 前4个词累积概率0.4+0.3+0.15+0.1=0.95≥0.85,动态包含更多候选 | | **两者结合** | k=3 + p=0.85 | 人工智能, 深度学习, 神经网络 | 先按k=3截断,再检查是否满足p=0.85(此时0.4+0.3+0.15=0.85已达标) | --- ### **4. 实际应用建议** 1. **单独使用**: - 优先尝试**Top-p**(推荐`p=0.9`),平衡质量多样性 - 严格限制输出时用**Top-k**(如`k=40`) 2. **组合使用**: 同时设置`top_k=50 + top_p=0.95`,先按Top-k截断,再通过Top-p动态筛选(多数框架支持叠加) 3. **温度参数(Temperature)配合**: - 低温度(如0.2) + 低Top-p(如0.7) → 更保守、确定性输出 - 高温度(如0.8) + 高Top-p(如0.95) → 更开放、创造性输出 --- ### **5. 典型应用场景** | 场景 | 推荐策略 | 参数示例 | |---------------------|-------------------------|-------------------| | 技术文档生成 | Top-p | p=0.9 | | 法律合同起草 | Top-k | k=30 | | 诗歌/故事创作 | Top-p + 高温度 | p=0.95, T=0.7 | | 客服问答 | Top-k + 低温度 | k=20, T=0.3 | 掌握这两种策略的配合使用,可以显著提升模型输出的可控性和质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hoper.J

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值