首页 深度学习 推荐算法 Agent 项目 关于

Measuring a Language Model(Perplexity 详解)

一、文章核心主题

这是一篇深度讲解 Perplexity(困惑度)的技术文章,从信息论基础出发,完整推导 perplexity 与 cross-entropy、bits-per-byte 之间的关系,并在 PyTorch 中用 GPT-2 实际计算演示。

二、核心概念

2.1 语言模型的基本任务

语言模型的核心任务是:给定前文,预测下一个 token 的概率分布

  • 输入:In a shocking finding, scientist discovered a herd of unicorns
  • 模型输出:对所有 50257 个可能的下一个 token 输出概率分布
  • 例如:perfect 之后的下一个词,GPT-2 给出:
64.57%   English
17.82%   Spanish
2.26%    Latin
2.02%    ,
1.81%    human

2.2 什么是 Perplexity?

Perplexity = 2^{cross-entropy}

衡量模型在给定文本上的”困惑程度”——模型对文本的预测有多不确定。

\[\text{PPL} = 2^{\frac{1}{N} \sum_{i=1}^{N} -\log_2 P(t_i | t_1, ..., t_{i-1})}\]
  • PPL = 2:模型对下一个 token 的预测”二选一”,完全不确定
  • PPL = 1:模型完美预测,完全确定
  • PPL 越低越好

2.3 Perplexity 与 Cross-Entropy 的关系

Cross-entropy 是平均每个 token 需要的编码位数:

\[H = -\frac{1}{N} \sum_i \log P(t_i | C)\]

Perplexity 是 cross-entropy 的指数形式:

\[\text{PPL} = 2^{H}\]

2.4 Perplexity 与压缩的关系

Cross-entropy 给出了理论最优压缩的下界(香农信息论):

  • 用 bit(以 2 为底):$H_{\text{bits}} = H_{\text{nats}} / \ln 2$
  • 实际可用算术编码(Arithmetic Coding)逼近这个下界

核心洞察:语言模型的预测能力 = 压缩能力。更好的语言模型能更好地”压缩”文本,perplexity 更低。


三、PyTorch 实现要点

3.1 核心代码流程

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
import torch.nn.functional as F

# 加载 GPT-2 XL (1.5B 参数)
model_name = 'gpt2-xl'
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)

# 输入文本
text = "In a shocking finding, scientist discovered a herd of unicorns..."
tokens = tokenizer(text, return_tensors='pt')['input_ids']

# 前向传播:得到每个位置的 logits
with torch.inference_mode():
    logits = model(tokens).logits.cpu()

# softmax 得到概率
probs = F.softmax(logits, dim=-1)

# 计算每个 token 的对数概率
# 目标 token 是原始序列左移一位
target_tokens = tokens  # 偏移一位
logprobs = torch.gather(probs.log(), dim=-1, index=target_tokens.unsqueeze(-1)).squeeze()

# 平均对数似然
avg_logprob = logprobs.mean()
ppl = torch.exp(avg_logprob)

3.2 数值稳定性技巧

概率的连乘容易下溢(underflow),解决方法是先取对数:

# ❌ 危险:连乘会下溢
prob = (p1 * p2 * p3 * ...).item()  # → 0

# ✅ 安全:取对数后求和
log_prob = log(p1) + log(p2) + log(p3) + ...
prob = exp(log_prob)

同时在 softmax 中减去最大值防止指数溢出:

logits - logits.max(dim=-1, keepdim=True).values  # 数值稳定版

四、重要结论

4.1 Perplexity 能对比吗?

  • ✅ 可以跨模型架构对比(GPT-2、Llama、Mistral 等)
  • ❌ 不能直接用于 BERT / T5 等 Masked LM(需要用 pseudo-log likelihood)
  • ⚠️ HuggingFace 的 WikiText-2 perplexity 计算有 bug(按 token 切分而非按词)

4.2 Perplexity 与下游任务的关系

关系 说明
✅ 某些设置下对齐 perplexity 低 → 下游任务好
❌ 并非所有设置 perplexity 低不一定任务好
✅ 可用于数据选择 用 perplexity 筛选高质量训练数据

4.3 一个令人震惊的数字

用 GPT-2 生成 unicorn 故事的概率约为 $4.2 \times 10^{-60}$。

如果有一百万个语言模型,每个每秒生成一百万个 token,产生这段文字的预期时间

\[\approx 7.5 \times 10^{41} \text{ 年}\]

宇宙年龄才约 $10^{10}$ 年,所以这段文字几乎不可能随机生成——这恰恰说明了 GPT-2 确实学到了语言的结构。


五、关键公式汇总

概念 公式 单位  
序列概率 $P(t_1,…,t_n) = \prod_i P(t_i | C_i)$ -  
对数似然 $\log P = \sum_i \log P(t_i | C_i)$ nats  
Cross-Entropy $H = -\frac{1}{N} \sum_i \log P(t_i | C_i)$ nats/token  
Perplexity $\text{PPL} = 2^H$ -  
Bits-per-byte $H / \ln 2 / \text{bytes}$ bits/byte  

六、实用资源

资源 说明
HuggingFace perplexity docs ⚠️ 注意 WikiText-2 计算有 bug
lm_perplexity 推荐替代工具
Chip Huyen - Understanding Evaluation Metrics Perplexity 入门概述
LAMBADA 数据集 长距离依赖评估基准
Enwik8 压缩评估标准数据集

七、一句话总结

Perplexity 是衡量语言模型预测能力的核心指标,本质是 cross-entropy 的指数形式,连接了语言建模与信息论压缩。模型预测越准,perplexity 越低,压缩率越高。