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:
co-authored by
Claude Opus 5
parent
57446c2f10
commit
86c86b105c
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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]
|
||||
@@ -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]
|
||||
@@ -1,8 +0,0 @@
|
||||
_base_:
|
||||
- ./baseline.yaml
|
||||
- ../model/resnet18.yaml
|
||||
|
||||
work_dir: runs/resnet18
|
||||
train:
|
||||
optimizer:
|
||||
lr: 0.0005
|
||||
Reference in New Issue
Block a user