refactor: 按实际的五步工作流裁掉无关代码

实际工作流是:simclr 训练 -> 聚类 -> 人工归类 -> 分类训练 -> GradCAM/SHAP 生成
热力图与 box。据此移除不参与其中的检测/定位链路,共 31 个文件、约 2600 行:

- 模型:defect_net、postprocess、necks/、heads/center_head
- 数据:film_defect(YOLO 读取端)、target_encoder
- 引擎:trainer、evaluator、losses
- 入口:train.py、eval.py
- 脚本:convert_annotations、split_dataset、export_onnx、profile_inference
- 配置:configs/{train,eval,model,dataset}
- utils/labels(多类/单类标签模式,仅检测分类头使用)

共享模块按实际用量瘦身:engine/metrics 只留 AverageMeter(检测指标随之移除);
datasets/yolo 只留写出侧(IMAGE_SUFFIXES 与 write_data_yaml)——第 5 步产出的
YOLO 标签是给外部检测训练用的交换格式,读取端不再需要。

裁剪过程中修掉一个真 bug:generate_boxes 的 --stage 默认 6(layer3)对 tiny_conv
这类非 nn.Sequential 骨架直接抛异常。现在自动退回骨架最终输出并警告,
另加 --stage -1 显式选择最终输出。

五步工作流已端到端实跑验证(simclr 1 轮 -> 聚类 -> 导出 -> 分类 1 轮 ->
gradcam 与 shap 两种方法各生成一遍)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Shaun Zhou
2026-09-11 10:27:20 +08:00
co-authored by Claude Opus 5
parent 57446c2f10
commit 86c86b105c
45 changed files with 186 additions and 3218 deletions
-51
View File
@@ -1,51 +0,0 @@
# 薄膜缺陷数据集(YOLO 风格标注:labels/*.txt,每行 `class_id cx cy w h`,归一化坐标)。
# 类别顺序即标注里的 class_id,改动顺序等于改变标签含义,必须重新训练。
# 也可以写成 data.yaml 的路径,从其中的 names 读类别:classes: data/raw/film/data.yaml
classes: [scratch, bubble, particle, crease, stain]
# 图像级标签形式;模型的分类头、分类损失、分类指标都跟随它。
# multilabel(多类):一张图可同时含多种缺陷,多热标签 + BCE,全 0 表示 OK 片;
# multiclass(单类):一张图只归一个类别,互斥 softmax + CE,
# 分类头多一维表示"无缺陷"(下标 = len(classes)),
# 一图出现多种缺陷时取框数最多的类别。
# 无论取哪种,定位分支始终按 classes 逐类输出 heatmap。
label_mode: multilabel
image_size: [512, 512]
gray: false
data:
train:
dataset:
name: film_defect
img_dir: data/raw/film/images/train
label_dir: null # 缺省按 YOLO 约定取 data/raw/film/labels/train
gray: false
max_objects: 64
transforms:
- {name: Resize, size: [512, 512]}
- {name: RandomHorizontalFlip, p: 0.5}
- {name: RandomVerticalFlip, p: 0.5}
- {name: ColorJitter, brightness: 0.2, contrast: 0.2}
- {name: ToTensor}
- {name: Normalize, mean: [0.485, 0.456, 0.406], std: [0.229, 0.224, 0.225]}
loader:
batch_size: 16
shuffle: true
num_workers: 8
drop_last: true
val:
dataset:
name: film_defect
img_dir: data/raw/film/images/val
label_dir: null
gray: false
transforms:
- {name: Resize, size: [512, 512]}
- {name: ToTensor}
- {name: Normalize, mean: [0.485, 0.456, 0.406], std: [0.229, 0.224, 0.225]}
loader:
batch_size: 16
shuffle: false
num_workers: 4
-12
View File
@@ -1,12 +0,0 @@
_base_:
- ../train/baseline.yaml
# auto 按 cuda > mps > cpu 自动选;部署前做精度回归可以显式 device=cpu。
device: auto
checkpoint: runs/baseline/best.pth
eval:
split: val
score_threshold: 0.3
iou_threshold: 0.5
topk: 50
-13
View File
@@ -1,13 +0,0 @@
# resnet18 版本的评估配置。
# 必须和训练时用的模型配置一致,否则构建出来的骨架与权重对不上。
_base_:
- ../train/resnet18.yaml
device: auto
checkpoint: runs/resnet18/best.pth
eval:
split: val
score_threshold: 0.3
iou_threshold: 0.5
topk: 50
-18
View File
@@ -1,18 +0,0 @@
# torchvision resnet18:stride 32 + 3 次上采样 => 输出 stride 4。
model:
name: defect_net
backbone:
# 整块替换:不加这行的话,从 tiny_conv 继承来的 widths/depths/block 会残留,
# 传给 TorchvisionBackbone 直接报错。见 utils/config.py::deep_merge
_replace_: true
name: torchvision
arch: resnet18
pretrained: true
in_channels: 3
neck:
name: upsample
channels: 64
num_upsamples: 3
head:
hidden_channels: 64
with_classification: true
-18
View File
@@ -1,18 +0,0 @@
# 自研轻量骨架:backbone stride 16 + 2 次上采样 => 输出 stride 4。
model:
name: defect_net
backbone:
name: tiny_conv
in_channels: 3
widths: [32, 64, 128, 256]
depths: [1, 2, 2, 2]
block: dw # dw=深度可分离(更快) / res=残差(更强)
neck:
name: upsample
channels: 64
num_upsamples: 2
head:
hidden_channels: 64
with_classification: true
classification:
dropout: 0.1
-43
View File
@@ -1,43 +0,0 @@
_base_:
- ../model/tiny_conv.yaml
- ../dataset/film_defect.yaml
work_dir: runs/baseline
seed: 42
deterministic: false
device: auto # auto 按 cuda > mps > cpu 挑最快的可用后端;也可写 cuda / mps / cpu
train:
epochs: 100
amp: auto # auto: CUDA 上开、MPS 上关(实测 MPS autocast 比 fp32 慢);也可写 true / false
clip_grad: 5.0
log_interval: 20
monitor: f1 # 用于挑选 best.pth 的验证指标
restart_schedule: false # 续训时按剩余轮数重开学习率曲线(调度已到末尾、想调大 lr 时用)
optimizer:
name: adamw
lr: 0.001
weight_decay: 0.0001
scheduler:
name: cosine
loss:
heatmap_weight: 1.0
wh_weight: 0.1
offset_weight: 1.0
cls_weight: 1.0
eval:
score_threshold: 0.3
iou_threshold: 0.5
topk: 50
# 训练过程可视化(SwanLab)。未安装或 enabled=false 时自动跳过。
swanlab:
enabled: true
project: film-defect
name: null # 缺省用 work_dir 的目录名
mode: online # online(云端) | local(本地看板) | offline(仅存盘) | disabled
tags: [tiny_conv, center-head]
-12
View File
@@ -1,12 +0,0 @@
_base_:
- ./baseline.yaml
# 单类(互斥)分类示例:一张图只归一个类别,分类头多一维表示"无缺陷"。
label_mode: multiclass
work_dir: runs/multiclass
train:
monitor: cls_f1 # 单类模式下常用分类指标挑选 best.pth
swanlab:
name: multiclass
tags: [tiny_conv, multiclass]
-8
View File
@@ -1,8 +0,0 @@
_base_:
- ./baseline.yaml
- ../model/resnet18.yaml
work_dir: runs/resnet18
train:
optimizer:
lr: 0.0005