前置讲 P3 · 提示实验的统计学 · Statistics for Prompt Experiments

Prompt Engineering · 预备知识 3。个人学习讲义与配套实验,按主题整理并持续修订。

课程源码 ZIP ↓

个人整理的学习笔记,非官方讲义;课程来源与整理说明见课程介绍。配套示例未逐一运行验证。

本篇目录

定位:这是本讲义补充的前置讲,原课没有对应的一节。原课的第三条学习目标是”设计实验来评估提示设计、优化提示的表现”,后面每一讲(尤其是第 2 讲的上下文学习、第 4 讲的思维链、第 10 讲的自动提示、第 17 讲的评估)都要比较提示的好坏;这一篇把需要的统计学讲清楚。 依据说明:区间、检验、样本量公式都是标准的统计学内容(Wilson 1927;McNemar 1947;Connor 1987 的配对样本量公式;Holm 1979);LLM 评测里的具体建议参考 Miller(2024)“Adding Error Bars to Evals”和 Zhao et al.(2021)。全部实验是本讲义自己设计的:前三个脚本用一个”知道真值”的模拟世界,第四个脚本用第 1 讲训练的真实小模型。 配套代码 Code:code/prereq3/(只用 Python 标准库,04 号脚本的后半部分用 PyTorch;4 个脚本 + 1 个模块;最慢的脚本约 7 秒) 预计阅读时间:2–3 小时(含运行代码)


0. 本讲导航 · How to read this lecture

0.1 为什么需要统计学

前置讲 P2 的实验跑完,得到了这样一张表:

模板准确率 [95% CI]
A 直接问84.4% [75.8, 90.3]
B 只答一个词84.4% [75.8, 90.3]
C 只输出 JSON81.2% [72.3, 87.8]

C 比 A 低 3 个百分点——C 更差吗?再看一些你会在论文、博客、群聊里看到的说法:

  • “加了一句 ‘Let’s think step by step’,准确率从 62% 提到了 66%。“(在 100 道题上)
  • “我们试了 20 种提示,最好的那个比基线高 8 个百分点。”
  • “这个提示在 GPT-X 上好用,在 GPT-Y 上没区别。“(各测了一次)
  • “我们每道题采样了 10 次,所以结果很可靠。”

每一句都可能是真的,也可能只是运气。这一篇讲怎样判断。好消息是需要的统计学并不多,而且几乎全部可以用”模拟一下,看看会怎样”来理解——这正是代码要做的事。

0.2 学习目标 Learning goals

  1. 理解抽样误差:测试集是从”所有可能的题”里抽出来的一份样本,准确率因此有波动;会算标准误,会用 Wilson 区间。
  2. 知道在同一组题上比较两个提示时为什么要用配对的方法(McNemar 检验、配对差值区间),以及它能省多少题。
  3. 理解功效和样本量:要多少道题才能发现一个给定大小的差别;“不显著”不等于”一样好”。
  4. 理解多重比较和赢家诅咒:试了很多个提示、挑最好的那个时会发生什么,怎样用开发集 / 测试集划分和 Holm 校正避免自欺。
  5. 认识题目之外的随机性来源:每道题采样多次(要用聚类标准误)、示例的选择和顺序(要当作随机因素)。
  6. 能写出一份提示实验的检查清单。

0.3 本讲地图 Map

§1 抽样误差:测试集只是一份样本                                    ← 代码 01 演示 1
§2 置信区间:Wald 为什么不行,Wilson、bootstrap                     ← 代码 01 演示 2–4
§3 比较两个提示:配对                                               ← 代码 02 演示 1
§4 功效与样本量:要多少道题                                         ← 代码 02 演示 2–3
§5 试了很多个提示之后:赢家诅咒与多重比较                            ← 代码 03
§6 随机性的其他来源:多次采样、示例的选择                            ← 代码 04
§7 一份提示实验的检查清单
§8 小结   §9 常见误区   §10 练习   §11 延伸阅读   §12 下一讲预告

0.4 术语 Terms

术语意思
总体 / 样本(population / sample)所有可能的题 / 你实际用来测的那些题
估计值(estimate)从样本算出来的数,例如测试集上的准确率 p^\hat p;真实值 pp 是总体上的准确率
标准误(standard error, SE)估计值在”换一份样本”时的标准差
置信区间(confidence interval)一个随样本变化的区间;95% 区间的意思是”用这种方法算,95% 的情况下会包含真值”
原假设(null hypothesis)通常是”两个提示一样好”
p 值如果原假设成立,看到至少这么极端的结果的概率
显著性水平 α事先定的门槛,常用 0.05:p < α 就说”显著”
第一类错误 / 假阳性其实一样好,却说有差别(概率 ≤ α)
第二类错误 / 功效(power)真有差别却没测出来 / 真有差别时测出来的概率
配对(paired)两个提示用同一组题,逐题比较
族错误率(FWER)做了很多次检验时,至少一个假阳性的概率

1. 抽样误差:测试集只是一份样本 · Sampling error

配套代码:01_intervals.py 演示 1、模块 stats_kit.py

一个提示”真正的”准确率,是它在所有可能的题(总体)上的准确率 pp。我们没法把所有可能的题都测一遍,只能抽一份测试集(样本),算出 p^\hat p。换一份同样难度的测试集,p^\hat p 就会变。

stats_kit.ItemBank 是一个”知道真值”的模拟世界:每道题有一个难度,每个提示有一个能力,提示答对一道题的条件由两者决定(还有一点每个提示自己的”手感”)。我们可以精确地设定一个提示的真实准确率,再看测出来会怎样。01 号脚本演示 1:一个真实准确率为 70% 的提示,在 1 万份各 50 道题的测试集上各测一次——

  • 前 5 次的结果:64%、64%、74%、62%、66%。
  • 1 万次结果的标准差是 0.0646,中间 95% 落在 58%–82%。

**同一个提示,换一份 50 道题的测试集,准确率可以差 10 个百分点以上。**两个提示在 50 道题上差 6 个百分点,完全可能是同一个提示测了两次。

这个标准差有一个简单的公式。把每道题对或错看成一次抛硬币(正面的概率是 pp),准确率就是 nn 次抛硬币里正面的比例,它的标准差是

SE(p^)=p(1−p)n\text{SE}(\hat p) = \sqrt{\frac{p(1-p)}{n}}

代入 p=0.7p = 0.7、n=50n = 50 得 0.0648,和模拟出来的 0.0646 几乎一样。这个结论只需要一个假设:测试题是从同一个题库里随机抽的、相互独立的。两个直接的推论:

  • 标准误随 1/n1/\sqrt{n} 缩小:题目多 4 倍,误差才减半。
  • 准确率越接近 50%,误差越大(p(1−p)p(1-p) 在 0.5 时最大)。

2. 置信区间 · Confidence intervals

配套代码:01_intervals.py 演示 2–4

2.1 “95% 置信区间”是什么意思

一个 95% 置信区间是一个方法:用它从样本算出一个区间,如果反复做这个实验(每次抽一份新的测试集),算出来的区间有 95% 的次数会包含真值。注意主语是”方法”,不是”这一个区间”——真值要么在这个区间里,要么不在,没有概率可言。这个”95% 的次数”叫覆盖率,可以用模拟检验。

2.2 Wald 区间为什么不行

最常见的区间是 Wald 区间:p^±1.96⋅p^(1−p^)/n\hat p \pm 1.96 \cdot \sqrt{\hat p(1-\hat p)/n}——把公式里的 pp 直接换成 p^\hat p。演示 2 在 12 种情形下各模拟 4000 次实验,看它的覆盖率:

题数真实准确率Wald 覆盖率Wilson 覆盖率
1050%89.3%97.9%
1090%65.2%93.4%
1098%17.6%98.5%
3098%45.6%97.9%
10098%86.2%94.8%
40050%95.6%94.8%

题多、准确率在中间时,Wald 区间没问题;可题少、准确率接近 100% 时它严重失灵。准确率 98% 时 10 道题全对很常见,Wald 区间就变成 [100%,100%][100\%, 100\%]——“绝对不会错”。LLM 评测里高准确率、小样本的情形恰恰很多。

Wilson 区间(Wilson 1927)把”pp 落在 p^±1.96p(1−p)/n\hat p \pm 1.96\sqrt{p(1-p)/n} 里”这个不等式对 pp 解出来,而不是先把 pp 换成 p^\hat p:

center=p^+z22n1+z2n,half=zp^(1−p^)n+z24n21+z2n\text{center} = \frac{\hat p + \frac{z^2}{2n}}{1 + \frac{z^2}{n}}, \qquad \text{half} = \frac{z\sqrt{\frac{\hat p(1-\hat p)}{n} + \frac{z^2}{4n^2}}}{1 + \frac{z^2}{n}}

它在所有 12 种情形下的覆盖率都在 93.4%–98.5%(小样本时略偏保守,宁宽勿窄),而且永远落在 [0,1][0, 1] 里。默认用 Wilson 区间;本讲义的所有表格都用它(console.pct_ci、stats_kit.wilson_ci)。

2.3 要多少道题

演示 3,准确率 80% 时:

题数50100200500100020005000
Wilson 半宽(百分点)±10.9±7.8±5.5±3.5±2.5±1.8±1.1

反过来,想要 ±5 / ±3 / ±2 / ±1 个百分点,大约要 246 / 683 / 1537 / 6147 道题(准确率 50% 时更多:385 / 1068 / 2401 / 9604)。公式是 n≈z2p(1−p)/h2n \approx z^2 p(1-p)/h^2。很多论文和博客在几十、几百道题上比较提示,报告的差别常常落在这个误差里。

2.4 bootstrap:没有公式时

自助法(bootstrap)用手上的这份题目代替总体,模拟”再出一份题”:从 nn 道题里有放回地抽 nn 道,算一次统计量;重复几千次,取中间 95% 那一段。演示 4:对准确率,bootstrap 区间 [0.640, 0.770] 和 Wilson 区间 [0.638, 0.764] 几乎一样;对”简单题准确率 − 难题准确率”这种没有现成公式的统计量,bootstrap 照样给出区间 [0.425, 0.637]。F1、加权平均、两个指标的差……只要能写出”怎样从题目算出这个数”,就能用 bootstrap。

关键是重抽的单位必须是独立的单位——在提示实验里通常是”题目”。§3 的配对 bootstrap 重抽题目(两个提示的结果跟着题目一起走),§6 的多次采样也要按题目聚类。


3. 比较两个提示:配对 · Paired comparisons

配套代码:02_paired.py 演示 1

3.1 同一组题上的 2×2 表

比较两个提示时,几乎总是让它们做同一组题。02 号脚本演示 1:提示 A 的真实准确率 70%,B 是 73%,同一组 200 道题。逐题对比:

B 对B 错
A 对12914
A 错1740

A 答对 143 道(71.5%),B 答对 146 道(73.0%)。两个提示在 169 道题上结果一样(都对或都错),只在 31 道题上”意见不同”。同一道题上两者结果的相关系数是 0.61:难题两个提示都容易错,简单题都容易对。

3.2 McNemar 检验:只看意见不同的题

两个提示都对、都错的题,对”谁更好”没有任何信息。McNemar 检验只看意见不同的题:A 对 B 错的有 n10=14n_{10} = 14 道,A 错 B 对的有 n01=17n_{01} = 17 道。如果 A、B 一样好,每道意见不同的题”A 赢”还是”B 赢”就像抛硬币,所以 n10∼Binomial(n01+n10,1/2)n_{10} \sim \text{Binomial}(n_{01} + n_{10}, 1/2)。p 值就是这个二项分布两侧的尾概率(mcnemar_exact 用精确的二项分布,不需要大样本近似)。

3.3 配对为什么灵敏得多

演示 1 对同一份数据做了几种分析:

分析方法B − A95% 区间p 值
不配对:两比例 z 检验+1.5%[−7.3%, +10.3%]0.738
配对:McNemar 精确检验+1.5%–0.720
配对:差值的正态区间+1.5%[−4.0%, +7.0%]–
配对:bootstrap(按题重抽)+1.5%[−4.0%, +7.0%]–

(这次抽到的 200 道题上只差 1.5 个百分点,比真实的 3 个点小,又是一个抽样误差的例子。)配对的区间(±5.5)比不配对的(±8.8)窄了 38%,相当于不配对时要多用 2.6 倍的题。原因在方差的公式里:

Var(p^B−p^A)=Var(p^A)+Var(p^B)−2 Cov(p^A,p^B)\text{Var}(\hat p_B - \hat p_A) = \text{Var}(\hat p_A) + \text{Var}(\hat p_B) - 2\,\text{Cov}(\hat p_A, \hat p_B)

同一组题上,两个提示的结果正相关,协方差项把方差减掉了一大块——“这组题碰巧难”这部分共同的波动,在作差时被抵消了。不配对的检验假设两组结果相互独立,把这份相关性白白浪费了。同一组题上比较两个提示,总是用配对的方法。


4. 功效与样本量 · Power and sample size

配套代码:02_paired.py 演示 2–3

4.1 两种错误

两个提示其实一样好真的有差别
检验说”显著”第一类错误(假阳性),概率 ≤ α正确,概率 = 功效
检验说”不显著”正确第二类错误(漏检)

α(常用 0.05)控制假阳性;功效是”真有差别时能测出来”的概率,常用的目标是 80%。

4.2 一个 3 个百分点的差别,要多少道题

演示 2:真实差别 3 个百分点(70% vs 73%),每种题数模拟 1000 次实验,看有多少次检验结果显著:

题数不配对 z 检验McNemar(配对)McNemar 的公式预测
1000.6%6.6%11%
2002.7%15.6%18%
5008.4%33.8%38%
100022.8%63.2%64%
200059.5%91.6%91%
  • 题目少时,一个真实的差别大多数时候测不出来:200 道题时配对检验只有 15.6% 的把握,500 道题时也只有 33.8%。反过来说,“在 200 道题上没有发现显著差别”不等于”两个提示一样好”——可能只是题太少。
  • 配对检验在每种题数下都灵敏得多。达到 80% 功效,配对需要约 1448 道题,不配对需要约 3554 道,差了 2.5 倍。题目和 API 调用都是钱。

4.3 在实验之前规划题数

McNemar 检验的样本量有一个近似公式(Connor 1987):

n≈(z1−α/2ψ+zpowerψ−δ2)2δ2n \approx \frac{\left(z_{1-\alpha/2}\sqrt{\psi} + z_{\text{power}}\sqrt{\psi - \delta^2}\right)^2}{\delta^2}

其中 δ\delta 是想检测的差别,ψ\psi 是两个提示”意见不同”的题占的比例。需要的题数大致和 ψ/δ2\psi/\delta^2 成正比:差别越小,需要的题越多(差别减半,题数要乘 4);两个提示在越多的题上意见不同,同样的平均差就越难分辨。表里的公式预测和模拟基本吻合(题少时公式略乐观)。实际做法:先用几十道题做一个小规模的预实验,估计 ψ\psi,再代入公式。

不配对的标准公式(nn 每组 =(z1−α/22pˉqˉ+zpowerp1q1+p2q2)2/δ2= (z_{1-\alpha/2}\sqrt{2\bar p\bar q} + z_{\text{power}}\sqrt{p_1q_1 + p_2q_2})^2/\delta^2)假设两组题相互独立。用在同一组题上时,它在题少的时候严重高估功效(100 道题时预测 7%、实际 0.6%)——这又是一个”同一组题不要用不配对的方法”的理由。

4.4 假阳性率

演示 3:两个提示的真实准确率完全相同,每次实验 500 道题、重复 2000 次。McNemar 检验有 3.4% 的实验”显著”(精确检验略偏保守,低于名义上的 5%);不配对的检验只有 0.2%——它把两个提示的结果当成独立的,高估了差值的方差,过于保守,这和它功效低是同一枚硬币的两面。

假阳性率 5% 的意思是:每做 20 次”其实没区别”的比较,大约有 1 次会冤枉出一个差别。这不是 bug,是 α = 0.05 的定义。如果你做了很多次比较,问题就来了(§5)。

4.5 显著不等于重要

题目足够多时,再小的差别都会”显著”:2 万道题上,0.5 个百分点的差别也能显著。可这个差别值不值得你把提示改得更长、更贵?报告结果时,差别的大小(带区间)比 p 值更重要;还要一起报告成本(token 数、延迟),前置讲 P2 的记账就是为此。


5. 试了很多个提示之后 · Multiple comparisons and the winner’s curse

配套代码:03_multiple_comparisons.py

5.1 赢家诅咒

提示工程的日常是:写 20 个版本,在一组开发题上各跑一遍,留下最好的那个。03 号脚本演示 1 让 20 个版本一样好(真实准确率都是 70%,只是每个在不同的题上”手感”不同),挑开发集第一名,再看它在全新的 2000 道题上的表现(重复 500 次):

开发集题数随便一个版本的开发集准确率第一名的开发集准确率第一名在新题上虚高
5070.5%77.8%70.0%+7.9
10069.8%75.3%70.0%+5.3
40070.0%72.8%70.0%+2.8

20 个一模一样好的版本,开发集上的”第一名”平均比真实水平高 5 个百分点以上,一换到新题就”掉回”70%。这叫赢家诅咒:挑最大值这个动作本身,就把运气选了进来。

这就是”在开发集上过拟合提示”:你反复修改提示、每次都看开发集分数,最后留下的版本有一部分好成绩来自运气。对策很简单,但必须严格执行:挑选用的开发集和报告用的测试集分开,测试集只在最后用一次。第 10 讲的自动提示优化会在开发集上试几百个提示,这个问题会被放大几百倍。

5.2 多重比较

演示 2:基线和 20 个版本的真实准确率都是 70%,在同一组 200 道题上,每个版本和基线做一次 McNemar 检验(只数”比基线好”的方向),重复 500 次:

做法至少有一个”显著优于基线”的比例
不校正(每个检验都用 p < 0.05)16.2%
Bonferroni(p < 0.05 / 20)1.2%
Holm(逐步校正)1.2%

每个检验单独看,冤枉的概率都不超过 5%;可 20 个检验里至少一个被冤枉的概率要大得多。试的版本越多,“总能找到一个显著的”就越确定。两种校正方法:

  • Bonferroni:每个检验的门槛降到 α/m\alpha/m(mm 是检验的个数)。
  • Holm(1979):把 p 值从小到大排序,第 ii 小的(从 0 开始数)和 α/(m−i)\alpha/(m-i) 比较,一旦有一个不显著就停下。它和 Bonferroni 一样把族错误率控制在 α 以内,但更容易发现真正的差别。

5.3 挑得出来 ≠ 证明得了

演示 3:20 个版本里真有一个好 5 个百分点(75%),其余 19 个和基线一样(70%):

开发集题数第一名正是那个更好的版本Holm 校正后检测出它平均每次的假发现
10053.4%1.8%0.02
40093.6%24.6%0.02
1000100.0%80.2%0.01

100 道题时,有将近一半的概率第一名不是真正更好的那个——19 个运气好的普通版本里,总有一个能冲到前面。400 道题时它大多能排第一,可经过校正之后,只有四分之一的概率能被证明显著优于基线。校正在保护你(假发现始终接近 0),代价是需要更多的题。候选越多,开发集要越大。

实用的做法:

  1. 事先写下你要比较哪几个(“预注册”),而不是事后从 20 个里挑一个显著的报告;
  2. 挑选和检验分开:在开发集上挑,在独立的测试集上只检验挑出来的那一个(只比一次,就不需要校正);
  3. 确实要同时比较多个时,比较了几个就校正几个。

6. 随机性的其他来源 · Other sources of randomness

配套代码:04_sampling_variance.py

“抽到了哪些题”不是唯一的随机性来源。

6.1 每道题采样多次:按题聚类

温度 > 0 时,同一道题每次的回答可能不同;常见的做法是每道题采样 kk 次,算总的正确率。可标准误该怎么算?04 号脚本演示 1:100 道题 × 每道题 5 次采样,重复 2000 次实验——

数值
估计值在不同实验之间的真实标准差0.0324
朴素 SE(把 500 个结果当成相互独立)的平均值0.0214
按题聚类的 SE 的平均值0.0322
朴素 95% 区间的覆盖率79.2%
聚类 95% 区间的覆盖率94.9%

同一道题的 5 次采样并不独立:难题 5 次都容易错,简单题 5 次都容易对。把 500 个结果当成 500 次独立的试验,SE 就小了一大截,区间”自信”得过了头。正确的做法是按题聚类:先算每道题的平均正确率 mim_i,再算它们的均值的标准误 sd(m)/n\text{sd}(m)/\sqrt{n}(cluster_se)。Miller(2024)建议 LLM 评测里一律这样报告:每道题采样多次、或者一篇文章出好几道题(阅读理解)时,都按”题”或”文章”聚类。

在第 1 讲的迷你 GPT 上(演示 3),96 道知识题在温度 1.0 下各采样 8 次:70 道题 8 次全对,26 道时对时错,聚类 SE 是朴素 SE 的 1.58 倍。温度 1.5 时,时对时错的题增加到 67 道,准确率从 92.8% 降到 78.0%——温度不只是”随机性”,它会系统性地改变你测到的结果,比较两个提示时必须保持一致。

6.2 预算固定时:多出题,还是多采样

演示 2:一共只能调用 400 次——

分配方式估计值的标准差95% 区间半宽
400 道题 × 1 次0.0242±4.7
200 道题 × 2 次0.0268±5.3
100 道题 × 4 次0.0338±6.6
50 道题 × 8 次0.0430±8.4
25 道题 × 16 次0.0577±11.3

估计值的方差 ≈(题目之间的差异)/n/n +(同一道题内部的采样噪声)/(nk)/(nk)。多采样只能缩小第二项,第一项只有多出题才能缩小,而它通常是大头。多次采样有它的用处(第 4 讲的 self-consistency 用投票提高单题的准确率),但如果目的只是”把准确率测准”,钱应该花在更多的题上。

6.3 示例的选择也是随机性

演示 4 回到第 1 讲 06 号脚本的那个实验:迷你 GPT 不认识 “question / answer” 这两个词,要靠示例看出格式。同一个模板、同一组题,只换示例(每次随机选 kk 个,整组题共用同一组示例),换 20 组:

示例数20 组里最低平均最高标准差
1 个12.0%25.7%38.0%8.5 个百分点
2 个70.5%86.8%92.0%6.2 个百分点

**只换了示例,准确率就能差二十几个百分点。**这不是小模型才有的毛病:Zhao et al.(2021)在 GPT-3 上报告,示例的选择和顺序能让准确率从接近随机变到接近最好(第 2 讲的主题)。

2 个示例时,20 组之间的标准差(6.2 个百分点)比一次运行自己的标准误(约 3.7 个百分点)还大。也就是说,只用一组示例跑一次,报告的置信区间根本没有包含”换一组示例会怎样”这部分不确定性,而它比”换一批题”的不确定性还大。所以:

  • 示例的选择(以及顺序、提示的措辞)要当作实验里的一个随机因素:用几组不同的示例各跑一遍,报告平均值和波动;
  • 比较两种提示策略时(例如”零样本 vs 少样本”),每种都要在多组示例上比较,而不是各挑一组”看起来不错的”;
  • 同一组示例下,两种策略的比较仍然可以配对(同一组题)。

7. 一份提示实验的检查清单 · A checklist

把这一篇和前置讲 P2 合在一起,一次可信的提示实验大致是这样的:

实验之前

  1. 写下要回答的问题和要比较的提示(预注册):比较几个,就准备校正几个。
  2. 把题目分成开发集(改提示、挑提示)和测试集(最后只用一次)。
  3. 用一个小规模的预实验估计不一致比例 ψ\psi,按 §4.3 的公式规划题数;题数不够时,事先承认只能检测多大的差别。
  4. 固定所有参数(模型、温度、max_tokens、系统提示),写进配置;把示例的选择当作随机因素,准备几组示例。

实验之中 5. 用前置讲 P2 的调用栈:重试、缓存、记账、预算、日志。每一次调用都留下记录。 6. 每道题、每组示例、每次采样都记下编号(seed),保证能复现。

实验之后 7. 报告每个提示的准确率和 Wilson 区间;多次采样时用聚类 SE。 8. 比较两个提示用配对的方法(McNemar 检验、配对差值的区间),报告差值和它的区间,而不只是 p 值。 9. 多个比较用 Holm 校正;在测试集上只检验最后挑出来的那个。 10. 报告差别的大小、成本(token、延迟、费用)以及换示例 / 换种子之间的波动。 11. 所有表格里的数字都能从日志重新算出来。

第 17 讲会把这份清单变成一个可复用的实验框架。


8. 小结 · Summary

  • 测试集是一份样本,准确率有抽样误差:SE =p(1−p)/n= \sqrt{p(1-p)/n},题多 4 倍误差才减半。100 道题的区间大约 ±8 个百分点。
  • 用 Wilson 区间,不要用 Wald 区间(小样本、高准确率时 Wald 会严重失灵)。没有公式时用 bootstrap,按题重抽。
  • 同一组题上比较两个提示,用配对的方法(McNemar、配对差值区间):两个提示的结果正相关,配对能省下一大半的题。
  • 功效:小的差别需要大量的题;“不显著”不等于”一样好”。用预实验估计 ψ\psi,事先规划题数。
  • 试了很多个提示:开发集上的第一名会虚高(赢家诅咒),多次检验会累积假阳性。开发集 / 测试集分开,比较多个时用 Holm 校正。候选越多,开发集要越大。
  • 其他随机性:每题多次采样时按题聚类计算 SE;固定预算下多出题比多采样更有用;示例的选择和顺序本身就能让准确率大幅波动,要当作随机因素来处理。

9. 常见误区 · Common pitfalls

  1. “B 比 A 高 4 个百分点,所以 B 更好。” 先看区间。100 道题上 4 个百分点的差别通常在误差之内。
  2. “两个准确率的置信区间重叠,所以没有显著差别。” 这个判断方法太保守,而且对配对的数据尤其不对。要直接看差值的区间(配对)。
  3. “我们没发现显著差别,说明两个提示一样好。” 可能只是功效不够。报告你能检测的最小差别。
  4. “我在开发集上试了 30 个版本,最好的比基线高 6 个点。” 赢家诅咒。在没参与挑选的测试集上再测一次。
  5. “每道题采样了 10 次,所以样本量是 10 × n,结果很精确。” 同一道题的多次采样不独立,要按题聚类;精度主要由题数决定。
  6. “我们精心挑了 3 个示例,准确率 85%。” 换一组示例可能是 70%。示例要当作随机因素,多组取平均,或者至少报告波动。
  7. “p < 0.05,所以这个改进很重要。” 显著不等于重要;看差值大小、区间和成本。
  8. “统计显著就说明结论在别的模型上也成立。” 统计推断只推广到”同一个题目总体、同一个模型、同样的设置”。换模型要重新测(第 1 讲 §8.6)。

10. 练习 · Exercises

练习 1(手算区间)。 一个提示在 50 道题上答对 45 道。分别用 Wald 和 Wilson 方法算 95% 区间。哪个更可信?

参考答案:p^=0.9\hat p = 0.9。Wald:0.9±1.960.9×0.1/50=0.9±0.0830.9 \pm 1.96\sqrt{0.9 \times 0.1/50} = 0.9 \pm 0.083,即 [0.817, 0.983]。Wilson:z2/n=0.0768z^2/n = 0.0768,center =(0.9+0.0384)/1.0768=0.8715= (0.9 + 0.0384)/1.0768 = 0.8715,half =1.960.0018+0.000384/1.0768=0.0851= 1.96\sqrt{0.0018 + 0.000384}/1.0768 = 0.0851,即 [0.786, 0.957]。用 stats_kit.wilson_ci(45, 50) 可以验证。Wilson 区间的中心向 0.5 收缩、上端更低:准确率 90%、50 道题时,Wald 区间的覆盖率不足 95%(01 号脚本演示 2 里 n = 30、90% 时只有 80.9%),Wilson 更可信。

练习 2(解读一个结论)。 有人报告:“A 在 100 道题上答对 62 道,B 答对 66 道,B 更好。” 用不配对的检验得到 p = 0.56。你能得出什么结论?还需要什么信息?

参考答案:不能说 B 更好,也不能说两者一样好——100 道题上 4 个百分点的差别远在误差之内(两个准确率的区间各宽约 ±9.5 个百分点)。还需要:(1) 两个提示是不是用的同一组题?如果是,应该用配对检验(需要逐题的结果,或者至少知道两者意见不同的题数 n01n_{01}、n10n_{10});(2) 这是事先计划的唯一一次比较,还是从很多版本里挑出来的?(3) 示例、温度等是否一致,换一组示例结果会不会变?

练习 3(McNemar 手算)。 两个提示在同一组题上,A 对 B 错的有 4 道,A 错 B 对的有 12 道。B 显著更好吗(α = 0.05)?

参考答案:意见不同的题 n=16n = 16;如果一样好,n10∼Binomial(16,1/2)n_{10} \sim \text{Binomial}(16, 1/2)。P(X≤4)=(1+16+120+560+1820)/65536=2517/65536≈0.0384P(X \le 4) = (1 + 16 + 120 + 560 + 1820)/65536 = 2517/65536 \approx 0.0384,双侧 p 值 ≈0.077\approx 0.077,不显著。注意:16 道意见不同的题里 B 赢了 12 道,看起来差别很明显,可样本太少。用 mcnemar_exact 验证:p = 0.0768。

练习 4(规划题数)。 你想检测两个提示之间 5 个百分点的差别(功效 80%、α = 0.05)。预实验显示两者在 20% 的题上意见不同。用配对检验需要多少道题?如果用不配对的方法(基础准确率 70%)呢?

参考答案:配对:n≈(1.960.2+0.84160.2−0.0025)2/0.0025=(0.8765+0.3740)2/0.0025≈626n \approx (1.96\sqrt{0.2} + 0.8416\sqrt{0.2 - 0.0025})^2/0.0025 = (0.8765 + 0.3740)^2/0.0025 \approx 626。不配对:n_unpaired(0.70, 0.75) = 1251(每组)。配对省了一半的题。对比一下:同样 ψ=0.2\psi = 0.2,检测 3 个百分点的差别要 n_paired_mcnemar(0.03, 0.2) = 1742 道,是 626 的 2.8 倍——差别变成原来的 3/5,题数大约变成 (5/3)2≈2.8(5/3)^2 \approx 2.8 倍。

练习 5(Holm 手算)。 5 个版本分别和基线比较,p 值是 0.001、0.012、0.03、0.04、0.2。在 α = 0.05 下,不校正、Bonferroni、Holm 各认定哪几个显著?

参考答案:不校正:前 4 个(< 0.05)。Bonferroni(门槛 0.01):只有第 1 个。Holm:排好序后,门槛依次是 0.05/5 = 0.01、0.05/4 = 0.0125、0.05/3 ≈ 0.0167、0.025、0.05。0.001 ≤ 0.01 ✓,0.012 ≤ 0.0125 ✓,0.03 > 0.0167 ✗,停下。所以 Holm 认定前 2 个显著——比 Bonferroni 多发现一个,同时仍然控制族错误率。

练习 6(聚类 SE 手算)。 3 道题,每道采样 4 次:第 1 题 [1, 1, 1, 1],第 2 题 [0, 0, 0, 0],第 3 题 [1, 0, 1, 0]。分别算朴素 SE 和聚类 SE。

参考答案:总正确率 6/12 = 0.5。朴素 SE =0.25/12≈0.144= \sqrt{0.25/12} \approx 0.144。聚类:每道题的平均是 1、0、0.5,均值 0.5,样本标准差 =(0.25+0.25+0)/2=0.5= \sqrt{(0.25 + 0.25 + 0)/2} = 0.5,SE =0.5/3≈0.289= 0.5/\sqrt{3} \approx 0.289——是朴素 SE 的 2 倍。直觉:真正”独立的信息”只有 3 道题,不是 12 次采样。

练习 7(赢家诅咒,动手)。 修改 03 号脚本演示 1,把版本数从 20 改成 5 和 100(开发集 100 道题)。第一名的虚高怎样变化?为什么?

参考答案:思路:把 for _ in range(20) 里的 20 改掉。版本越多,“20 个随机变量的最大值”变成”100 个的最大值”,最大值越偏离均值,虚高越大;版本少时虚高小。粗略地说,mm 个独立的、标准差为 σ\sigma 的估计值,最大值大约高出均值 σ2ln⁡m\sigma\sqrt{2\ln m}(这里各版本共用同一组题、彼此相关,实际的虚高会比这个式子小一些)。具体数字以你的运行为准。这也说明:自动提示优化一次试几百个候选,开发集上的分数几乎一定是虚高的。

练习 8(设计实验)。 你要回答”在这个分类任务上,少样本提示比零样本提示好吗?“手上有 600 道带标签的题、一个能用的模型、500 美元的预算。写出你的实验设计(划分、示例、参数、分析方法、报告内容)。

参考答案(一种合理的设计):(1) 划分:200 道开发集(只用来选示例的候选池、调格式),400 道测试集(只在最后用一次)。(2) 示例:从开发集里随机抽 5 组、每组 4 个示例,作为随机因素;零样本没有示例,但可以用 5 种措辞略有不同的指令,作为对应的随机因素。(3) 参数:同一个模型、同样的温度(或模型默认)、同样的 max_tokens;全部写进配置,用 P2 的调用栈记日志和缓存,先用 20 道题试跑估计费用。(4) 分析:每组示例 × 测试集得到一个准确率;主要比较”少样本 5 组的平均”vs”零样本 5 种措辞的平均”,用按题配对的差值(每道题在两种策略下的平均正确率之差)做 bootstrap 区间;同时报告 5 组之间的最小值、最大值。(5) 报告:两种策略的准确率和区间、差值和区间、组间波动、每道题的平均 token 数和费用、所有原始日志。

练习 9(显著 vs 重要)。 一个新提示在 20000 道题上把准确率从 90.0% 提高到 90.4%,配对检验 p < 0.001;但它的提示长了 800 个 token。你会建议换成新提示吗?需要考虑什么?

参考答案:差别是真的(不太可能是运气),但很小:每 1000 道题多答对 4 道。要考虑:(1) 成本:每次调用多 800 个输入 token,按 P2 的价格算一下,一年的调用量下多花多少钱;能不能用提示缓存降低(不变的部分放在前缀);(2) 延迟:更长的输入意味着更慢;(3) 这 0.4 个百分点落在哪些题上——如果正好是业务上最重要的那类题,可能值得;(4) 稳健性:换一组示例、换模型版本后这个提升还在吗?结论取决于这些,而不是 p 值本身。


11. 延伸阅读 · Further reading

  • Miller, E. (2024). Adding Error Bars to Evals: A Statistical Approach to Language Model Evaluations. arXiv:2411.00640.(聚类标准误、配对比较、功效分析在 LLM 评测里的应用)
  • Zhao, Z. et al. (2021). Calibrate Before Use: Improving Few-Shot Performance of Language Models. ICML.(示例的选择和顺序带来的巨大方差,第 2 讲的核心阅读)
  • Dror, R. et al. (2018). The Hitchhiker’s Guide to Testing Statistical Significance in Natural Language Processing. ACL.
  • Card, D. et al. (2020). With Little Power Comes Great Responsibility. EMNLP.(NLP 实验普遍功效不足)
  • Agresti, A. & Coull, B. (1998). Approximate is Better than “Exact” for Interval Estimation of Binomial Proportions. The American Statistician.(Wilson 等区间为什么比 Wald 好)
  • 本仓库:CS486 第 1 讲 的研究方法部分(Wilson、bootstrap、McNemar、Holm、最小可检测差异)。

12. 下一讲预告 · Next lecture

三篇前置讲到此结束:P1 讲了文字怎样变成 token,P2 讲了怎样可靠地调用模型、记录实验,P3 讲了怎样判断一个提示是不是真的更好。

第 2 讲进入原课的第一个技术主题:上下文学习(In-Context Learning)。§6.3 已经看到,只换示例就能让准确率差二十几个百分点。第 2 讲会追问这种波动从哪里来——模型有哪些系统性的偏差(偏向示例里多数的标签、偏向最近的示例、偏向常见的词),怎样用上下文校准修正它们,示例到底在教模型什么——并且用这一篇的方法,把每一个结论都放在置信区间里检验。

← 返回课程目录