报告里写『通过率 92%』,等于只报了一半:把 AI 测试数字连置信区间一起交出去

简介: AI测试通过率本质是分布而非单点,盲目报告单一数值易误导决策。本文倡导用Bootstrap法计算95%置信区间(如“92%,95%CI [86%, 95%],n=210”),将不确定性显性化:区间宽度反映数据可靠性,重叠判断替代主观“显著”断言。纯标准库实现,可无缝嵌入CI流水线——让质量报告真正说出“我有多确定”。

同一套回归用例,周一早上跑完是 88%,你不放心又跑了一次,变成 94%。周报你贴了 94%——贴 88% 那次,评审会上要被人追问『怎么又掉了』;贴 94% 这次,没人记得它统共就跑了十七八条。数字没撒谎,你只是从一摞结果里挑了最顺眼的那一颗珠子。

AI 应用的通过率、稳定性,天生是一个分布,不是一个点。模型输出的随机性、用例里那一两条边界抖动,都会让『同一次改动』每次跑出来的通过率在一个带子里晃。报告只交一个点,是系统性地把『我其实没那么确定』这件事抹平了。正确做法,是把每个关键数字连它的不确定度一起交出去。

一、把区间交出去:通过率 X%,95%CI 也要一起写

先说最小动作。你手上有一组通过记录——每条用例跑过记 1、没过记 0,或者你把多次运行的通过率攒成一列。别只算平均,用 bootstrap 从这组记录里有放回地重采样几千次,每次算一个通过率,把这一堆通过率排序,取中间 95% 的两个端点,就是置信区间。报告里那行字,于是从『通过率 92%』变成『通过率 92%,95%CI [86%, 95%],n=210』。读者第一次能看见这个数字到底有多『实』。

呈现口径 读者会得出什么结论 什么时候会误导
裸点估计『通过率 92%』 系统稳定在 92%,可以直接跟 95% 的放行线比 n 很小或多次波动时:一个数盖住了它其实只跑了十几条
点 + 区间『92%,95%CI [86%, 95%],n=210』 真实值大概率落在这个带里,够不够格卡线一眼能判 几乎不误导;只需提醒一句:区间说的是『当期真值』,不是『下次跑分落点』
两版区间重叠比较 两次到底是不是『真的不一样』 只报两个点就下『显著提升 / 明显退化』:两个区间其实大面积重叠

bootstrap 是公开统计方法,不用连任何外部服务,纯标准库就能跑——这也正是它适合长在流水线里的原因。

还有一层用 bootstrap 而不是背公式的理由:通过/失败是 0/1 数据,当真值偏向九成以上时,抽样分布明显左偏,用『±1.96×标准误』那套正态近似算出来的区间,在小样本下会越过 100%、甚至越过 0,覆盖率一塌糊涂。bootstrap 不假设正态,它把样本当成总体本身,重采样几千次,区间长成什么样完全跟着数据走——样本越小,它就越宽,这个『宽』恰恰是报告里最该被看见的诚实。

二、区间宽度本身就是一条质量结论

把那套十七八条的用例塞进脚本,跑出来是这个样子:周一那次『通过率 88%,95%CI [71%, 100%]』,重跑那次『通过率 94%,95%CI [82%, 100%]』。6 个点的差距,背后只是两条用例翻了个面——因为 n=17,一条用例的值就差不多占 6 个百分点,点估计当然站不稳。区间宽到 29 个点,等于报告在喊:这次样本太少,不足以单独支撑放行。这是一条过去被『92%』这种漂亮数字盖住的结论。

再换一套:同一套逻辑扩到 210 条,通过率还是 91%,可区间收紧到 [88%, 95%],宽度只剩 7 个点。同样是『九成通过』,一个宽到不敢签字、一个够到能拿去和 90% 的放行线比。宽度不是噪音,宽度是你本该写进报告的第二条结论。

顺带堵一个常被误读的地方:置信区间说的是『这批改动真实通过率大概率藏在哪』,不是『下一次再跑,通过率会落在哪』。前者是关于真值、关于『我有多确定』,后者是关于单次跑分的波动。报告里把区间按真值的意思写,它才能拿去当放行依据;一旦读者把它错当成下次跑分的预言,那句『95%CI [88%, 95%]』就会被理解成『下次跑一定在 88 到 95 之间』——那就不是同一件事了,卡线的锅也说不清。

【配图1插入位置:本小节之后】

三、比较两个数字,先看区间重不重叠

『新版本通过率 93%,旧版本 90%,提升 3 个点,建议升级』——这种话在报告里出现一次,就该被拦一次。把两次各 n=100 的结果丢进脚本:旧版 90% 落在 [84%, 95%],新版 93% 落在 [88%, 97%],两个区间重叠了将近八成。重叠到这个份上,3 个点的差完全在样本波动能解释的范围内,写『显著提升』就是把运气写成了能力。规矩很简单:新旧两个区间大幅重叠,就老实写『本次差异落在噪声范围内』;只有区间基本分离,才配得上『显著』这两个字。

反过来,当两个区间确实基本分离——比如新版下压到了旧版上界之上——那才敢理直气壮写『显著提升』,而且能顺带写清是怎么判的:一句『两次 95% 区间不重叠』,就能挡住所有『你这是不是运气』的口头争执。『显著』『明显』这类词,在报告里永远不该脱离动作单独出现;出现了,就得能回答『拿什么判的显著』。

四、报告里这几个字段,得并排站

区间不是孤立的一列,它得和几个字段捆在一起才读得懂。单看一个 [88%, 95%] 没意义,得知道它是 210 条跑出来的、得知道分母口径是同一批用例、得知道是哪一次运行。

字段 演示值 为什么必须并排出现
通过率(点估计) 91% 给个体感,但单独看会骗人
样本量 n 210 决定区间宽度的根,没了它区间无从算起
95% 置信区间 [88%, 95%] 点估计的可信带,能不能卡线看它
口径 同一用例集、同一配置 防拿不同分母、不同配置的数字横比
运行时间 2026-09-24 01:12 · #4471 防拿旧一次的数冒充这一次

口径和运行时间这两栏看着像摆设,其实卡的是最常见的翻车:把上次大样本的区间宽度,套到这次小样本的通过率上,或者拿三个月前那次的漂亮数字给今天背书。

五、跑一遍:纯标准库把区间算出来

下面这段只用标准库,喂进去的就是本文演示构造的通过记录,开箱即跑。接自家工程时,把 records 换成你 pytest 结果里每条用例的 0/1,或多次运行攒出的通过率列表即可。

# -*- coding: utf-8 -*-
"""pass_rate_interval.py —— 通过率连置信区间一起交(纯标准库,开箱即跑)

用法:python pass_rate_interval.py
输入一组 0/1 通过记录,bootstrap 重采样算 95% 置信区间,
输出报告用文案『通过率 X%,95%CI [a%, b%],n=Y』。数据均为演示构造。
"""
import random


def point_estimate(records):
    return sum(records) / len(records)


def bootstrap_ci(records, iters=10000, level=0.95, seed=20260924):
    """对 0/1 记录做 bootstrap:有放回重采样 n 次、每次算一个通过率,
    把通过率分布排序后取分位数当置信区间(percentile 法)。"""
    rng = random.Random(seed)
    n = len(records)
    means = sorted(sum(rng.choices(records, k=n)) / n for _ in range(iters))
    lo = int((1 - level) / 2 * iters)
    hi = int((1 + level) / 2 * iters) - 1
    return means[lo], means[hi]


def fmt_pct(x):
    return f"{x * 100:.0f}%"


def report_line(records, iters=10000):
    p = point_estimate(records)
    lo, hi = bootstrap_ci(records, iters=iters)
    return f"通过率 {fmt_pct(p)},95%CI [{fmt_pct(lo)}, {fmt_pct(hi)}],n={len(records)}", hi - lo


def overlap(a, b):
    """重叠宽度占较窄区间的比例:>0.5 视为『分不出胜负』,别写显著提升。"""
    inter = max(0.0, min(a[1], b[1]) - max(a[0], b[0]))
    narrowest = min(a[1] - a[0], b[1] - b[0])
    return inter / narrowest if narrowest else 1.0


def gen_demo_passes(n_true, n_total, seed):
    rng = random.Random(seed)
    recs = [1] * n_true + [0] * (n_total - n_true)
    rng.shuffle(recs)
    return recs


def main():
    print("== 场景A:同一套用例,样本很小,点估计站不稳 ==")
    for lab, rec in [("周一那次", gen_demo_passes(15, 17, seed=1)),
                     ("手快重跑那次", gen_demo_passes(16, 17, seed=2))]:
        line, width = report_line(rec)
        print(f"  {lab}:{line}(区间宽度 {fmt_pct(width)})")

    print("\n== 场景B:同一套逻辑扩到上百条,通过率没动,区间却收窄 ==")
    line2, width2 = report_line(gen_demo_passes(192, 210, seed=3))
    print(f"  {line2}(区间宽度 {fmt_pct(width2)})")

    print("\n== 场景C:新旧两版通过率,先过区间重叠关 ==")
    old, new = gen_demo_passes(90, 100, seed=4), gen_demo_passes(93, 100, seed=5)
    lo_old, hi_old = bootstrap_ci(old)
    lo_new, hi_new = bootstrap_ci(new)
    print(f"  旧:{report_line(old)[0]}")
    print(f"  新:{report_line(new)[0]}")
    ov = overlap((lo_old, hi_old), (lo_new, hi_new))
    verdict = "两区间大幅重叠,别写『显著提升』" if ov > 0.5 else "区间基本分离,可写『显著提升』"
    print(f"  重叠比例 {ov * 100:.0f}% → {verdict}")


if __name__ == "__main__":
    main()

两个刻意的处理值得点名。其一,bootstrap 固定了随机种子(seed=20260924),这样这份报告里的区间下次重算还是同一个——用随机方法去算一份要进报告的确定性数字,得先把重采样这层随机按住在报告里,不然『区间』本身又成了新的一颗珠子。其二,overlap 判的是『重叠宽度占较窄区间的比例』,不是简单看有没有交集;只要沾一点边就算分开太松,会把噪声差判成显著。脚本跑出来的三组数,就是前面几节引用的全部数字:n=17 两条宽到 [71%, 100%]、[82%, 100%],n=210 收到 [88%, 95%],新旧对比重叠 78% 判成『别写显著提升』。

六、挂进流水线:报告正文一行带区间

区间化这件事最好长在流水线里,否则又变成『想起来才做』。pytest 出结果之后加一步统计,直接写进 step summary:

- run: pytest --junitxml=report.xml
- run: python pass_rate_interval.py >> $GITHUB_STEP_SUMMARY

从此报告里那句通过率,天生带着它的区间和 n。谁想只贴那颗最顺眼的珠子,脚本第一行就把区间甩在他脸上。

写这行报告文案时,给个小的语序建议:先点估计给体感,再区间给幅度,最后 n 给底气——『通过率 91%(95%CI 88%–95%,n=210)』。别把区间放在最前面,读者抓不到锚;也别把 n 省在文末脚注里,忙的人根本不会往下翻,而 n 恰恰是那个能一票否决整句结论的数字。

七、回到那场评审会

下次有人拿你周报里那个漂亮的百分比对上『为什么又掉了』,答案不再是运气:那个数一直是带,不是点;宽的时候本就不该拿去签字,窄的时候才有资格和放行线比。把区间交出去,不是把报告写复杂,是终于把『我有多确定』这件一直在心里、却从没写下来的事,写下来了。

诚实的质量报告,报的不是一个通过率,是一整个『这个数大概落在哪』——只交点估计,等于把确定性的成本悄悄转嫁给了读报告的人。

相关文章
|
7天前
|
人工智能 JSON API
全网刷屏的 Jev 模型正式开放!一手实战测评 + 保姆级教程
全网爆火的 Jev 模型是什么?有什么用?怎么使用?怎么接入 AI 编程工具?效果真的好么?傻子可懂的 Jev 保姆级实战教程 + 项目实战测评来啦
6911 9
|
5天前
|
人工智能 测试技术 API
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
Jev是TypeSafe AI推出的“系统一模型”,不生成文本,专做毫秒级结构化决策:Choice(多选)、Score(打分)、Noul(是非概率)。响应快193倍、成本低444倍,适合工单路由、内容审核、测试定级等高频判断场景。
1390 4
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
|
6天前
|
人工智能 并行计算 PyTorch
秋叶 ComfyUI 2026 整合包 v3.2 完整部署教程:Python 3.13 + Torch 2.13 全栈升级
秋叶aaaki ComfyUI 2026年8月整合包v3.2正式发布!全面升级Python 3.13.11、PyTorch 2.13.0+cu130及ComfyUI v0.30.2,原生支持MiniMax H3、Wan 2.2、Qwen-Image-2.1等2026主流音视频/图像模型,解压即用,无需环境配置。
850 5
|
19天前
|
人工智能 自然语言处理 安全
阿里云千问办公 QwenWork详细介绍:产品核心能力、典型场景、价格及常见问题解答
千问办公是阿里云推出的一站式AI办公平台,主打"不止于对话,更注重交付",依托通义千问旗舰大模型,用户一句话即可完成数据分析、PPT生成、视频剪辑等复杂任务,直接输出可用成果。产品深度打通钉钉生态与企业OA,覆盖桌面端、网页端,提供企业标准版198元/人/月等多档订阅方案,新用户注册即赠2000积分,适配工程师、HR、财务等多职业办公场景,成为能动手干活的"全能AI同事"。
3433 10
|
13天前
|
缓存 IDE Java
【保姆级】Android Studio下载、安装和汉化教程(2026最新)
Android Studio 是 Google 官方推出的免费 Android 应用开发集成环境,基于 IntelliJ IDEA,内置模拟器、调试器、性能分析及 Compose 界面工具,功能全面,文档丰富,是安卓开发首选工具。(239字)
1509 1
|
18天前
|
IDE 开发工具
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
Qoder国际版上线全新内置大模型Sonus(/ˈsoʊnəs/),全球领先,专精超长任务执行与电脑操作(Computer Use)。配合Qoder桌面端0.2.3版本,可自主完成编程、金融建模、科研及表格制作等复杂工作。现全面支持Qoder全系产品,效率提升3.2倍。
1897 9
Qoder 上线 Sonus 模型,Computer Use 能力全面增强

热门文章

最新文章