要跑多少次,取决于你想证明什么
证明失败率低于 p:零失败要跑约 3/p 次;把成功率估到 ±5%:最多 385 个样本;检测两个版本差 5 个点:每个版本约 900 个。
三种问题,三个公式。样本量数的都是独立样本,同一个输入重跑 400 次不算 400 个。
1问题:"跑多少次"之前,先问"要证明什么"
面试官问"这个 Agent 上线前要跑多少次评测",答"100 次"或"越多越好"都会被追问:凭什么是 100?
样本量不是拍脑袋的数,它由你要下的结论反推出来。测开和 Agent 评测里常见的结论只有三种:
| 想说的话 | 统计问题 | 典型答案(95% 置信度) |
|---|---|---|
| "退款误操作率 ≤ 5%" | 零失败证明上界 | 59 次全过 |
| "任务成功率约 80%,误差 ±5%" | 估计到指定精度 | 246 个样本;不知道成功率时按最坏情况 385 个 |
| "新 prompt 比旧的好 5 个点" | 检测两个版本的差距 | 80% → 85%:每个版本 906 个(独立两组);配对能省多少看两个版本有多一致 |
三个问题的难度差了一个数量级。先说清楚是哪一种,再算 n。
2场景一:零失败,证明失败率 ≤ p(回顾 rule of three)
这是「rule of three」一章的内容。如果真实失败率等于 p,n 次全过的概率是 \((1-p)^n\)。要让这件事"巧合到只有 α 的概率",解出:
$$n \ge \frac{\ln \alpha}{\ln(1-p)} \approx \frac{-\ln\alpha}{p}$$α = 5%(95% 置信度)时 \(-\ln 0.05 \approx 3\),就是 rule of three:n ≈ 3/p。99% 置信度时常数变成 4.6。
| 要证明失败率 ≤ | 90% 置信 | 95% 置信 | 99% 置信 | 速算 3/p |
|---|---|---|---|---|
| 10% | 22 | 29 | 44 | 30 |
| 5% | 45 | 59 | 90 | 60 |
| 2% | 114 | 149 | 228 | 150 |
| 1% | 230 | 299 | 459 | 300 |
表里是精确法向上取整后的次数。速算 3/p 总是略多一点,面试时说 3/p 就够。
3场景二:把成功率估到 ±E
老板问"这个 Agent 成功率多少",你想回答"80%,误差 ±5%"。误差(区间半宽)约为 \(z\sqrt{p(1-p)/n}\),令它等于 E,反解 n:
$$n \approx \frac{z^2\,p(1-p)}{E^2}$$z 是置信度对应的正态分位数:90% 取 1.645,95% 取 1.96,99% 取 2.576。
| 预估成功率 p | ±10% | ±5% | ±3% | ±2.5% |
|---|---|---|---|---|
| 50%(最坏情况) | 97 | 385 | 1068 | 1537 |
| 80% | 62 | 246 | 683 | 984 |
| 90% | 35 | 139 | 385 | 554 |
两个规律:
- p = 50% 是最坏情况。\(p(1-p)\) 在 p = 0.5 时最大,等于 0.25。不知道成功率大概多少时,就按 50% 算,结果只会偏保守。
- 精度减半,样本量 ×4。E 在分母上是平方。±5% 要 385 个,±2.5% 要 1537 个。想把误差从 5 个点压到 1 个点,要 25 倍的样本。
4场景三:检测两个版本的差距
改了 prompt,想知道新版本是不是真的更好。这时有两种犯错方式:
| 错误 | 含义 | 控制它的参数 | 常用取值 |
|---|---|---|---|
| 误报(第一类错误) | 其实没变好,你说变好了 | 显著性水平 α | 5%(双侧) |
| 漏报(第二类错误) | 其实变好了,你没测出来 | β;功效 power = 1 − β | power 80% 或 90% |
再加上第三个量:最小可检测差距(效应量)δ。你关心"好 5 个点"还是"好 1 个点"?差距越小越难测出来。
两个版本各跑一批互不相关的样本(独立两组),基线成功率 \(p_1\),新版本 \(p_2 = p_1 + \delta\),每个版本需要:
$$n = \frac{\left(z_{1-\alpha/2}\sqrt{2\bar p(1-\bar p)} + z_{1-\beta}\sqrt{p_1(1-p_1)+p_2(1-p_2)}\right)^2}{\delta^2},\qquad \bar p = \frac{p_1+p_2}{2}$$| 基线 → 新版本 | power 80% | power 90% |
|---|---|---|
| 80% → 90%(差 10 个点) | 199 | 266 |
| 80% → 85%(差 5 个点) | 906 | 1212 |
| 90% → 95% | 435 | 582 |
| 50% → 55% | 1565 | 2095 |
| 80% → 82%(差 2 个点) | 6039 | 8084 |
α = 5% 双侧,正态近似、不带连续性校正,数字是每个版本的样本数。差距减半,样本量约 ×4,和场景二一样。
配对设计:同一批用例,两个版本都跑
离线评测里,两个 prompt 版本几乎总是跑同一批用例。这时应该逐条比较:大部分用例两个版本结果一样(都过或都挂),这些用例对"谁更好"没有信息;真正有用的是结果不一致的用例。
设两个版本结果不一致的用例占比为 ψ,配对设计需要的用例数(Connor, 1987):
$$n = \frac{\left(z_{1-\alpha/2}\sqrt{\psi} + z_{1-\beta}\sqrt{\psi-\delta^2}\right)^2}{\delta^2}$$| 80% → 85%,power 80% | 每个版本要跑的用例数 |
|---|---|
| 独立两组 | 906 |
| 配对,不一致率 ψ = 20% | 626 |
| 配对,不一致率 ψ = 10% | 312 |
| 配对,ψ = 5%(新版本只修好、没改坏) | 155 |
| 配对,ψ = 29%(两个版本的结果互不相关) | 909 |
▶互动演示:三种问题,各要跑多少次
5允许少量失败的发版门禁:漏放率和误拦率
把场景一变成流水线里的门禁:"跑 n 次,失败不超过 f 次就放行"。一个门禁有两个错误率,和上一节的 α、β 一一对应:
- 漏放率:一个坏版本(失败率 = q坏)碰巧通过门禁的概率,\(P(\text{失败数} \le f \mid q_{坏})\)。
- 误拦率:一个好版本(失败率 = q好)碰巧被拦下的概率,\(1 - P(\text{失败数} \le f \mid q_{好})\)。
失败数服从二项分布,两个概率都能精确算出来。把"通过概率"画成失败率的函数,就是抽样验收里的 OC 曲线(operating characteristic)。f = 0 时,漏放率就是 \((1-q_{坏})^n\),也就是 rule of three 里的 α。
以 q好 = 2%、q坏 = 10% 为例:
| 门禁规则 | 漏放率(10% 的坏版本通过) | 误拦率(2% 的好版本被拦) |
|---|---|---|
| 5 次全过 | 59.0% | 9.6% |
| 30 次全过 | 4.2% | 45.5% |
| 30 次最多挂 1 次 | 18.4% | 12.1% |
| 89 次最多挂 4 次 | 5.0% | 3.3% |
"30 次全过"漏放率够低,但好版本有将近一半会被拦下。团队很快就会习惯"挂了再跑一遍"。最多跑 3 轮、有一轮全过就放行,坏版本的漏放率从 4.2% 涨到 12.2%,门禁的保证就没了。
▶模拟门禁:跑 n 次,最多允许 f 次失败
模拟结果
点"模拟 200 轮发版":每一格是一轮,按真实失败率 q 随机跑 n 次,失败 ≤ f 次算放行(绿),否则拦下(红)。
6样本量数的是独立样本
上面所有公式里的 n,都是独立样本的个数(见「独立性假设」一章)。同一个输入重跑 400 次,只能说明这一个输入的 flaky 率,对"Agent 在这类任务上的成功率",换算成独立样本也只有个位数(公式上限约 1/ρ ≈ 3.3),而且只有 1 个用例,根本推不到这类任务。
如果每个用例跑 m 次,用例内相关系数为 ρ,有效样本是 \(n/(1+(m-1)\rho)\)。反过来,要凑够 \(n_{\text{req}}\) 个有效样本,需要的用例数是:
$$C = \frac{n_{\text{req}}\,\bigl(1+(m-1)\rho\bigr)}{m}$$| 目标:±5% 精度(需要 385 个有效样本),ρ = 0.3 | 用例数 | 总运行次数 |
|---|---|---|
| 每个用例跑 1 次 | 385 | 385 |
| 每个用例跑 5 次 | 170 | 850 |
| 1 个用例跑 385 次 | 做不到:有效样本上限约 1/ρ ≈ 3.3 | |
✎练习
7面试要点与代码
一句话讲清楚
样本量由要下的结论决定。证明失败率低于 p,零失败要跑约 3/p 次,失败率 <10% 要 30 次全过;把成功率估到 ±E,要 1.96²·p(1−p)/E²,最坏 ±5% 是 385 个,精度减半样本 ×4;比较两个版本要定 α、功效和最小差距,80% 到 85% 独立两组每边约 900 条,同一批用例配对跑,不一致率低时能省一大半。所有 n 数的都是不同的用例,不是重跑次数。
常见错误说法
❌ "估计误差 ±1%,跑 1000 次":±1% 最坏要 9604 个,1000 个只能到 ±3.1%。
❌ "新版本 85%、旧版本 80%,跑了 100 条,新版本更好":每边 100 条时差 5 个点的功效只有约 15%,这点差距多半是噪声。
❌ "30 次全过的门禁很严格":对坏版本严格,对好版本也严格。2% 失败率的好版本有 45% 会被拦,最后变成"挂了重跑"。
❌ "同一个用例跑 400 次,样本量 400":有效样本看的是用例数。
from math import ceil, log, sqrt
from scipy.stats import binom, norm
def n_zero_failure(p: float, conf: float = 0.95) -> int:
"""零失败时,证明失败率 <= p 需要的次数(精确法)。"""
return ceil(log(1 - conf) / log(1 - p))
def n_precision(p: float, e: float, conf: float = 0.95) -> int:
"""把成功率估到 ±e 需要的独立样本数;p 未知时用 0.5。"""
z = norm.ppf(1 - (1 - conf) / 2)
return ceil(z ** 2 * p * (1 - p) / e ** 2)
def n_two_groups(p1: float, p2: float, alpha: float = 0.05, power: float = 0.8) -> int:
"""独立两组比较成功率,每组需要的样本数(双侧、无连续性校正)。"""
za, zb = norm.ppf(1 - alpha / 2), norm.ppf(power)
pbar = (p1 + p2) / 2
num = za * sqrt(2 * pbar * (1 - pbar)) + zb * sqrt(p1 * (1 - p1) + p2 * (1 - p2))
return ceil(num ** 2 / (p1 - p2) ** 2)
def n_paired(psi: float, delta: float, alpha: float = 0.05, power: float = 0.8) -> int:
"""配对设计(McNemar)需要的用例数,psi 是结果不一致的用例占比(Connor, 1987)。"""
if not 0 < abs(delta) <= psi:
raise ValueError(f"需要 0 < |delta| <= psi,收到 delta={delta}, psi={psi}")
za, zb = norm.ppf(1 - alpha / 2), norm.ppf(power)
return ceil((za * sqrt(psi) + zb * sqrt(psi - delta ** 2)) ** 2 / delta ** 2)
def gate_errors(n: int, f: int, q_good: float, q_bad: float) -> tuple[float, float]:
"""门禁"n 次里最多 f 次失败"的(漏放率, 误拦率)。"""
return binom.cdf(f, n, q_bad), 1 - binom.cdf(f, n, q_good)
print(n_zero_failure(0.05)) # 59
print(n_precision(0.5, 0.05)) # 385
print(n_two_groups(0.80, 0.85)) # 906
print(n_paired(0.10, 0.05)) # 312
print(gate_errors(89, 4, 0.02, 0.10)) # (0.0497, 0.0334)
公式显示依赖 KaTeX(CDN),断网时公式会显示成原始 LaTeX 源码,交互部分不受影响。