Windows10下DETR目标检测实战:从COCO到自定义数据集的完整迁移指南
在计算机视觉领域,目标检测一直是一个核心任务。传统的基于CNN的目标检测方法如Faster R-CNN、YOLO等已经取得了显著成果,但Facebook AI提出的DETR(DEtection TRansformer)模型首次将Transformer架构成功应用于目标检测任务,实现了端到端的检测流程。本文将带你完整走过在Windows10系统下,将DETR模型从COCO数据集迁移到自定义数据集的全过程。
1. 环境准备与依赖安装
Windows系统下的深度学习环境配置往往比Linux系统更具挑战性。我们需要特别注意以下几个关键点:
基础环境要求:
- Windows10 64位系统(建议版本1903或更高)
- Python 3.7或3.8(DETR对Python3.9+支持可能存在问题)
- CUDA 10.2或11.1(需与PyTorch版本匹配)
- cuDNN 8.0.5或更高
提示:建议使用Anaconda创建独立的Python环境,避免依赖冲突。
安装核心依赖库:
conda create -n detr python=3.8 conda activate detr pip install torch==1.8.1+cu111 torchvision==0.9.1+cu111 -f https://download.pytorch.org/whl/torch_stable.htmlDETR特有的依赖项安装可能会遇到以下常见问题:
- pycocotools安装失败:这是Windows用户最常见的障碍
- VC++编译工具缺失:需要安装Visual Studio 2019的C++构建工具
- apex安装问题:混合精度训练支持库
针对pycocotools安装问题,推荐以下解决方案:
git clone https://github.com/philferriere/cocoapi.git cd cocoapi/PythonAPI python setup.py build_ext install2. 自定义数据集准备与标注
DETR默认使用COCO格式的数据集,我们需要将自己的数据转换为这种格式。整个过程可以分为三个主要步骤:
2.1 数据标注工具选择
推荐使用LabelImg进行标注,它支持Pascal VOC格式的输出:
pip install labelImg labelImg标注时需要注意:
- 确保每个对象的边界框紧密贴合目标
- 类别名称保持一致(区分大小写)
- 避免重叠框(DETR对重叠检测敏感)
2.2 VOC转COCO格式转换
以下是将VOC格式转换为COCO格式的关键代码片段:
import xml.etree.ElementTree as ET import json import os def convert_voc_to_coco(voc_annotations_dir, output_json_path): categories = [{"id": 1, "name": "your_class1"}, {"id": 2, "name": "your_class2"}] annotations = [] images = [] for ann_file in os.listdir(voc_annotations_dir): tree = ET.parse(os.path.join(voc_annotations_dir, ann_file)) root = tree.getroot() # 处理image信息 image_id = len(images) + 1 image_info = { "id": image_id, "file_name": root.find("filename").text, "width": int(root.find("size/width").text), "height": int(root.find("size/height").text) } images.append(image_info) # 处理annotation信息 for obj in root.findall("object"): bbox = obj.find("bndbox") xmin = float(bbox.find("xmin").text) ymin = float(bbox.find("ymin").text) xmax = float(bbox.find("xmax").text) ymax = float(bbox.find("ymax").text) width = xmax - xmin height = ymax - ymin ann = { "id": len(annotations) + 1, "image_id": image_id, "category_id": categories.index(next( c for c in categories if c["name"] == obj.find("name").text )) + 1, "bbox": [xmin, ymin, width, height], "area": width * height, "iscrowd": 0 } annotations.append(ann) coco_format = { "images": images, "annotations": annotations, "categories": categories } with open(output_json_path, "w") as f: json.dump(coco_format, f)2.3 数据集目录结构
最终的数据集目录应组织如下:
custom_dataset/ ├── annotations/ │ ├── instances_train2017.json │ └── instances_val2017.json └── images/ ├── train2017/ │ ├── 000001.jpg │ └── ... └── val2017/ ├── 000101.jpg └── ...3. 模型调整与权重适配
DETR预训练模型是基于COCO的91类设计的,迁移到自定义数据集需要进行以下关键修改:
3.1 类别数量调整
修改预训练权重以适应新的类别数量:
import torch def adapt_class_embedding(pretrained_path, num_classes, output_path): state_dict = torch.load(pretrained_path) # 调整分类头权重 orig_weight = state_dict["model"]["class_embed.weight"] orig_bias = state_dict["model"]["class_embed.bias"] new_weight = torch.zeros((num_classes + 1, orig_weight.shape[1])) new_bias = torch.zeros(num_classes + 1) # 保留背景类权重 new_weight[0] = orig_weight[0] new_bias[0] = orig_bias[0] # 随机初始化新类别权重 new_weight[1:] = torch.nn.init.xavier_uniform_(torch.empty((num_classes, orig_weight.shape[1]))) state_dict["model"]["class_embed.weight"] = new_weight state_dict["model"]["class_embed.bias"] = new_bias torch.save(state_dict, output_path)3.2 模型配置文件修改
需要修改detr.py中的两个关键参数:
- 将
num_classes改为你的实际类别数 - 调整
hidden_dim(默认为256)以适应不同大小的模型
对于小型数据集,建议减小Transformer的层数:
# 修改models/detr.py def build_model(args): transformer = Transformer( d_model=args.hidden_dim, dropout=args.dropout, nhead=args.nheads, num_encoder_layers=4, # 原为6 num_decoder_layers=4, # 原为6 dim_feedforward=args.dim_feedforward, normalize_before=args.pre_norm, return_intermediate_dec=True, )4. 训练策略与参数调优
4.1 基础训练命令
python main.py \ --dataset_file "coco" \ --coco_path "path/to/your/custom_dataset" \ --epochs 150 \ --lr 1e-4 \ --batch_size 4 \ --num_workers 4 \ --output_dir "outputs" \ --resume "detr-r50_adapted.pth"4.2 Windows特有优化
针对Windows系统的特殊优化:
- 解决OMP错误:
import os os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'- 提高数据加载效率:
- 将数据集放在SSD上
- 使用更小的
num_workers(通常2-4为宜) - 启用
pin_memory
# 修改datasets.py train_loader = torch.utils.data.DataLoader( dataset_train, batch_size=args.batch_size, shuffle=True, num_workers=min(4, os.cpu_count()), pin_memory=True, collate_fn=utils.collate_fn )4.3 学习率调度策略
DETR原始论文使用以下学习率策略:
| 阶段 | 学习率 | 轮次 |
|---|---|---|
| 预热 | 1e-5 | 1-50 |
| 主训练 | 1e-4 | 51-150 |
| 衰减 | 1e-5 | 151-200 |
对于小型数据集,建议调整:
# 修改engine.py def adjust_learning_rate(optimizer, epoch, args): lr = args.lr if epoch < 30: # 延长预热 lr = args.lr * (epoch + 1) / 30 elif epoch > 100: # 提前衰减 lr = args.lr * 0.1 for param_group in optimizer.param_groups: param_group['lr'] = lr5. 模型评估与可视化
5.1 评估指标解读
DETR输出几个关键指标:
- AP: 平均精度(IoU=0.50:0.95)
- AP50: IoU=0.5时的AP
- AP75: IoU=0.75时的AP
- APS: 小目标AP
- APM: 中目标AP
- APL: 大目标AP
5.2 结果可视化
使用DETR自带的可视化工具:
import matplotlib.pyplot as plt from util.plot_utils import plot_results def visualize_prediction(image_path, model, transform): img = Image.open(image_path) img_tensor = transform(img).unsqueeze(0) with torch.no_grad(): outputs = model(img_tensor) plot_results(img, outputs[0], threshold=0.7) plt.show()5.3 常见问题排查
训练损失不下降:
- 检查学习率是否合适
- 验证数据标注是否正确
- 尝试减小batch size
验证指标波动大:
- 增加验证集大小
- 使用更长的预热期
- 尝试标签平滑
内存不足:
- 减小输入图像尺寸
- 使用梯度累积
python main.py --batch_size 2 --gradient_accumulation_steps 2
在实际项目中,我发现DETR对小目标检测性能相对较弱,可以通过以下方式改善:
- 增加小目标样本数量
- 使用更高分辨率的输入
- 在Backbone后添加FPN结构