filter-inspection / docs /AUDIT.md
daipath's picture
加入完整文档集:复现指南、逐文件说明、结果汇总、诚实性审计、已知边界
0e9808f verified
|
Raw
History Blame Contribute Delete
6.7 kB

诚实性审计

为什么需要这一章

本项目上一代的图级分类模型拿到 AUROC = 1.0。 拿 30 张目检干净的隔离图去试,**全部被打 0.999+**。

它学到的不是缺陷,是「这张图来自哪个压缩包」——一代数据里良品 100% 来自 good.rar、 不良 100% 来自其他包,类别与批次完全绑定。模型只要认出批次签名就赢了。

由此得出本项目的核心教训:

监督粒度决定诚实度。

同一批数据、同一个骨干,只改监督信号的粒度,隔离集误报率(quarantine_over_thr0)单调下降:

监督形式 隔离集误报
图级 BCE 1.00
特征判别器 0.92
DINO 线性探针 0.85
双头 cls 分支 0.31
判决头(含梯度隔离) 0.23
像素 top-k / 检测框 0.00

监督越细,越没有空间去学捷径。

所以二代数据上分类模型 AUROC 0.99+ 这件事,必须先证明它不是同一个骗局。 下面四道审计就是干这个的。


前提条件:捷径是否还存在

二代数据的关键改变:批次内良品与不良品混合采集,类别不再与批次绑定。

但「不绑定」不等于「无信息」。先量一下作弊空间还有多大:

python cls_probe.py

**批次指纹强度 = 92.7%**(frozen_probe_*.json 里的 pkg_acc)。

拿模型的冻结特征去预测「这张图属于 11 个包中的哪一个」,准确率 92.7%。 图像里确实带着强烈的批次签名(光照、白平衡、镜头状态逐包不同)。

这一条不是失败项,恰恰相反:它证明作弊是可行的。 如果批次不可分,后面三道审计就没有意义了——通过也说明不了什么。 现在的问题变成:模型有这个机会,它用了没有?


审计一:未见类硬正样本

做法:「碎」这一类(64 张)整类从未参与训练,模型从没见过。 如果模型学的是「缺陷长什么样」,它应该能抓到;如果学的是「批次签名」,它没理由认识。

结果cls_test_all.csvsui 列):

模型 未见类「碎」检出
bin_mobilenetv3_large_100_mid_320 (A) 100.0%
bin_resnet34_mid_320 (A) 100.0%
bin_efficientnet_b0_mid_320 (A) 98.4%
bin_resnet34_mid_320 (B) 98.4%
cls4_resnet34_mid_320 (B) 98.4%
cls4_resnet34_mid_320 (A) 92.2%

通过。 全榜 40 个可用模型的 sui 中位数 > 0.95。 模型抓的是「这里有东西不对」的通用特征,不是记住的类别模板。


审计二:跨批次泛化(B 套切分)

做法:把 样本_38016_P08262014 整包扣出来当 test。 训练集里完全没有这个批次的任何图p10_honest.jsonpkg_overlap = 0)。

如果模型靠批次签名,遇到全新批次应该崩掉。

结果

A 套(同批次可见) B 套(批次全新) 差值
bin_resnet34_mid_320 test AUROC 0.9911 0.9862 −0.0049
cls4_resnet34_mid_320 test AUROC 0.9867 0.9825 −0.0042

通过。 掉 0.005,和 AUROC 的标准误(test_se ≈ 0.005)同量级——统计上不可区分

另外 B 套的 eta2 = 0.000:包身份完全解释不了良品分数的方差。 A 套是 0.05–0.06,也很低。


审计三:冻结特征对照(决定性)

前两道审计有个共同弱点:它们能证明「模型没有完全依赖捷径」, 但证明不了「模型没有部分利用捷径」。第三道补上这个。

做法:冻结骨干,只训探针,比两种:

探针 用了标签吗 test AUROC
线性探针 用了良/不良标签 0.9461
只见良品的 kNN 完全没用标签 0.9634

判读逻辑

如果特征空间里存在一条「批次 → 类别」的捷径,那么给探针看标签,它必然能顺着标签把捷径挖出来, 表现应该显著优于一个压根不知道标签存在的 kNN。

实测反过来:不用标签的 kNN 赢了 0.017。

通过,而且这是最强的一条证据。 拿到标签没有带来任何优势, 说明特征空间里没有可被标签解锁的捷径——良品自己就构成一个紧致的簇, 偏离这个簇的就是缺陷,这是纯粹的异常检测结构。

未见类「碎」上同样:kNN 0.9375 vs 探针 0.7969。没用标签的反而更能抓未见缺陷。


审计四:良品分数分布

做法:看 185 张 test 良品被打了多少分。

结果169 张分数恰好为 0,只有 16 张非零。

这 16 张逐张目检的结果在 被模型报警的良品.html 里。 它们不是随机误报——多数确实有肉眼可见的异常(漏标的真缺陷、边缘毛刺、附着物)。

这也是「良品标签本身约 3.3% 存疑」这个结论的来源之一。


汇总

审计 结果 判读
批次指纹强度 92.7% 作弊空间
未见类「碎」检出 92–100% 学的是通用缺陷特征 ✓
跨批次泛化 −0.005 AUROC 噪声量级,没退化 ✓
冻结特征对照 kNN 0.9634 > 探针 0.9461 没有可解锁的捷径 ✓✓
良品分数分布 169/185 恰好为 0 非零的那些多是真缺陷 ✓

四道全过。二代数据上的分类结果是可信的。


但仍需谨慎的地方

审计通过 ≠ 可以直接上产线。三条限制:

  1. 审计只覆盖了本数据集的 11 个包。 换产线、换光源、换相机是分布外,审计结论不自动延续。

  2. gwz 归一化的抗漂移能力没验证过。 我曾推测灰世界白平衡能扛住色调漂移 (B 通道逐日 15→8→5),但 test 上 imnet 归一化反而拿了最高 AUROC(0.9976 vs gwz 0.9918)。 该推测已撤回。 要证明需要专门的色调漂移压力测试,本项目没做。

  3. 样本量限制无法用审计绕过。CAVEATS.md


如果你要在新数据上重做这套审计

最小可行版本,按性价比排序:

  1. 先跑冻结特征对照cls_frozen_probe.py)——一个脚本,最强证据,几分钟
  2. 留一个批次当 test(B 套那样)——需要重训,但直接回答「换批次灵不灵」
  3. 找一类不参与训练的缺陷当硬正样本——几乎零成本,只要你有一类可以牺牲
  4. 看良品分数分布——零成本,且顺带帮你找出漏标

第 1 条最值。如果只做一条,做它。