feat: 新增缺陷分类训练与评估链路
在聚类 + 人工归类得到的数据集(data/<集>/<类别名>/*.png)上训练分类模型。 - datasets/classification.py:按目录组织的分类数据集,**逐类分层**切分 train/val (others 只有 65 张,整体随机切很容易让它在验证集里挂零),固定种子可复现 - models/classifier.py:卷积骨架 + 分类头,与 DefectNet 共用 backbone 注册表, 因此自监督产出的 simclr_backbone.pth 可用 init_from 直接初始化; frozen_backbone 可做线性探针 - engine/classification.py:训练循环 + 指标。主指标用 macro-F1 而非准确率—— 数据从 normal 2679 张到 others 65 张差 41 倍,全预测成 normal 也有 24% 准确率; 损失按类别频率加权,避免小类被淹没;输出逐类 P/R/F1 与混淆矩阵 - classify.py:训练/评估入口,--eval-only 可单独评估并导出 eval_report.json - configs/classify/film.yaml:预处理沿用聚类阶段的结论(拉伸 + 逐图标准化)。 抹掉亮度在这里尤其重要:有几类几乎只来自单一原始数据集,不抹掉的话模型可能 靠"认出这是哪个数据集"作弊 - 续训语义与检测/自监督一致:检查点只提供进度,超参以配置为准 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
33d28dcc7c
commit
33fdf396ee
@@ -0,0 +1,78 @@
|
||||
# 在人工归类好的数据集上训练缺陷分类模型。
|
||||
#
|
||||
# 数据来自 scripts/export_clusters.py:自监督聚类 + 人工整理后的 15 个类别。
|
||||
#
|
||||
# 用法:
|
||||
# uv run python classify.py --config configs/classify/film.yaml
|
||||
# uv run python classify.py --config configs/classify/film.yaml --eval-only \
|
||||
# --checkpoint runs/classify/best.pth
|
||||
|
||||
work_dir: runs/classify
|
||||
seed: 42
|
||||
device: auto
|
||||
|
||||
data:
|
||||
root: data/orgnized_from_r101_k40
|
||||
val_ratio: 0.2
|
||||
exclude: [] # 需要剔除某些类别时写在这里,如 [unknown, others]
|
||||
classes: null # null = 按目录名排序自动确定;训练与评估必须一致
|
||||
|
||||
# 预处理沿用聚类阶段的结论:
|
||||
# - 拉伸到 128x128 而不是 letterbox——尺寸与宽高比是 ROI 裁剪的产物,不是缺陷属性;
|
||||
# - 逐图标准化抹掉整体亮度/对比度。这里尤其重要:15 个类别里有几类几乎只来自
|
||||
# 单一原始数据集(ripple 几乎全是 pearlescent、grease 与 zigzag 全是 film),
|
||||
# 不抹掉亮度的话模型可能靠"认出这是哪个数据集"就把类别猜对,看着准确率很高,
|
||||
# 换个批次的数据就崩。
|
||||
image_size: [128, 128]
|
||||
train_transforms:
|
||||
- {name: Resize, size: [128, 128]}
|
||||
- {name: RandomHorizontalFlip, p: 0.5}
|
||||
- {name: RandomVerticalFlip, p: 0.5}
|
||||
- {name: ToTensor}
|
||||
- {name: PerImageStandardize}
|
||||
val_transforms:
|
||||
- {name: Resize, size: [128, 128]}
|
||||
- {name: ToTensor}
|
||||
- {name: PerImageStandardize}
|
||||
|
||||
loader:
|
||||
batch_size: 128
|
||||
num_workers: 8
|
||||
|
||||
model:
|
||||
name: classifier
|
||||
backbone:
|
||||
name: torchvision
|
||||
arch: resnet18
|
||||
pretrained: true
|
||||
in_channels: 3
|
||||
classification:
|
||||
dropout: 0.2
|
||||
# 用自监督预训练的骨架初始化——那正是前面聚类阶段的产物。
|
||||
# 例:runs/simclr_r101/simclr_backbone.pth(注意 backbone 配置要与自监督时一致)
|
||||
init_from: null
|
||||
frozen_backbone: false # true = 冻结骨架只训分类头(线性探针)
|
||||
|
||||
train:
|
||||
epochs: 30
|
||||
amp: auto
|
||||
clip_grad: 5.0
|
||||
log_interval: 20
|
||||
|
||||
# 主指标用 macro-F1 而不是准确率:数据从 normal 2679 张到 others 65 张差 41 倍,
|
||||
# 全预测成 normal 也有 24% 准确率,但 macro-F1 会很低。
|
||||
monitor: macro_f1
|
||||
|
||||
# 按类别频率加权,避免小类被淹没;不需要时设 none。
|
||||
class_weight: balanced
|
||||
label_smoothing: 0.05
|
||||
|
||||
optimizer: {name: adamw, lr: 0.0003, weight_decay: 0.0001}
|
||||
scheduler: {name: cosine}
|
||||
|
||||
swanlab:
|
||||
enabled: true
|
||||
project: film-classify
|
||||
name: null
|
||||
mode: local
|
||||
tags: [classify, resnet18]
|
||||
Reference in New Issue
Block a user