MMdetection3.0中DETR模型训练常见问题解析与优化策略
1. DETR模型训练中的验证集AP为0问题解析最近在MMdetection3.0框架下训练DETR模型时很多同学都遇到了验证集AP值始终为0.000的情况。这个问题看似简单但实际上涉及到多个可能的原因。我自己在NWPU-VHR-10数据集上就踩过这个坑当时训练了整整一天结果验证集指标纹丝不动那种感觉真是让人抓狂。首先我们需要明确DETRDetection Transformer作为基于Transformer的目标检测模型与传统CNN-based检测器有很大不同。它完全摒弃了anchor boxes和NMS这些传统组件而是采用端到端的集合预测方式。这种创新架构带来了性能上的突破但也让训练过程变得更加敏感。从实际经验来看验证集AP为0通常有以下几个主要原因预训练权重加载不正确数据集类别数不匹配学习率设置不当数据量严重不足以NWPU-VHR-10数据集为例这个遥感影像数据集只有650张图片训练验证比为611:39。在这种小数据场景下如果直接从头训练DETR模型几乎肯定会遇到AP为0的情况。这是因为Transformer架构对数据量非常敏感需要大量数据才能学到有效的特征表示。2. 预训练权重加载的关键技巧预训练权重的处理是DETR训练中最容易出问题的环节。很多同学虽然知道要加载预训练模型但还是会遇到各种报错和警告。最常见的就是下面这个size mismatch错误size mismatch for bbox_head.fc_cls.weight: copying a param with shape torch.Size([81, 256]) from checkpoint, the shape in current model is torch.Size([11, 256])这个错误的原因是COCO数据集有80个类别加背景共81而我们的自定义数据集可能只有10个类别加背景共11。直接加载COCO预训练权重就会导致最后的分类层维度不匹配。解决方法其实很简单我们需要修改预训练模型的最后分类层。具体操作如下import torch pretrained_weights torch.load(detr_r50_8xb2-150e_coco.pth) pretrained_weights[state_dict][bbox_head.fc_cls.weight].resize_(11, 256) pretrained_weights[state_dict][bbox_head.fc_cls.bias].resize_(11) torch.save(pretrained_weights, detr_custom.pth)这里的关键是使用PyTorch的resize_方法调整分类层的维度。注意要同时修改weight和bias两个参数。修改完成后模型就能正常加载了。3. 小数据集下的训练优化策略对于NWPU-VHR-10这样的小数据集单纯的预训练权重调整可能还不够。我们需要采取更多措施来提升训练效果3.1 数据增强的合理配置在MMdetection3.0中DETR的默认数据增强可能过于激进。建议调整如下train_pipeline [ dict(typeLoadImageFromFile), dict(typeLoadAnnotations, with_bboxTrue), dict(typeRandomFlip, flip_ratio0.5), dict( typeAutoAugment, policies[ [ dict( typeResize, img_scale[(480, 1333), (512, 1333), (544, 1333)], multiscale_modevalue, keep_ratioTrue) ], [ dict( typeResize, img_scale[(400, 1333), (500, 1333)], multiscale_modevalue, keep_ratioTrue), dict( typeRandomCrop, crop_typeabsolute_range, crop_size(384, 600), allow_negative_cropTrue) ] ]), dict(typeNormalize, **img_norm_cfg), dict(typePad, size_divisor1), dict(typeDefaultFormatBundle), dict(typeCollect, keys[img, gt_bboxes, gt_labels]) ]3.2 学习率与优化器调参DETR对学习率非常敏感。对于小数据集建议使用更小的初始学习率optimizer dict( typeAdamW, lr2e-5, # 通常用2e-4小数据集可以更小 weight_decay0.0001) optimizer_config dict(grad_clipdict(max_norm0.1, norm_type2))同时可以尝试使用学习率warmup策略lr_config dict( policystep, warmuplinear, warmup_iters500, warmup_ratio0.001, step[8, 11])4. 模型结构与训练技巧进阶4.1 注意力机制的调整DETR的核心是Transformer的自注意力机制。对于小数据集可以尝试减少注意力头的数量model dict( typeDETR, backbonedict(...), transformerdict( typeTransformer, encoderdict( typeDetrTransformerEncoder, num_layers6, num_heads4), # 默认是8可以减半 decoderdict(...)), ...)4.2 训练过程中的监控与调试建议在训练时添加更多的监控指标log_config dict( interval50, hooks[ dict(typeTextLoggerHook), dict(typeTensorboardLoggerHook), dict(typeMMDetWandbHook, init_kwargs{project: detr-debug}, interval10, log_checkpointTrue, log_checkpoint_metadataTrue) ])当遇到AP为0的情况时可以检查以下方面损失曲线是否在下降梯度是否正常更新预测框是否合理即使AP为0也可能有预测框输出5. 实际项目中的经验分享在最近的一个遥感检测项目中我们使用DETR遇到了典型的AP为0问题。经过反复调试总结出以下几点实用建议首先一定要确保数据标注的正确性。我们曾经遇到过因为标注文件格式错误导致模型完全学不到任何东西的情况。建议先用简单的Faster R-CNN等模型验证数据集的正确性。其次对于小数据集可以尝试冻结部分层的参数。例如# 冻结backbone的前几层 for name, param in model.backbone.named_parameters(): if layer1 in name or layer2 in name: param.requires_grad False最后不要忽视硬件的影响。我们发现使用更大的batch size即使只有2-4有时就能显著改善训练效果。如果显存不足可以尝试梯度累积optimizer_config dict( typeGradientCumulativeOptimizerHook, cumulative_iters4)DETR的训练确实比传统检测器更具挑战性但一旦调通其端到端的简洁性和稳定性会带来很大优势。关键是要有耐心从数据、预训练权重、超参数等多个角度系统性地排查问题。