feat(localization): SHAP Partition 定位方法,并把每图框数上限默认收紧为 1

新增基于 SHAP Partition explainer 的定位,与 Grad-CAM 形成互补对照:

- engine/shap_explain.py:对目标类别求 SHAP 归因(只保留正贡献),以及方框平滑。
  遮挡用数值 masker 而非教程里的 inpaint_telea——后者依赖 opencv,而我们的图已做过
  逐图标准化,用 0(即该图均值)遮挡语义更干净
- scripts/shap_boxes.py:按类别抽样生成标签,并输出「原图 | Grad-CAM | SHAP」并排图
- shap 放入可选依赖组:uv sync --group explain

实测(225 张,每类 15):SHAP 在小目标类别上明显更准,框面积占比
blackdot 0.019 vs 0.269(14 倍)、mosquito 0.030 vs 0.173、whitedot 0.076 vs 0.253。
原因是 Grad-CAM 受限于 8x8 特征图(每格 16x16 像素),几像素的黑点根本不可分辨。
代价是单张 0.55 秒,全量 11k 张约 1.7 小时,而 Grad-CAM 全量只要 2 分钟。

调参时发现的坑:SHAP 第一版全部出 0 框,因为沿用了给 8x8 调的
min_area_ratio=0.02(在 128x128 上等于 328 像素)。参数不能跨分辨率照搬,
SHAP 默认改为 0.002。

--max-boxes 两个脚本都默认改为 1(原为 2):一张裁片通常只对应一处缺陷。
库函数 cam_to_boxes 的默认值同步收紧,相关测试改为显式传参而不依赖默认值。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Shaun Zhou
2026-09-10 16:10:50 +08:00
co-authored by Claude Opus 5
parent fc7136fddf
commit 9aa87d31a6
9 changed files with 2173 additions and 1344 deletions
+3 -1
View File
@@ -667,8 +667,10 @@ resnet18 在 128×128 输入下各层的 CAM 尺寸:layer4 只有 4×4、layer
### 几个调参点
- `--threshold`(默认 0.4):热力图相对最大值的阈值
- `--max-boxes`(默认 1):每张图最多保留几个框,按连通域内热力总和排序取前 N 个。
一张裁片通常只对应一处缺陷,多出来的框多半是噪声;确实有多缺陷的图再调大
- `--peak-ratio`(默认 0.75):次要连通域的峰值要达到全局最大值的这个比例才保留。
不加这条会在没有缺陷的角落刷出假框——实测把两框比例从 53% 降到 20%
不加这条会在没有缺陷的角落刷出假框
- `--padding`(默认 0.1):框四周外扩。CAM 倾向只覆盖最具判别性的部位(缺陷中心),
往往比真实缺陷范围小
- `--viz-per-class`(默认 20):每类存多少张可视化;`--viz-all` 全存(很慢很占盘)