1. 环境准备:避开版本兼容的深坑
第一次用PyTorch跑Faster R-CNN时,我花了整整三天时间在环境配置上。最坑的是当时没注意PyTorch版本问题,用1.6版本跑0.4的老代码,报错信息看得我怀疑人生。后来才发现,不同版本的PyTorch对CUDA、CUDNN的依赖天差地别。
强烈建议使用以下组合:
- Ubuntu 18.04/20.04(别用Windows,编译时各种路径问题能让你崩溃)
- CUDA 10.1 + CUDNN 7.6.5(这是PyTorch 1.0的黄金搭档)
- Python 3.6/3.7(3.8以上会有scipy兼容性问题)
安装PyTorch时一定要指定版本:
bash复制conda install pytorch==1.0.0 torchvision==0.2.1 cuda100 -c pytorch
遇到过最奇葩的报错是"ImportError: torch.utils.ffi is deprecated",这是因为新版PyTorch移除了FFI模块。解决方法很简单——换用pytorch-1.0分支的代码:
bash复制git clone -b pytorch-1.0 --single-branch https://github.com/jwyang/faster-rcnn.pytorch.git
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据准备:自定义数据集的正确姿势
很多教程只教用VOC2007数据集,但实际项目中我们总要处理自己的数据。这里有个大坑:VOC格式要求图片名必须是6位数字(比如000001.jpg),但我们的原始图片可能是任意命名。用这个Python脚本批量重命名:
python复制import os
from PIL import Image
img_dir = 'your_images_folder'
for idx, img_name in enumerate(os.listdir(img_dir)):
new_name = f"{idx:06d}.jpg"
img = Image.open(os.path.join(img_dir, img_name))
img.save(os.path.join('JPEGImages', new_name))
Annotations文件夹的XML文件也要对应修改。建议用labelImg工具标注,它会自动生成符合VOC标准的XML。我遇到过标注框越界导致的"assert(boxes[:,2]>=boxes[:,0]).all()"错误,解决方法是在生成XML时检查坐标是否超出图片宽高:
python复制# 在标注工具的输出代码里加上边界检查
xmax = min(xmax, image_width-1)
ymax = min(ymax, image_height-1)
3. 训练技巧:从报错中杀出一条血路
第一次训练时GPU显存直接炸了,后来发现batch_size不能超过4(我的显卡是RTX 2080 Ti)。如果出现CUDA out of memory,试试这些参数组合:
bash复制CUDA_VISIBLE_DEVICES=0 python trainval_net.py \
--dataset pascal_voc \
--net res101 \
--bs 2 \ # 关键参数!显存不够就调小
--nw 4 \ # dataloader线程数
--lr 0.001 \
--cuda
致命陷阱:缓存文件冲突!当你更换数据集后,一定要删除data/cache下的voc_2007_trainval_gt_roidb.pkl,否则程序会傻傻地加载旧数据索引。我在这栽过跟头,训练时一直报KeyError:'width',就是因为缓存没清理。
4. 模型调优:参数里的魔鬼细节
官方代码的默认学习率可能不适合你的数据。我的经验是:
- 小数据集(<1000张):lr=0.0005
- 中等数据集(1000-5000张):lr=0.001
- 大数据集(>5000张):lr=0.005
在lib/model/config.py里有几个隐藏参数很关键:
python复制__C.TRAIN.RPN_POSITIVE_OVERLAP = 0.7 # 建议调低到0.5-0.6
__C.TRAIN.RPN_NEGATIVE_OVERLAP = 0.3 # 建议调高到0.4
修改检测类别时要注意两个地方必须同步改:
- lib/datasets/pascal_voc.py里的self._classes
- demo.py里的pascal_classes
有个骚操作可以提升小目标检测效果——修改anchor尺寸。在lib/model/config.py中找到:
python复制__C.ANCHOR_SCALES = [8,16,32] # 改为[4,8,16]检测小物体更灵敏
5. 实战技巧:那些官方没告诉你的黑科技
技巧1:用–vis参数实时查看训练效果
bash复制python trainval_net.py --vis --cuda
这会在data/vis文件夹生成检测效果图,方便随时监控训练质量。
技巧2:冻结底层网络加速训练
在trainval_net.py的109行附近添加:
python复制for param in net.Conv_base.parameters():
param.requires_grad = False # 冻结卷积层
技巧3:自动保存测试结果到Excel
在test_net.py的预测循环后添加:
python复制import pandas as pd
results = []
for box, score in zip(boxes, scores):
results.append({'x1':box[0],'y1':box[1],'x2':box[2],'y2':box[3],'score':score})
pd.DataFrame(results).to_excel('det_results.xlsx')
6. 避坑指南:我踩过的那些雷
坑1:验证集效果突然暴跌
可能原因:学习率太高导致模型震荡。解决方案:
- 添加梯度裁剪:在lib/model/train_val.py的backward步骤前加
python复制torch.nn.utils.clip_grad_norm_(model.parameters(), 10.0)
坑2:预测框全部挤在图片角落
典型症状:loss_rpn_loc一直很高。这是anchor设置不合理导致的,检查:
- 数据集的标注框长宽比分布
- config.py中的ANCHOR_RATIOS是否匹配
坑3:训练时GPU利用率波动大
通常是因为数据加载瓶颈。试试这些优化:
- 使用更快的存储(NVMe SSD)
- 增加–nw参数(不要超过CPU核心数)
- 在datasets/pascal_voc.py里启用缓存:
python复制self._roidb = self.gt_roidb() # 改为
self._roidb = cache.cache(self.gt_roidb)
7. 部署优化:让模型飞起来
训练好的模型可以用torch.jit.trace加速:
python复制model.eval()
example = torch.rand(1, 3, 600, 800).cuda()
traced_model = torch.jit.trace(model, example)
traced_model.save('fasterrcnn_jit.pt')
实测发现,用半精度推理能提升30%速度:
python复制with torch.cuda.amp.autocast():
detections = model(im_data, im_info)
如果是部署到生产环境,建议转ONNX格式:
python复制torch.onnx.export(model,
(im_data, im_info),
"fasterrcnn.onnx",
opset_version=11)
最后提醒:别用OpenCV的dnn模块加载PyTorch模型!我测试发现其NMS实现与原生代码有差异,会导致漏检。推荐用libtorch部署,保持前后处理一致性。
