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

逐文件使用说明

41 个脚本、11 张结果表、5 份 HTML、51 个训练产物目录。 所有脚本的工作目录都假定是 /workspace/CV_Task/seg3/newdata,解释器 /workspace/venvs/seg/bin/python


目录结构

newdata/
├── raw/                     解包后的原始数据(3728 PNG + 1977 JSON,11 个包目录)
├── splits/
│   ├── splitA/              全混合 8:1:1
│   │   ├── meta.csv         3611 行,切分表
│   │   ├── dropped.csv      117 行,剔除清单带原因
│   │   ├── best.pt          分割模型(按 val 选)
│   │   ├── eval_report.json 分割评估
│   │   ├── curve_{val,test}.csv   阈值 → 逐类检出曲线
│   │   ├── geom_{val,test}.csv    逐图几何量测
│   │   ├── viz_{val,test}/  分割可视化 PNG
│   │   ├── aug_{none,weak,mid,strong}/   增广消融
│   │   ├── cls/             第一阶段分类模型(13 个)
│   │   └── cls2/            第二阶段多轴消融(19 个)
│   └── splitB/              跨批次,结构同上
├── release/                 部署包(predict.py + onnx + 文档)
├── docs/                    本文档集
└── *.py *.sh *.csv *.json *.html

脚本:数据准备

fetch_and_unpack.sh (25 行)

样本7_27.zip 并调 unpack.py。一键起步。

bash fetch_and_unpack.sh

unpack.py (87 行)

递归解包嵌套 zip。两个关键行为

  • GBK 文件名修复:zip 内中文名以 cp437 存储,按 cp437 → gbk → gb18030 → big5 回退解码。不修则目录名全乱码,pkg 字段失效。
  • zip-slip 防护:拒绝解到 raw/ 之外。
python unpack.py <zip路径> <输出目录>

输出:raw/ 下 11 个包目录。

inventory.py (175 行)

全量清点,解析批次 / 机器 / 会话 / 采集配置 / 标注精细度。

python inventory.py            # -> inventory.csv (3728 行, 854 KB)

关键约束:无批次号或无机器号的包,字段留空,不做默认填充。11 个包中 5 个无机器号。

metrics_fix.py (164 行)

逐图几何指标。修了原版 metrics.py 的两个 bug:circle 类型 shape 漏计(展开为 24 边形)、 tightness 指标无物理意义(换成 in_body_ratio + vert_density)。

python metrics_fix.py          # -> metrics_fixed.csv (1948 行, 313 KB)

build_splits.py (219 行)

生成两套切分。分组单位 group = pkg‖sess,同组不跨 split;剔除 rare_class / zero_shapes / no_json。

python build_splits.py         # -> splits/split{A,B}/{meta,dropped}.csv

build_dataset_v2.py (207 行)

历史脚本,一代数据的构建流程。保留用于对照,新流程不用它。

make_samples.py (206 行)

每个包抽 N 张交给 subagent 目检。产出 agent_tasks.json(抽样清单)与 qa_results.json(核查结论,440 KB)。


脚本:分割路线

train_v3.py (181 行) ★ 主训练脚本

SMP U-Net + resnet34,三类分割(划痕 / 麻点 / 崩边)。

python train_v3.py <split目录> <epochs> <size> <batch> <workers>
python train_v3.py splits/splitA 200 384 32 10

相对初版的改动:全量 RAM 预载、batch 32 + channels_last + bf16、gwz 归一化、固定种子 42、 test 泄漏断言。产出 best.pt / last.pt / train_summary.json / trainlog.csv

train_v2.py (158 行)

上一代训练脚本,保留对照。

train_aug.py (188 行)

增广消融专用(none / weak / mid / strong)。

python train_aug.py <split目录> <aug> <epochs> <size> <batch> <workers>

run_aug_ablation.sh (35 行)

4 档 × 2 切分 = 8 个作业,每波 4 并发。

bash run_aug_ablation.sh 200

eval_v3.py (206 行) ★ 主评估脚本

val + test 一次性评估,不做阈值标定(标定在 optimize_rules.py)。

python eval_v3.py splits/splitA

产出 eval_report.json(逐类 Dice/IoU + 三种 AUROC)、eval_{val,test}.csv(逐图分数)、 curve_{val,test}.csv(阈值扫描 → 逐类检出)。

eval_v2.py (151 行) / eval_aug_models.py (185 行)

上一代评估 / 增广消融批量评估(产出 aug_compare.json)。

measure_geom.py (180 行)

从分割预测图里量 7 个几何量:划痕长度/宽度/面积/条数、麻点颗数/最大颗/面积/直径、崩边面积/弧长/过角。

python measure_geom.py splits/splitA    # -> geom_{val,test}.csv

optimize_rules.py (153 行)

搜几何判据阈值,同时输出 oracle(test 上调,作弊)与 honest(val 上调)两套,供对比过拟合幅度。

python optimize_rules.py    # -> rules_maxfp3.json, rules3_maxfp3.json

脚本:分类路线

cls_train.py (185 行) ★

timm 骨干,二分类或四分类。

python cls_train.py <split目录> <backbone> <aug> <task> <epochs> <size> <batch>
python cls_train.py splits/splitA efficientnet_b0.ra_in1k mid bin 60 320 32

产出 best.pt / summary.json / train.logsplits/<sp>/cls/{task}_{bb}_{aug}_{size}/

cls_train2.py (233 行) ★ 多轴版

6 个正交轴,命名带全部超参。

python cls_train2.py splits/splitA --ep 60 \
  --bb efficientnet_b0.ra_in1k --sz 320 --aug mid --norm gwz --loss ce --task bin
参数 取值
--sz 224 / 256 / 320 / 384 / 448
--norm gwz(灰世界+z-score)/ imnet / zscore
--aug none geo photo weak mid strong mixup cutmix
--loss ce / ce_nols(无标签平滑)/ focal
--task bin / cls4

run_cls_sweep.sh (60 行) / run_cls2.sh (30 行) / run_cls_aug.sh (17 行)

批量调度。run_cls_sweep.sh 分两阶段(bash run_cls_sweep.sh 1|2),run_cls2.sh 跑 19 个多轴作业。 并发数由 CONC 控制(4090 上 2–3 合适)。

cls_eval.py (152 行)

单模型评估,产出 eval.json(含混淆矩阵与 fp_budget 表)。

confusion 的方向是 外层 = 预测类,内层 = 真实类。读反会得到完全不同的数字。

cls_eval_all.py (157 行) ★ 统一评测

把所有分类模型(各用自己的 size/norm)评到 test。

python cls_eval_all.py                       # 默认 splitA + splitB
python cls_eval_all.py splits/splitA         # 只评一套

产出 cls_test_all.csv(42 行)。脚本主动声明选择偏差:在 test 上横比 N 个模型再挑最好是有偏的, 所以它额外打印「按 val 预先选定」的那个模型——只有那个数字是无偏的

cls_tta_ens.py (92 行)

TTA×8(4 旋转 × 2 翻转)与模型集成。

python cls_tta_ens.py splits/splitA          # -> tta_ens.json

cls_collect.py (34 行)

把散落的 summary.json 汇成 cls_all_results.csv


脚本:诚实性审计 ★★

这四个脚本是本项目最重要的部分。原理见 AUDIT.md

cls_probe.py (188 行)

三合一审计:

  1. 批次指纹——用模型特征预测「这张图来自哪个包」,准确率越高说明可作弊空间越大
  2. 未见类「碎」硬正样本——这一类整类未参与训练,检出率 sui 应接近 1
  3. eta²——包身份能解释多少良品分数方差,越低越好
python cls_probe.py            # -> cls_probe_all.csv

cls_frozen_probe.py (80 行) ★ 决定性审计

冻结骨干特征,对比两种探针:

  • 有标签线性探针(用了良/不良标签)
  • 只见良品的 kNN(完全没用标签)

如果存在可解锁的捷径,有标签的必然显著胜出。实测 kNN 0.9634 > 探针 0.9461——它没有。

python cls_frozen_probe.py splits/splitA resnet34 320
# -> frozen_probe_resnet34_320.json

cls_hardprobe.py (59 行)

硬正样本专项检验。


脚本:报告与指标

precision_table.py (118 行)

产线不良率 × 不良桶良品率上限 → 可达性表。

python precision_table.py      # -> precision_table_{A,B}.csv (各 36 行)

gen_p10_report.py (287 行)

产线不良率固定 10% 的专项报告。阈值在 val 上定、test 只评一次, 产出 p10_honest.json + HTML。

这个脚本存在的原因:我此前有两次在 test 上选阈值(precision 表、以及早期只用 train/val 的切分), 得到 A 套不良桶良品率 0% 的假象。诚实口径重算是 **17.89%**。这个脚本就是修正版。

gen_precision_report.py (182 行) / gen_report.py (613 行) / gen_showcase.py (323 行) / gen_nonzero_goods.py (178 行)

HTML 报告生成器,见下方 HTML 清单。

make_granularity_figs.py (220 行) / make_risk1_figs.py (185 行)

标注精细度对比图、风险 1(良品漏标)实例图。

bench_*.py (39/170/49/124 行)

CPU 核数 / 内存 / 吞吐基准,产出 cpu_bench.json cpu_cores.json throughput.json

export_onnx.py (46 行)

导出 ONNX。**dynamo=False 不能删**——新导出器会把权重拆成 .onnx.data,破坏单文件分发。


结果表字段说明

cls_test_all.csv(42 行,主榜单)

含义
split A / B
task bin / cls4
backbone size aug norm loss param 超参与参数量(M)
val_auroc test_auroc AUROC
test_se AUROC 的 Hanley–McNeil 标准误,约 0.005,是噪声地板
rec@K 在 val 上取阈值使 val 误报 ≤K,搬到 test 后的检出率
fp@K 该阈值下 test 上实际发生的误报数(不受 K 约束,可能超)
imp_test test 口径不良桶良品率 = FP/(TP+FP)
imp_line10 换算到产线不良率 10% 的不良桶良品率
sui 未见类「碎」的检出率(诚实性指标,越高越好)
dir 模型目录

cls_probe_all.csv(6 行,审计)

含义
tau 阈值
test_rec test_fp test 检出 / 误报
sui 未见类「碎」检出率
dirty 良品中疑似脏标的检出率
nolabel 无标注缺陷图的检出率
eta2 包身份解释良品分数方差的比例,越低越好(A 套 0.05–0.06,B 套 0.00)
good_med def_med 良品 / 缺陷分数中位数

precision_table_{A,B}.csv(各 36 行)

列名已是中文:产线不良率 不良桶中良品率上限 可达 tau 检出率 漏检率 误报率 实际不良桶良品率 放行桶良品纯度 放行桶混入不良 每万片漏检 每万片冤杀 误报率CP95上界 最坏不良桶良品率 最坏放行桶纯度 TP FP split

误报率CP95上界 是 Clopper–Pearson 精确上界。**185 张良品下,即使 0 误报, 95% 置信上界也有 1.61%**——这是样本量的硬限制,不是模型的问题。

curve_{val,test}.csv(9 行)

tau 良品误报率 误报数 总检出率 检出数 划痕 麻点 崩边。 分割的阈值扫描曲线,麻点那一列是本项目最重要的一张表(见 INDEX.md)。

其他

文件 内容
inventory.csv 3728 行全量清点
metrics_fixed.csv 1948 行几何指标
qa_results.json subagent 目检结论(440 KB)
agent_tasks.json 抽样清单
rules_maxfp3.json 单阈值 + 7 维几何,oracle vs honest
rules3_maxfp3.json 3 自由度几何,按误报预算 0–5 逐档
p10_honest.json 产线 10% 的诚实口径结果
cls_all_results.csv 25 行,训练期汇总(含 best_ep tr_loss va_loss
cpu_bench.json cpu_cores.json throughput.json 性能基准

HTML 报告(5 份)

文件 大小 内容
样本7_27_数据核查报告.html 2.1 MB 数据核查主报告。11 个包逐包核查:批次/机器识别、标注精细度分档、缺陷类型分布、抽样目检结论、6 类数据质量风险
分割效果展示.html 6.4 MB 每种缺陷类型 / 良品 / 误判良品各 10 张,A、B 两套都有,原图 + 预测掩码叠加
被模型报警的良品.html 2.6 MB 185 张 test 良品里被打非零分的 16 张。169 张分数恰好为 0
不良率10%_判废纯度报告.html 0.7 MB 产线不良率 10% 下的判废纯度,诚实口径
判废纯度对照表.html 不良率 × 纯度上限的可达性矩阵

训练产物目录(51 个)

每个目录里:best.pt(按 val 选)、summary.json(超参 + val 指标)、train.log、 部分有 eval.json(含混淆矩阵)。

位置 数量 内容
splits/splitA/cls/ 13 第一阶段:bin × {convnext_nano, efficientnet_b0, mobilenetv3, resnet34, vit_small} + cls4 × {mobilenetv3, resnet34}
splits/splitA/cls2/ 19 第二阶段多轴消融
splits/splitB/cls/ 9 B 套对照
splits/split{A,B}/aug_*/ 8 分割增广消融
splits/split{A,B}/best.pt 2 分割主模型

命名规则:

  • cls/{task}_{backbone}_{aug}_{size}
  • cls2/{task}_{backbone}_{aug}_{norm}_{loss}_{size}

release/ 部署包

文件 说明
predict.py 单文件推理,只依赖 onnxruntime + numpy + pillow(+ openpyxl 可选)
filter_binary.onnx (16.8 MB) 判废模型,mobilenetv3_large_100
filter_binary.json 元信息 + 阈值标定表
filter_4class.onnx (85.1 MB) 类型模型,resnet34
filter_4class.json 元信息
requirements.txt 4 个 pip 包
README.md 技术说明
操作指南.md 傻瓜版:下载 + 一条命令
数据集下载指南.md 图片仓库下载方式
sample_images/ 22 张样例(来自锁箱 test)

predict.py 用法

python predict.py -i 图片.png                              # 单张
python predict.py -i 图片目录/ -o 结果.xlsx                 # 批量(递归)
python predict.py -i 图片目录/ -o 结果.xlsx --with-type     # 附缺陷类型
python predict.py -i 图片目录/ -o 结果.csv                  # 不装 openpyxl
python predict.py -i 图片目录/ -o r.xlsx --threshold 0.787  # 调松紧

预处理必须与训练逐字节一致:等比缩放 → 居中补零 → 逐图灰世界白平衡 → 逐图 z-score。 改动其中任何一步,标定好的阈值全部失效。

换自己重训的模型:把新的 filter_binary.onnx + .json 放在可执行文件旁边即可, find_model() 优先找 exe 同目录,找不到才用打包进去的。不用重新打包。