C_Meng PSNA

Never wait for the storm to pass, just dance in the rain.

0%

开放域问答评测:从数据集到统计显著性

“我们的模型在 NQ 上比 baseline 高 2.1 个点”——这句话在 2026 年几乎没有信息量。因为它缺三样东西:哪个 NQ 变体、多少样本量、这个差值是否超过噪声。

导语

开放域问答(Open-Domain QA)是大模型评测里最成熟、也最容易被误用的板块。成熟在于:数据集、评测框架、指标都有十年积累;易误用在于:大多数论文和内部评测报告只报均值,不做统计检验,也不说明数据集的变体与设置。

结果是三类常见无效结论:

  1. 在 3,610 条的 NQ-open test 上,2.1 个点的提升可能完全不显著(后文会算出 95% 置信区间);
  2. 拿 closed-book 的数字和 retrieval-augmented 的数字直接比——这是两个任务;
  3. **在训练集里见过答案的情况下报”零样本”**——这在大模型时代几乎是默认状态。

本文分三部分:

  • 数据集:NQ / TriviaQA / PopQA / HotpotQA / InsCit 的来源、推理类型、证据标注、以及它们各自在测什么;
  • 评测框架:LM Harness 的 task 配置、运行方式、输出解读,以及它不做什么;
  • 统计检验:配对 t、Wilcoxon、McNemar、bootstrap 各自适用条件,以及”为什么不能只看均值”的定量回答。

面向做过模型评测、需要写报告或看别人报告的读者。本文的核心主张是:QA 评测的可靠性问题,一半在数据集选择,一半在统计方法,几乎不在模型本身。


0. 先建立坐标系:QA 数据集的四个正交维度

在逐个介绍之前,先把维度理清。不同数据集之间的差异,基本可以拆成四个独立的轴,理解这四轴比记住每个数据集的数字有用得多。

维度 取值 决定了什么
① 跳数 单跳 / 多跳 是否需要组合多个事实;考察推理还是检索
② 证据 无 / 段落级 / 句子级 / 实体级 能否评”证据正确性”;能否做可解释评测
③ 知识分布 头部(热门)/ 长尾 / 人工构造 考察”记住了多少”还是”泛化到多冷”
④ 可答性 完全可答 / 部分信息缺失 / 完全不可答 考察”会不会承认不知道”

五个数据集在这四轴上的位置:

1
2
3
4
5
6
7
8
9
            单跳                     多跳
┌──────────────┬──────────────────┐
头部 │ NQ │ │
│ TriviaQA │ HotpotQA │
├──────────────┼──────────────────┤
长尾 │ PopQA │ (PopQA 的部分) │
├──────────────┼──────────────────┤
信息缺失│ │ InsCit │
└──────────────┴──────────────────┘

这张图最重要的信息是:五个数据集测的是五种不同能力,它们的分数不可横向比较。 “在 NQ 上 55,在 HotpotQA 上 60”没有任何意义。


1. 五个数据集逐个拆

1.1 Natural Questions(NQ)

来源:Google,2019(Kwiatkowski et al., Natural Questions: A Benchmark for Question Answering Research, TACL)。问题来自真实用户的 Google 搜索查询,答案由标注者在维基百科页面中标注。

规模与切分:

切分 规模 说明
训练 ~307k 每条含问题 + 维基页面 + 长答案(段落)+ 短答案(span)
开发 7,830 同上
测试 7,842 标注不公开,需提交

关键:NQ 有两个完全不同的用法

变体 出处 规模 任务定义
NQ(原始) Google 2019 见上 给定维基页面,从页面中抽 span
NQ-open Lee et al., 2019(Latent Retrieval for Weakly Supervised ODQA) dev 3,610 / test 3,610 不给证据,模型要自己检索或靠参数知识回答

这是评测里最常见的混淆点。论文里写”我们在 NQ 上达到 X”,必须问:是 NQ 还是 NQ-open?是 dev 还是 test?

难点:

  • 答案形式不唯一:NQ 的短答案有多个可接受形式(”USA” / “United States” / “the US”),评测必须做答案规范化;
  • 问题真实但不规整:来自搜索框,有拼写错误、代词指代、隐含上下文;
  • 有 5 类答案类型:短答案、长答案、是/否、无答案(页面里没有明确答案)。

适合测什么:单跳事实检索的”基本盘”。它是 ODQA 的 ImageNet——不前沿,但必须有。

1.2 TriviaQA

来源:华盛顿大学等,2017(Joshi et al., TriviaQA: A Large Scale Distantly Supervised Challenge Dataset)。问题来自 trivia 竞赛网站(Quiz Bowl 风格),由爱好者编写,带标准答案和”证据文档”。

规模:

项 数量
问题-答案对 ~95k
证据文档 ~650k(每条问题平均 6 篇)
开放域测试集 17,944 条(另有 1,100 条 verified 子集)

核心特点:证据是”远程监督”标注的

TriviaQA 的证据文档不是人工标注”哪段话回答了问题”,而是通过实体链接 + 检索自动找到的。这带来一个重要的性质:

证据文档里包含答案,但不一定包含”推理链”。

对单跳问题这通常没问题,但对需要组合的问题,证据可能只覆盖一半。

难点:

  • 答案别名极多:trivia 问题的答案常有多种写法(人名、地名、作品名),EM 指标对规范化极其敏感;
  • 问题风格独特:Quiz Bowl 式问题常有多层修饰(”这位在 1994 年获得诺贝尔文学奖、出生于 1936 年的日本作家是”),信息在问题内部逐步收窄——这和大模型喜欢的”直接问”很不一样;
  • distantly supervised 噪声:部分证据文档与问题实际无关。

适合测什么:**模型的”世界知识广度”**。TriviaQA 覆盖大量冷门事实(历史、地理、流行文化),是检验”参数里到底存了多少东西”的好工具。也是 closed-book 评测的常用选择。

1.3 PopQA

来源:马德里自治大学等,2023(Mallen et al., When Not to Trust Language Models: Investigating Effectiveness of Parametric and Non-Parametric Memories, ACL)。这个数据集的动机非常明确:不是测”平均准确率”,而是测**”准确率如何随实体流行度变化”**。

构造方式:

1
2
3
4
5
1. 从 Wikidata 取 16 种关系(如"某人的出生地"、"某作品的作者")
2. 对每个实体-关系对,用模板生成问题
(如 "What is the place of birth of {entity}?")
3. 用维基百科月访问量作为"流行度"代理
4. 按流行度分层,保证长尾实体占比足够

规模:14,267 条问题。

核心贡献:分层评测(popularity-stratified evaluation)

这是 PopQA 最值得学的一点。它要求按实体流行度分组报分:

分位 典型准确率(量级参考)
头部(最热门 10%) 70–85%
中部 45–65%
长尾(最冷门 10%) 20–40%

同一个模型,头尾差距可达 40 个点以上。 而这个信息在”总体准确率”里被完全掩盖了——因为数据集是刻意让尾部分布加权的,但很多人在自己的采样子集上又把它拉回头部了。

难点与陷阱:

  • 模板化问题:问题形式高度重复(16 种模板),模型可以利用模板模式而非真正理解;
  • 答案唯一但表述可能不同:实体名有别名,需要规范化;
  • 流行度代理的偏差:维基访问量不等于”模型训练时见过的频率”,但对大模型来说两者高度相关。

适合测什么:**”模型是不是只会答热门问题”**。如果你的业务有大量长尾实体(专业领域、小众商品、地方性知识),PopQA 的分层结果是比 NQ 总分更相关的指标。

一个必须做的方法论动作:任何 QA 评测都应该做流行度/难度分层。总分是加权平均,而权重是数据集定的,不一定符合你的业务分布。

1.4 HotpotQA

来源:CMU、Stanford 等,2018(Yang et al., HotpotQA: A Dataset for Diverse, Explainable Multi-hop Question Answering, EMNLP)。多跳问答的基准数据集。

规模与切分:

项 数量
问题总数 ~113k
训练 90,564
dev(distractor) 7,405
dev(fullwiki) 7,405
test 7,405(隐藏)

两种设置(必须区分):

设置 输入 难度
Distractor 给 10 篇段落(2 篇金标 + 8 篇干扰) 中(只需在给定段落里找)
Fullwiki 给整个维基百科 高(要先检索)

论文里报”HotpotQA EM”必须说明是哪个 setting,两者差距通常 10–15 个点。

核心特点:两个问题类型 + 句子级证据

① 问题类型:

  • Bridge(桥接):需要先找到中间实体,再问它的属性。

    “《冰与火之歌》的作者出生在哪个城市?” → 先找作者(George R. R. Martin)→ 再查出生地

  • Comparison(比较):比较两个实体的属性。

    “两位导演谁更年轻?” → 分别查两人年龄 → 比较

② 句子级 supporting facts 标注

每条问题都标注了哪些句子是必要的推理依据(通常是 2 句,一句一个跳)。这带来了两个额外的评测维度:

  • Supporting Fact F1 / EM:模型找的证据对不对;
  • Joint EM/F1:答案对 且 证据对。

Joint 指标非常重要,但经常被省略。因为一个模型可以”猜对答案但理由全错”——这种情况下它没有真正学会多跳推理。

难点:

  • 真正的多跳:HotpotQA 的桥接问题是强制的(必须走两步),不像某些数据集只是”恰好需要两段”;
  • 干扰段落:distractor 设置里的 8 篇干扰项经过挑选,容易混淆;
  • 对检索的依赖:fullwiki 设置下,检索失败 = 必然失败,模型能力被检索上限压制。

适合测什么:组合推理能力 + 证据可追溯性。它是”RAG 系统是否真的在做多跳”的标准检验。

1.5 InsCit:测”信息不足时怎么办”

来源与定位:InsCit 是一类针对**”信息不完整问题”(insufficient / incomplete information)**的基准。它的构造思路与上面四个都不同:

不是”从证据里找答案”,而是”判断证据是否足够,不够就主动澄清”。

典型构造方式(据该工作公开描述):

1
2
3
4
5
6
1. 取一个本来可答的多跳/复杂问题
2. 删掉其中一个关键的桥接实体或约束条件
(如 "《冰与火之歌》的作者出生在哪个城市" → "他的作者出生在哪个城市","他"指代不明)
3. 问题变得"看似可答,实际信息不足"
4. 期望模型的行为:识别信息不足 → 指出缺什么 → 追问/澄清
(而不是编一个答案)

它测的是三种能力,而且必须分开评:

能力 评测方式 失败模式
① 不足检测 判定”这个问题的信息是否足够” 幻觉出答案(最严重)
② 缺失类型识别 指出缺的是哪类信息(实体/关系/时间/约束) 笼统地说”信息不足”
③ 澄清质量 生成的反问是否有效(能否真正补全信息) 问了但问偏,或重复原问题

为什么这个数据集在 2026 年特别重要:

  1. **RAG 系统的默认行为是”总能答”**——检索不到也硬答,这是幻觉的主要来源之一;
  2. **Agent 系统需要”主动问”**——多轮交互的前提是知道”我缺什么”;
  3. 传统 QA 指标(EM/F1)完全无法评这类能力——因为”正确行为”不是输出一个答案串。

评测方法上的特殊之处:

  • 不能只看准确率:要把”答对”、”正确弃答”、”幻觉”三类分开统计。一个模型”答对 60%、幻觉 20%、正确弃答 20%”和”答对 60%、幻觉 40%、弃答 0%”是完全不同的系统,但传统准确率一样;
  • 澄清质量难自动评:通常需要 LLM-as-judge 或人工,成本高且一致性存疑;
  • **需要构造”配套的可答版本”**:否则无法判断”弃答”是能力还是过度保守。

术语提示:这个基准在不同文献里可能有不同的写法(InsCit / INS-CIT 等),具体规模、类别数量与切分请以原始论文为准。本文检索时外部搜索接口限流,未能核对原文表格,故此处只描述任务范式,不引用具体数字——这也正是一个好的评测习惯:不确定的数字不写。

1.6 五个数据集的横向对照

NQ(-open) TriviaQA PopQA HotpotQA InsCit
来源 Google 搜索日志 trivia 竞赛 Wikidata 模板生成 众包(看维基后提问) 改造多跳问题
跳数 单跳 单跳 单跳 多跳(桥接/比较) 多跳(被破坏)
证据标注 段落 + span 远程监督(实体链接) 无 句子级 supporting facts 缺失信息位置
知识分布 头部为主 头部 + 冷门 trivia 刻意长尾分层 头部实体 头部
可答性 可答(含 5% 无答案) 可答 可答 可答 部分不可答
指标 EM / F1 EM / F1 Accuracy(分层) EM / F1 / Joint / Support F1 检测 Acc / 澄清质量
主要测什么 单跳检索基线 参数知识广度 长尾泛化 组合推理 + 证据 知道自己不知道
典型规模(dev/test) 3,610(open) 17,944 14,267 7,405 以原文为准

2. SOTA 参考:怎么读、怎么用

2.1 先说清楚:这些数字只能当”量级参考”

我先给出量级区间,然后解释为什么不该精确引用。核对时间 2026-11,且本次外部检索受限,以下为公开文献的常见区间,具体以各模型技术报告为准。

数据集 设置 强系统量级 备注
NQ-open 闭卷(参数知识) EM 30–45 大模型 few-shot
NQ-open 检索增强 EM 45–60 检索 + 重排 + 阅读器
TriviaQA 开卷(给证据) EM 70–85 强模型 + 检索
TriviaQA 闭卷 EM 65–80 参数量大的模型优势明显
PopQA 总体 Acc 45–60 方差极大,看分层更有意义
PopQA 头部 / 尾部 70–85 / 20–40 头尾差 40+ 点
HotpotQA Distractor EM 60–70 / F1 75–85 强系统
HotpotQA Fullwiki F1 65–78 受检索上限压制
HotpotQA Joint EM 显著低于 EM 常被省略但更关键
InsCit 检测 / 澄清 依设定差异极大 不建议跨论文比

2.2 为什么这些数字不能精确引用

原因一:答案规范化不同,EM 可以差 3–8 个点

NQ 和 TriviaQA 的答案有大量别名。EM 计算前要做:

1
2
小写化 → 去标点 → 去冠词(a/an/the)→ 数字统一(1,200 → 1200)
→ 日期格式统一 → 单位统一 → (可选)同义词表

不同实现的规范化程度不同,同一模型同一数据可以报出 5 个点的差异。TriviaQA 因为答案别名特别多(人名、作品名),这个差异更大。

原因二:few-shot 示例数不同

0-shot / 5-shot / 25-shot 在同一个模型上能差 5–15 个点。而 few-shot 示例的选择也会影响结果(选到与测试集相似的示例会虚高)。

原因三:test 与 dev 混用

NQ test 需要提交(或已公开但常被用于训练);很多报告用的是 dev。dev 上调过 prompt 的分数不能当 test 分数。

原因四:是否允许”无答案”

NQ 有约 5% 的无答案样本。允许模型输出”无法回答”会提高真实可用性,但会降低 EM(因为有些”无答案”其实有模糊答案)。

原因五:模型见过的数据量不同

这是最根本的。NQ / TriviaQA / HotpotQA 都是 2017–2019 年的公开数据集,几乎必然在 2023 年之后的预训练语料里。 详见第 5 节。

结论:报告里应该写清”设置五要素”

1
2
3
4
5
① 数据集与变体(NQ vs NQ-open;HotpotQA distractor vs fullwiki)
② 切分(dev / test)
③ 上下文设置(闭卷 / 开卷 / 检索 top-k=?, 检索器是什么)
④ few-shot 数 + prompt 模板
⑤ 答案规范化规则 + 是否允许多答案

缺任何一项,这个数字就不可比。


3. LM Harness:标准化的代价与价值

3.1 它是什么

lm-evaluation-harness(EleutherAI)是当前最广泛使用的 LLM 评测框架。它的核心价值不是”提供了多少任务”,而是把”任务定义 + 提示格式 + 指标计算”标准化成可复现的配置。

架构上分三层:

1
2
3
4
5
6
7
8
9
10
11
tasks/          任务定义(YAML 或 Python)
├─ dataset_path / dataset_name 数据集加载
├─ doc_to_text 如何把样本转成 prompt
├─ doc_to_target 如何取参考答案
├─ fewshot_delimiter / target_delimiter
└─ metric_list exact_match / f1 / acc / acc_norm ...
models/ 模型后端
├─ hf(transformers)
├─ vllm / sglang(高吞吐)
└─ openai-completions / local-completions(API)
evaluator/ 运行与聚合(含 stderr 计算)

3.2 一个 task 的 YAML 长什么样

以 NQ-open 类任务为例(示意,非官方原文):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
task: nq_open
dataset_path: google-research-datasets/nq_open
output_type: generate_until
training_split: train
validation_split: validation
doc_to_text: "Q: {{question}}\nA:"
doc_to_target: "{{answer}}" # 列表,多个可接受答案
fewshot_delimiter: "\n\n"
target_delimiter: " "
generation_kwargs:
until: ["\n"]
do_sample: false
temperature: 0.0
max_gen_toks: 32
metric_list:
- metric: exact_match
aggregation: mean
higher_is_better: true
- metric: f1
aggregation: mean

四个必须理解的字段:

字段 作用 踩坑点
doc_to_text 决定 prompt 这是分数差异最大的来源,换个模板能差 10 个点
doc_to_target 参考答案(可以是列表) 列表 = 多个可接受答案,会取最优匹配
generation_kwargs 解码参数 do_sample: false 保证可复现;until 决定在哪停
metric_list 指标 exact_match 的规范化程度由框架定,不一定符合你的需求

3.3 怎么跑

基础跑法:

1
2
3
4
5
6
7
8
lm_eval \
--model hf \
--model_args pretrained=meta-llama/Llama-3.1-8B,dtype=bfloat16 \
--tasks nq_open,triviaqa,hotpotqa \
--num_fewshot 5 \
--batch_size auto \
--output_path ./results/llama31_8b \
--log_samples

关键参数说明:

参数 作用 建议
--tasks 任务列表(逗号分隔或 +group) 用 group 一次性跑一套
--num_fewshot few-shot 数 固定住,否则不可比
--batch_size auto 自动找最大 batch 大模型用 auto:4 限制上限
--limit N 只跑前 N 条 只用于调试,绝不能用于报数
--log_samples 保存每条样本的输出 必开,否则无法做配对检验
--seed 随机种子 采样解码时才有意义
--apply_chat_template 用模型的 chat 模板 指令模型必须开,否则格式错
--num_fewshot + --fewshot_as_multiturn few-shot 作为对话轮次 与 chat 模型匹配

换后端(同一任务定义):

1
2
3
4
5
6
# vLLM 高吞吐(本地批量评测首选)
--model vllm --model_args pretrained=...,tensor_parallel_size=4,gpu_memory_utilization=0.85

# OpenAI 兼容 API(评第三方模型)
--model local-completions \
--model_args model=my-model,base_url=http://localhost:8000/v1,concurrent=32

这一层的意义很重要:任务定义不变,只换后端。这保证了”同一批 prompt、同一套指标”,只是推理引擎不同——这是 harness 相对”自己写脚本”的最大优势。

3.4 输出解读

results.json 的结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"results": {
"nq_open": {
"alias": "nq_open",
"exact_match,none": 0.4213,
"exact_match_stderr,none": 0.0082,
"f1,none": 0.5312,
"f1_stderr,none": 0.0079,
"samples": 3610
}
},
"config": { "model": "hf", "model_args": "...", "num_fewshot": 5, ... },
"git_hash": "...",
"versions": { "nq_open": 1 }
}

必须看的三个字段:

字段 为什么重要
*_stderr 框架已经给了标准误。±2×stderr 就是 95% CI 的粗略区间
config / git_hash / versions 复现的凭据。没有这三样,结果不可追溯
samples 确认没被 --limit 截断

samples_*.jsonl**(--log_samples 的产物):每条样本的 doc、target、resps(模型原始输出)、filtered_resps(规范化后)。这是做配对检验的前提**——你必须能对齐”模型 A 和模型 B 在第 i 条上的对错”。

3.5 LM Harness 不做什么(这是关键)

不做 后果 你要自己补
不做显著性检验 只给 stderr,不给 p 值 用 samples 做配对检验(第 4 节)
不控制数据污染 不知道测试集是否在预训练里 用去污染版本 / 新数据集
不保证 prompt 公平 不同模型的 chat template 差异巨大 手工检查模板与 few-shot 格式
不处理多选题的选项顺序偏差 acc_norm 只是按长度归一 做选项置换测试
不做多轮/工具调用评测 主要是单轮生成 用 agent 专用框架
不做答案规范化的领域适配 通用规则(小写、去标点) 领域别名表

4. 统计检验:为什么”高 2.1 个点”经常是噪声

4.1 先算一下:这个差值可能压根不可分辨

准确率的抽样标准误:

1
2
SE = sqrt(p(1-p)/n)
95% CI 半宽 ≈ 1.96 × SE

在 p ≈ 0.7 时算一遍:

测试集样本量 n SE 95% CI 半宽 能分辨的最小差值(约)
100 4.58pp ±9.0pp ~13pp
300 2.65pp ±5.2pp ~7.5pp
500 2.05pp ±4.0pp ~5.8pp
1,000 1.45pp ±2.8pp ~4.1pp
3,610(NQ-open test) 0.76pp ±1.5pp ~2.1pp
7,405(HotpotQA dev) 0.53pp ±1.0pp ~1.5pp
17,944(TriviaQA) 0.34pp ±0.7pp ~1.0pp

读法:在 NQ-open test(3,610 条)上,两个模型的准确率差 2.1 个点,恰好落在 95% 置信区间的边界。这意味着:

如果只看均值,”高 2.1 个点”在统计上处于”可能显著也可能不显著”的模糊地带,必须做检验才能下结论。

而如果测试集只有 500 条(很多内部评测的真实规模),4 个点以内的差异基本没有信息量。

这就是”不能只看均值”的第一层原因:样本量决定了你能分辨多大的差异。

4.2 第二层原因:配对信息被浪费了

两个模型跑的是同一批测试题。这是关键——它们的错误高度相关(难题都会错,简单题都会对)。

如果做独立样本检验,等于假装”两个模型跑的是不同题目”,把配对信息丢了。统计功效会大幅下降(通常损失 30–50% 的等效样本量)。

正确的做法是配对检验:

1
2
3
4
对每条样本 i,得到:
a_i = 1 if 模型A答对 else 0
b_i = 1 if 模型B答对 else 0
只关心 a_i ≠ b_i 的样本(不一致对)

这直接引出下面四种方法。

4.3 方法一:McNemar 检验(QA 场景的默认选择)

适用:配对二分类结果(答对/答错)。这是 QA 准确率比较的正确工具,但在论文里被严重低估。

原理:只看不一致的样本,构造 2×2 列联表:

B 对 B 错
A 对 n₁₁(都对) n₁₀(只有 A 对)
A 错 n₀₁(只有 B 对) n₀₀(都错)

原假设:P(只有A对) = P(只有B对),即 b = n₁₀ 和 c = n₀₁ 服从对称分布。

统计量(连续校正版,小样本更稳):

1
χ² = (|b − c| − 1)² / (b + c)     ~ χ²(1)

关键洞察:n₁₁ 和 n₀₀ 完全不影响检验结果。两个模型都在 90% 的样本上答对,样本量再大也不增加检验力——只有”分歧”提供信息。

这解释了一个常见困惑:为什么”两个很强的模型(都 85%+)之间的 1 个点差异”很难显著?因为他们的分歧样本很少(可能只有 3%),b + c 太小。

检测力估算(双侧 α=0.05,power=0.8):

分歧方向的比例 需要的不一致样本数
55% : 45% ~784
60% : 40% ~197
65% : 35% ~88

读法:如果两个模型的分歧样本有 200 条,且其中 60% 是”只有 A 对”,那么显著。如果分歧只有 50 条,即使方向是 70:30 也很难显著。

为什么 QA 评测应该首选 McNemar:

  1. 准确率本质是二分类,不是连续值;
  2. 天然配对(同题);
  3. 对样本量要求比 t 检验低(只看分歧);
  4. 不假设正态性。

局限:只能用于准确率(0/1),不能用于 F1、BLEU 这类连续指标。

4.4 方法二:配对 t 检验

适用:配对连续指标(如每条样本的 F1、BLEU、log-likelihood、响应长度)。

原理:

1
2
d_i = metric_A(i) − metric_B(i)
t = mean(d) / (sd(d)/sqrt(n)) ~ t(n−1)

三个假设:

假设 对 LLM 评测的现实
配对观测 ✅ 满足(同题)
差值近似正态 ⚠️ 通常靠 CLT(n ≥ 30 勉强)
独立观测 ⚠️ 可能违反(同一文档的多个问题相关)

第三个假设最容易被忽略:HotpotQA 里同一个维基页面的多条问题不独立。严格来说要用聚类稳健标准误(cluster-robust SE,按文档聚类)。多数论文不做,这会让 p 值偏小(更容易显著)——这是一个系统性的乐观偏差。

什么时候可以用:

  • 指标是连续值(F1、nDCG);
  • n ≥ 100(CLT 生效);
  • 差值的分布没有极端离群(检查一下 d 的直方图)。

4.5 方法三:Wilcoxon 符号秩检验

适用:配对连续指标,但差值不服从正态(有离群、偏态、有界)。

原理:不只看向号,还看差值的秩:

1
2
3
4
1. 算 d_i = A_i − B_i,丢弃 d_i = 0
2. 按 |d_i| 排序,赋秩
3. W⁺ = 正差值的秩和,W⁻ = 负差值的秩和
4. 检验 W⁺ 与 W⁻ 是否对称

与配对 t 检验的对比:

配对 t 检验 Wilcoxon
假设 差值正态 差值对称(不需要正态)
对离群值 敏感(均值被拉动) 稳健(用秩)
功效 正态时最高 正态时略低(约 95%)
小样本 不可靠 可用(但有最小 n 要求)
适用指标 连续、无界 连续、有界、有序

什么时候选 Wilcoxon:

  • F1/BLEU 这类有界指标(0 到 1,分布常偏态,大量接近 1);
  • 有少量极端样本(某几条 F1 从 0 变成 0.9);
  • n < 30。

注意一个细节:Wilcoxon 要求差值分布对称(不是正态)。如果大量 d_i = 0(两个模型在这条上完全一样),这些样本被丢弃,实际 n 会大幅缩小。**报结果时应说明”有效配对数”**。

4.6 方法四:Bootstrap(最适合”报告置信区间”)

适用:任何指标(包括 F1、Joint EM、分层指标),只要你能重采样。

做法(配对 bootstrap):

1
2
3
4
5
6
for b in 1..B (B=1000~10000):
从 n 条样本中有放回抽 n 条(记录索引)
用同一批索引计算 metric_A 和 metric_B
保存 diff_b = metric_A − metric_B
95% CI = [diff 的 2.5 分位, 97.5 分位]
若 CI 不含 0 → 显著

关键:必须用同一批索引(配对)。分别对 A 和 B 独立重采样会高估方差。

优点:

  • 不假设分布;
  • 直接给置信区间(比 p 值信息量大);
  • 适用于任何指标(包括分层后的子集、Joint 指标);
  • 可以同时给出”效应量”和”不确定性”。

这是我最推荐的主报告方式:**报”差值 + 95% CI”,而不是”p < 0.05”**。

4.7 选择树

1
2
3
4
5
6
7
8
9
10
11
12
你的指标是什么?
├── 准确率(0/1) → McNemar 检验
└── 连续指标(F1/BLEU/nDCG)
├── 差值近似正态 且 n≥100 → 配对 t 检验
├── 差值偏态/有界/有离群 → Wilcoxon 符号秩
└── 任何情况都可以补一个 → 配对 Bootstrap(给 CI)

样本量 < 30?
└── 不要用 t 检验,用 Wilcoxon 或 Bootstrap

要报"提升多少"给业务方?
└── 报 Bootstrap 的 95% CI,而不是 p 值

4.8 效应量与多重比较

p 值只说”有没有”,不说”有多大”。 样本量足够大时,0.3 个点的差异也能 p < 0.001。所以必须同时报:

指标 计算 解读
绝对差 acc_A − acc_B 直接、可解释
相对提升 (acc_A − acc_B) / acc_B 宣传常用,但会夸大(基数小时)
Cohen’s h(比例) 2·arcsin(√p₁) − 2·arcsin(√p₂) 跨数据集可比:0.2 小 / 0.5 中 / 0.8 大
Cohen’s d(连续) mean(d)/sd(d) 0.2 / 0.5 / 0.8

多重比较:如果你比较了 5 个模型 × 6 个数据集 = 30 次检验,α=0.05 下期望有 1.5 个假阳性。

修正方法:

  • Holm-Bonferroni(推荐,比 Bonferroni 有功效):按 p 升序,第 i 个用 α/(m−i+1);
  • Benjamini-Hochberg(FDR 控制):适合探索性分析,允许一定假阳性。

实践建议:如果主结论是”模型 A 优于所有 baseline”,那么只需要和最强的 baseline 做一次检验,不要做 30 次然后挑显著的报——后者是 p-hacking。


5. 评测避坑:六个真实会导致错误结论的问题

5.1 坑一:数据污染(最严重,且难以自证)

问题:NQ(2019)、TriviaQA(2017)、HotpotQA(2018)几乎必然在 2023 年后的预训练语料中。模型可能”记得答案”,而不是”会检索/推理”。

三种表现形式:

形式 现象
答案记忆 闭卷准确率异常高(如某冷门实体一次答对)
证据记忆 能背出 supporting facts 的原句
格式记忆 输出格式与数据集标注风格高度一致(如固定用 “it is” 开头)

怎么检测(没有一个方法是决定性的):

  1. 构造扰动版本:改实体名(Paris → Prais)、改数值、换问法。如果分数大幅下降,说明依赖记忆;
  2. 新数据集:用发布时间晚于模型训练截止的数据(这是最可靠的,但要确认截止日期);
  3. **看”答案频率分布”**:如果模型对冷门实体的准确率与热门实体接近(PopQA 上),可疑;
  4. n-gram 重叠检测:把测试问题与训练语料做子串匹配(对大模型不现实,但对开源模型可做);

报告里应该写:数据集的发布时间、模型的训练截止时间、是否做了扰动测试。如果三者都没有,这个”零样本”结论不可信。

5.2 坑二:采样方差被当成模型差异

问题:如果解码用了 temperature > 0 或 top_p < 1,同一条样本跑两次结果可能不同。

定量:单条样本的”随机错误率”如果是 5%,在 3,610 条上,两次运行的总准确率差异约 sqrt(0.05 × 3610)/3610 ≈ 0.36pp——看起来不大,但如果两次运行的 prompt 顺序也变了,差异会放大到 1–2pp。

正确做法:

做法 说明
贪心解码(do_sample=False) 评测的默认选择,消除采样方差
固定 seed 必须采样时,多 seed 取均值并报方差
多次运行报 mean ± std 至少 3 次
报告单次 vs 多次的差异 如果差异 > 1pp,说明评测不稳定

一个反直觉的建议:评测应该用贪心,产品可以用采样。 两者的目标不同——评测要可复现和可比较,产品要体验。

5.3 坑三:用错误的方式做”重复实验”

三种错误:

错误 后果
同一 seed 跑 3 次取均值 完全相同的数字,方差为 0,毫无意义
只换 seed 不换数据顺序 只捕捉了采样方差,没捕捉数据顺序带来的方差
报告”最好的一次” 系统性高估

正确做法:

  • 固定数据,跑多个 seed(采样解码时),报 mean ± std;
  • 固定模型,做 bootstrap 重采样,报 CI(这是估计”如果换一批测试题”的波动);
  • 两者都做:seed 方差反映”解码随机性”,bootstrap 方差反映”测试集抽样随机性”。后者通常大得多。

5.4 坑四:prompt 格式不公平

问题:LM Harness 的 --apply_chat_template 会用模型自己的 chat 模板。不同模型的模板差异很大:

1
2
3
Llama-3:   <|start_header_id|>user<|end_header_id|>\n\n{question}<|eot_id|>
Qwen: <|im_start|>user\n{question}<|im_end|>
Mistral: [INST] {question} [/INST]

如果某个模型没开 chat template,或用错了模板,分数可能掉 10–20 个点——这不是模型差,是格式错。

检查清单:

  1. 指令模型是否开了 --apply_chat_template;
  2. few-shot 是否也应该作为对话轮次(--fewshot_as_multiturn);
  3. 手工打印 5 条实际 prompt,肉眼确认格式正确;
  4. 输出是否有”截断”(until 设置不对,答案被切)。

第 3 条是最有效的:任何人做评测,第一件事都应该是把实际送进模型的 prompt 打印出来看。

5.5 坑五:答案规范化不一致

问题:同一份输出,不同的规范化规则,EM 差 3–8 个点。

典型分歧点:

情况 处理方式 影响
"The Beatles" vs "Beatles" 去冠词 or 不去 影响 1–3pp
"1,200" vs "1200" 数字规范化 影响 <1pp
"USA" vs "United States" 别名表 影响 2–5pp
"2024-01-05" vs "January 5, 2024" 日期归一 影响 1–2pp
中文答案的空格/标点 全半角统一 影响大(中文任务)

建议:报告里明确写出规范化规则,或者用多套规则报区间(如 “EM 48.2 (strict) / 51.3 (normalized)”)。

5.6 坑六:在 dev 上调 prompt,在 dev 上报分数

问题:NQ-open 的 dev 只有 3,610 条。如果你用 dev 调了 20 次 prompt,选最好的那个报 52%,这个数字是乐观偏置的(相当于在测试集上训练)。

估算:在 3,610 条上,做了 20 次尝试后取最大值,期望虚高约 1.5~2.5pp(极值统计效应)。

正确做法:

  1. **划出 dev 的一部分作为 “prompt 开发集”**(如 1,000 条),剩下的作为”报告集”;
  2. 或者用另一个数据集的 dev 调 prompt(如用 TriviaQA dev 调格式,到 NQ 上报);
  3. **至少要披露”调了多少次”**。

6. 汇总

6.1 数据集速查

需求 选哪个 理由
单跳检索基线 NQ-open 标准、规模适中、社区对比多
参数知识广度 TriviaQA(闭卷) 冷门事实多,区分度高
长尾泛化 PopQA(分层) 唯一按流行度分层的标准集
多跳推理 HotpotQA(fullwiki) 强制桥接,有句子级证据
证据可追溯 HotpotQA(Joint EM + Support F1) 唯一能同时评答案与理由的
拒答/澄清 InsCit 类 唯一能评”知道自己不知道”的
中文场景 CMRC / DRCD / DuReader(本文未展开) NQ 系是英文维基

6.2 一份可执行的评测协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
【阶段 0:环境与声明】
□ 记录数据集版本、切分、发布时间
□ 记录模型训练截止时间(判断污染风险)
□ 记录 prompt 模板、few-shot 数、few-shot 选择规则
□ 打印 5 条实际 prompt,人工确认

【阶段 1:运行】
□ 贪心解码(do_sample=False)作为主结果
□ --log_samples 必开
□ 不用 --limit 报数(只用于调试)
□ 固定 batch_size 与 dtype(bf16 与 fp32 可能有差异)

【阶段 2:指标】
□ 主指标 + 95% CI(用 bootstrap)
□ 分层指标(按难度/流行度/问题类型)
□ 对多跳任务:同时报 EM 和 Joint EM

【阶段 3:统计】
□ 准确率 → McNemar
□ 连续指标 → 配对 t / Wilcoxon
□ 报效应量(绝对差 + Cohen's h/d)
□ 多次比较 → Holm 修正

【阶段 4:稳健性】
□ 扰动测试(改实体名/数值),看分数变化
□ 换一次 prompt 模板,看分数变化
□ 至少 2 个 seed(如果采样解码)

【阶段 5:报告】
□ 设置五要素写清
□ 不报"最好的一次"
□ 说明"没做什么"(未去污染、未做聚类稳健等)

6.3 一句话记住每个数据集

  • NQ:真实搜索问题,ODQA 的基本盘,但必须分清 NQ 和 NQ-open;
  • TriviaQA:冷门知识广度高,答案别名多,EM 对规范化敏感;
  • PopQA:头尾差 40 个点,总分是骗人的,必须分层看;
  • HotpotQA:强制桥接,Joint EM 才反映真本事;
  • InsCit:把”幻觉”从”答错”里分出来,是 Agent 时代的必备评测。

7. 小结

  1. 五个数据集测五种能力,分数不可横向比较。 NQ 测单跳检索、TriviaQA 测参数知识广度、PopQA 测长尾泛化、HotpotQA 测组合推理、InsCit 测”知道自己不知道”。选数据集就是选你要证明什么。
  2. NQ 与 NQ-open 是两个任务。 前者给维基页面抽 span,后者不给证据。论文里写”在 NQ 上 X”必须追问是哪个。 HotpotQA 的 distractor / fullwiki 同理。
  3. HotpotQA 必须报 Joint EM。 只报 EM 会让”猜对答案但理由全错”的模型看起来很好。多跳任务的考点是”推理链对不对”,不只是”答案对不对”。
  4. PopQA 的价值在分层,不在总分。 头部 70–85%、尾部 20–40%,总分把最有信息量的部分平均掉了。任何 QA 评测都该做难度分层。
  5. SOTA 数字只能当量级参考。 答案规范化、few-shot 数、dev/test、是否允许无答案、模型是否见过数据——五项里有任意一项不同,数字就不可比。
  6. LM Harness 的价值是”任务定义与推理后端解耦”**,不是”任务多”。它能保证同一批 prompt 换不同引擎跑。但它不做显著性检验、不做去污染、不保证 prompt 公平**——这三件事要自己补。
  7. 评测第一件事是打印实际 prompt。 没开 chat template、until 设置错误、few-shot 格式错——这些问题的共同表现是”分数异常低”,而它们占”模型看起来变差”原因的很大比例。
  8. 样本量决定了你能分辨多大的差异。 p≈0.7 时:n=500 → ±4.0pp,n=1000 → ±2.8pp,n=3610 → ±1.5pp。在 500 条的测试集上,4 个点以内的差异没有信息量。
  9. QA 准确率比较应该用 McNemar,不是 t 检验。 因为准确率是二分类、天然配对。而且它的检验力只来自”分歧样本”——两个都很强的模型之间,1 个点的差异很难显著,因为分歧太少(分歧 200 条、方向 60:40 才勉强够)。
  10. 连续指标(F1/BLEU)用配对 t 或 Wilcoxon。 差值正态、n≥100 用 t;有界/偏态/有离群/小样本用 Wilcoxon。两者都该补一个配对 bootstrap 报 CI。
  11. 报”差值 + 95% CI”比报 p 值有用。 p 值只说有没有,CI 说”可能有多大”。给业务方的报告应该是”提升 2.3pp,95% CI [0.4, 4.2]”,而不是”p<0.05”。
  12. 数据污染是大模型时代评测的第一大坑,且无法自证清白。 NQ/TriviaQA/HotpotQA 都在 2023 年后的预训练语料里。唯一可靠的检测是扰动测试(改实体名、换问法),如果分数大幅下降,说明靠的是记忆。
  13. 不要在同一小 dev 集上调 20 次 prompt 再报最高分。 极值统计下有 1.5–2.5pp 的虚高。要么划出独立的 prompt 开发集,要么披露调参次数。
  14. 多重比较会制造假阳性。 5 模型 × 6 数据集 = 30 次检验,α=0.05 下期望 1.5 个假阳性。主结论只和最强 baseline 比一次,不要挑显著的报。

如果只留一句:QA 评测的可靠性,一半取决于你选了哪个数据集(它测的是不是你想证明的能力),一半取决于你有没有做统计检验(那个差值是不是噪声)——模型本身反而是最确定的变量。


参考来源

数据集

  • Kwiatkowski et al., Natural Questions: A Benchmark for Question Answering Research, TACL 2019
  • Lee, Chang, Toutanova, Latent Retrieval for Weakly Supervised Open Domain Question Answering(ORQA / NQ-open 切分), ACL 2019
  • Joshi et al., TriviaQA: A Large Scale Distantly Supervised Challenge Dataset for Reading Comprehension, ACL 2017
  • Mallen et al., When Not to Trust Language Models: Investigating Effectiveness of Parametric and Non-Parametric Memories(PopQA), ACL 2023;arXiv:2212.10511
  • Yang et al., HotpotQA: A Dataset for Diverse, Explainable Multi-hop Question Answering, EMNLP 2018
  • InsCit 相关工作:面向”信息不充分”场景的 QA 基准(构造方式为破坏多跳问题的关键桥接信息,要求模型检测缺失并澄清)。注:本文对外检索接口在写作时限流,未能核对原文的规模、类别体系与切分,故只描述任务范式,不引用具体数字。

评测框架

  • EleutherAI, lm-evaluation-harness:https://github.com/EleutherAI/lm-evaluation-harness(task YAML 结构、doc_to_text / doc_to_target、--log_samples、stderr 计算、vLLM/SGLang/API 后端)
  • Gao et al., A Framework for Few-Shot Language Model Evaluation, 2021(harness 设计说明)
  • Hugging Face lighteval、OpenCompass(同类框架的对比参考)

统计方法

  • McNemar, Note on the Sampling Error of the Difference Between Correlated Proportions or Percentages, Psychometrika 1947
  • Dietterich, Approximate Statistical Tests for Comparing Supervised Classification Learning Algorithms, Neural Computation 1998(推荐:比较分类器的正确检验选择,明确指出 McNemar 与 t 检验的适用边界)
  • Wilcoxon, Individual Comparisons by Ranking Methods, 1945
  • Efron & Tibshirani, An Introduction to the Bootstrap, 1993
  • Koehn, Statistical Significance Tests for Machine Translation Evaluation, EMNLP 2004(配对 bootstrap 在 NLP 的经典应用)
  • Dror et al., The Hitchhiker’s Guide to Testing Statistical Significance in Natural Language Processing, ACL 2018(推荐:NLP 显著性检验的实践指南)
  • Cohen, Statistical Power Analysis for the Behavioral Sciences(效应量 h / d)
  • Holm, A Simple Sequentially Rejective Multiple Test Procedure, 1979;Benjamini & Hochberg, Controlling the False Discovery Rate, 1995
  • Card et al., With Little Power Comes Great Responsibility, EMNLP 2020(NLP 实验统计功效不足的实证)
  • Miller, Adding Error Bars to Evals: A Statistical Approach to Language Model Evaluations, Anthropic 2024(推荐:LLM 评测的方差分解与置信区间)

污染与稳健性

  • Sainz et al., NLP Evaluation in Trouble: On the Need to Measure LLM Data Contamination for Each Benchmark, EMNLP Findings 2023
  • Zhu et al., PromptBench: Towards Evaluating the Robustness of Large Language Models on Adversarial Prompts, 2023(prompt 敏感性)
  • Sclar et al., Quantifying Language Models’ Sensitivity to Spurious Features in Prompt Design, ICLR 2024(格式敏感性的量化)

说明:第 2 节的 SOTA 区间为公开文献的常见量级,不是精确引用值;本次写作时外部检索接口限流,未能逐个核对最新榜单。第 4 节的样本量与检测力数字由本文用标准公式计算得出(SE=sqrt(p(1-p)/n);McNemar 检测力用 z=(z_{α/2}+z_β)/|2r-1| 近似),可直接复现。所有具体数字在用于决策前,请在自己的数据与设置下重算。