You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

相同目标Token下困惑度计算结果为何不一致?

固定长度模型困惑度计算异常排查

参考Huggingface固定长度模型困惑度(Perplexity)计算文档时,发现异常现象:当使用不同上下文但后续目标Token相同时,按文档说明将上下文对应的target设为-100以忽略其对数似然损失,理论上困惑度应一致,但实际结果不同。测试T5、GPT2、sshleifer/tiny-gpt2等模型均存在该问题,将-100替换为T5的pad token 0后,困惑度结果仍不一致,需排查遗漏的关键点。

实验代码

from transformers import T5Tokenizer, T5ForConditionalGeneration
import torch
tokenizer = T5Tokenizer.from_pretrained("t5-small")
model = T5ForConditionalGeneration.from_pretrained("t5-small")

context_1 = 'here is some context_1 and some more stuff'
context_2 = 'here is some context and some more stuff and more stuff aspodkaspd'
answer_1 = 'this is not the answer'

input_ids_wrong = tokenizer(context_1 + answer_1, return_tensors="pt").input_ids
input_ids_correct = tokenizer(context_2 + answer_1, return_tensors="pt").input_ids
context_1_tokens_length = len(tokenizer(context_1, return_tensors="pt").input_ids[0])
context_2_tokens_length = len(tokenizer(context_2, return_tensors="pt").input_ids[0])

target_ids_wrong = input_ids_wrong.clone()
target_ids_correct = input_ids_correct.clone()

target_ids_wrong[:, :context_1_tokens_length] = -100 
target_ids_correct[:, :context_2_tokens_length] = -100 

print('target_ids_wrong', target_ids_wrong)
print('target_ids_correct', target_ids_correct)

with torch.no_grad():
    outputs_wrong = model(input_ids_wrong, labels=target_ids_wrong)
    outputs_correct = model(input_ids_correct, labels=target_ids_correct)
    
    neg_log_likelihood_wrong = outputs_wrong.loss
    neg_log_likelihood_correct = outputs_correct.loss

    ppl_wrong = torch.exp(neg_log_likelihood_wrong)
    ppl_correct = torch.exp(neg_log_likelihood_correct)
    print('ppl_wrong', ppl_wrong)
    print('ppl_correct', ppl_correct)

输出结果

target_ids_wrong tensor([[-100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,   19,
               59,    8, 1525,    1]])
target_ids_correct tensor([[-100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
             -100, -100, -100, -100, -100, -100,   19,   59,    8, 1525,    1]])
ppl_wrong tensor(9.0377)
ppl_correct tensor(21.1208)

问题根源

你混淆了损失计算的忽略规则和模型的输入依赖逻辑:

  • 将labels中上下文位置设为-100,仅作用于损失函数:告诉它跳过这些位置的损失计算,但模型的输入仍然是完整的「上下文+目标Token」序列。
  • 自回归/Seq2Seq模型预测目标Token时,是基于前面所有输入Token(包括不同的上下文)进行条件预测的。不同上下文会让模型的隐层状态完全不同,导致对目标Token的预测概率分布产生差异,最终损失和困惑度自然不同。

验证与修正

如果要让两次计算的困惑度一致,需要保证模型预测目标Token时的输入上下文完全相同。例如:

  • 仅将目标Token作为模型输入(无上下文)
  • 让两个实验的输入上下文完全一致,仅保留目标Token部分相同

补充说明

  • 无论使用-100还是pad token 0,核心都是让损失函数忽略对应位置,但无法改变模型对输入序列的依赖关系。
  • 困惑度本质是模型对目标Token序列的平均负对数似然的指数,而这个似然是基于前面所有输入Token的条件概率,因此上下文不同,结果必然不同。

内容的提问来源于stack exchange,提问作者Penguin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 22:57:07