# 在人工归类好的数据集上训练缺陷分类模型。 # # 数据来自 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: 60 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]