☰
MMDetection 与 Faster R-CNN 实战:从依赖安装到模型训练完整指南
2026/10/19 10:32:01 网站建设 项目流程

做目标检测相关实验的人,十有八九会碰到 MMDetection 这个框架。它在 Faster R-CNN、Mask R-CNN 这一票经典模型的训练、测试和调参上确实很省事,但代价是安装链路长,版本匹配要求极高。尤其当你第一次想以 Faster R-CNN 为例跑通“安装—训练—测试”全流程时,环境缺一个依赖、版本错一个号,都能卡住你大半天。

我最近刚好在一台空机器上从头装了一遍 MMDetection,并用 Faster R-CNN 完成了一次完整训练和评估。这篇文章就是把整个过程的细节按顺序理一遍,重点写清楚那些容易踩、又不怎么见诸文档的坑。

1. 动手前要理解的两件事:框架组成和版本对应关系

1.1 框架组成:它不是只有一个包

很多人以为安装 MMDetection 就是pip install mmdet然后就能用,其实它的底层依赖关系完全不是这么简单。MMDetection 本质上是建立在三个核心包之上的:

  • PyTorch:负责基础的张量运算和自动求导,所有深度学习模型都跑在它上面。
  • MMCV:这是最关键也最容易出问题的部分。它是整个 OpenMMLab 系列共用的底层库,提供了大量编译好的 CUDA 算子,比如 RoIAlign、nms、deformable conv 等。Faster R-CNN 的很多核心算子就依赖这些编译好的 CUDA 扩展。
  • MMDetection:真正面向目标检测的算法库,包含大量模型、数据集适配层和训练测试工具。

理解这层关系之后,你就明白安装并不是单点任务,而是一条“Python → PyTorch → MMCV → MMDetection”的依赖链路。哪一环断掉,后面都会出问题。

1.2 CUDA、PyTorch 和 MMCV 的版本对应是核心矛盾

安装过程中最让人头疼的是版本匹配。举一个我实际遇到的例子:如果安装的 PyTorch 是通过 CUDA 11.3 编译的,而编译 MMCV 时指定的是 CUDA 11.7,虽然这几个版本很接近,但实际运行中调用 GPU 算子时可能出现加载失败,报一个nvcc mismatch或者undefined symbol之类的错误,排查起来非常痛苦。

所以在动手之前,我强烈建议你先确定三件事:

  1. 本机显卡驱动支持的最高 CUDA 版本;
  2. 打算安装的 PyTorch 版本对应的 CUDA 版本;
  3. MMDetection 当前版本对 MMCV 版本的要求。

个人经验是:先查 MMDetection 官方版本发布说明里标注的“兼容版本表”,再反推 PyTorch 和 CUDA 的选择,顺序不要搞反。

以我这次的配置为例,我选择了 Python 3.8 + PyTorch 1.13.1 + CUDA 11.7 的组合,对应的 MMCV 版本使用 2.0.0 系列,然后安装 MMDetection 2.25.0。这套组合比较成熟,社区验证量大,遇到问题容易查到解决方案。

2. 环境准备的完整步骤与验证方法

2.1 用虚拟环境隔离项目目录

我优先建议用 conda 创建独立虚拟环境,不要直接在系统环境里装深度学习依赖。原因很简单:不同项目对 PyTorch 的要求经常冲突,一个项目要 1.8,另一个要 2.0,系统环境会变得一团糟。

创建环境并激活:

conda create -n mmdet python=3.8 -y conda activate mmdet

这里特意选了 Python 3.8,而不是更新的版本,是考虑到一些老版本 MMCV 的编译脚本对 3.9、3.10 支持得没那么及时。如果要用比较新的 MMDetection 3.0 以上版本,Python 3.8 依然是个稳妥选择。

2.2 PyTorch 安装的细节选择

PyTorch 的安装有两种常见路径:一种是使用 conda,另一种是使用 pip。我个人的建议是:只要网速允许,优先用 pip 安装官方编译好的 wheel 包。conda 安装 PyTorch 经常会把它自身的依赖全部升级一遍,容易带崩 numpy 等基础库。

以 CUDA 11.7 为例,安装命令大概长这样:

pip install torch==1.13.1 torchvision==0.14.1 --index-url https://download.pytorch.org/whl/cu117

安装完成后,需要验证一下 PyTorch 是否真正能调用 GPU:

python -c "import torch; print(torch.__version__, torch.cuda.is_available(), torch.cuda.device_count())"

执行结果里,第二个值必须是True,第三个值至少是1。如果第二个值是False,大概率是 PyTorch 的 CUDA 版本和驱动不匹配。这个时候先检查驱动,再考虑重装。

2.3 提前装好编译工具链

MMCV 在安装时如果选择编译版本,会用到 C++ 编译器和一些系统级库。在它以预编译的 wheel 安装的情况下通常不会触发编译,但保险起见,我建议在 Ubuntu 系统上先装好:

sudo apt update sudo apt install build-essential

如果你用的是容器环境,这部分可能已经内置,但我遇到过极简镜像缺 gcc 导致编译到一半直接失败的情况。提前装好,能省去后面中途报错的麻烦。

3. 从源安装 MMCV 与 MMDetection 的实操记录

3.1 MMCV 的安装是关键节点

我在前面提到,MMCV 是整个依赖链里最敏感的环节。它有两种安装方式:预编译版本和源码编译版本。

对于绝大多数人,我推荐用预编译版本。命令大概是:

pip install mmcv==2.0.0 -f https://download.openmmlab.com/mmcv/dist/cu117/torch1.13/index.html

这行命令的意思是:让 pip 去指定的索引里找支持 CUDA 11.7 和 PyTorch 1.13 的预编译 wheel。只要找到,就直接下载安装,整个过程不需要本地编译。

但这种方式有个隐藏问题:不是所有 MMCV 版本都有对应的预编译包。如果你的 PyTorch 或 CUDA 版本比较新,或者 MMCV 版本比较特殊,预编译索引里并没有对应包,pip 会自动退回源码编译。源码编译需要几分钟到十几分钟不等,期间如果内存不够或者缺依赖,就会报错。

以下是节选自编译过程的典型报文,帮助大家识别当前是否真的在编译:

Building wheels for collected packages: mmcv Building editable object for mmcv ...

看到Building字样,就是在编译了。如果不想等,可以 Ctrl+C 中断,换一个更保守的 MMCV 版本。

3.2 MMDetection 的安装路径选择

MMDetection 同样有两种安装方式:pip install mmdet直接装,或者git clone源码后以pip install -e .的方式安装。

我的建议是,新手直接 pip 安装即可,简单省事。但如果你之后想改模型代码、想在训练过程中查看源码细节,那源码安装更对口:

git clone https://github.com/open-mmlab/mmdetection.git cd mmdetection pip install -e .

使用-e参数安装的意思是“可编辑模式”,代码克隆到本地目录,改动后会直接生效。好处是调试方便,坏处是你得随时注意源码更新,不然会有版本漂移问题。

安装结束后,可以用这个命令验证:

python -c "import mmdet; print(mmdet.__version__)"

如果这个命令成功,说明框架主体已经装好。但我还要提醒一点:这一步成功不代表所有 CUDA 算子都能正常使用,必须再测试一个最常调用的算子——RoIAlign。在 Python 里执行:

import torch from mmcv.ops import RoIAlign roi_align = RoIAlign(output_size=(7, 7), spatial_scale=0.0625) print(roi_align)

能正常输出算子对象,才算环境验证真正通过。如果这里报ModuleNotFoundError或者ImportError,说明 MMCV 的编译或安装有问题,需要回头查版本对应关系。

4. 数据准备:把数据集整理成 MMDetection 认识的样子

4.1 COCO 与 VOC 两种主流格式

Faster R-CNN 在 MMDetection 里的默认配置几乎都是基于 COCO 数据集写的,但这不代表你必须用它内置的数据集。如果你只是想快速验证安装是否成功,可以用官方自带的 mini 数据集;如果你想在自定义数据集上训练,就有必要搞清楚 COCO 和 VOC 两种格式的区别。

我实际测试使用的方式是,把数据整理成 COCO 格式。因为 COCO 是 Faster R-CNN 相关配置默认的格式,直接使用 COCO 相关类可以少写很多代码。COCO 的核心是一个 JSON 文件,里面要包括:

  • images:每张图片的 id 和文件路径;
  • annotations:每个目标的 bbox、category_id 和所属图片 id;
  • categories:类别名称和 id 的对应关系。

如果你的数据本来就是 VOC 格式,也没关系,MMDetection 提供了 VOC 转换工具,可以通过命令行完成:

python tools/dataset_converters/pascal_voc.py \ -d /path/to/VOCdevkit \ -o /path/to/output_coco_format \ --split train val test

这样转换出来的数据,就能直接被 COCO 相关的配置读取。

4.2 数据集目录结构的优先级

MMDetection 读取数据集的路径遵循一定的默认规则,并不是你把图片丢给配置就能自动识别。我使用的目录结构是:

data/ ├── coco/ │ ├── annotations/ │ │ └── instances_train2017.json │ └── images/ │ └── train2017/

默认配置里,data_root变量通常是data/coco/这种相对路径。如果你把数据放在其他位置,一定要记得把配置文件里的data_root改成自己的绝对路径。这一步最容易被忽略,但一旦路径错误,训练一开始就会报FileNotFoundError。

特别提醒:如果用软链接把数据链接到项目目录下,注意检查目标路径的权限。我曾经遇到过软链接指向只读分区,结果训练时无法写入缓存,报了一个非常奇怪的错误。

4.3 标注内容的前置校验

在正式训练之前,我非常建议先用一个小的脚本统计一下数据集的标签分布,确认没有空 box、越界 box。出错的样本不一定会第一时间报错,但训练到一半,某个样本的 bbox 值为负或者超出图像边界,就会导致 loss 变成 NaN,训练中断。这种问题排查起来比环境问题还费时间。

我自己常用的校验思路很简单:写脚本遍历每个 annot 的bbox字段,检查四个数值是否非负,且x + w和y + h是否超过对应图像的宽高。如果有异常,先清洗数据再训练。这一步投入的十分钟,远小于训练中断后浪费的时间。

5. 用 Faster R-CNN 实例跑通训练流程

5.1 配置文件的修改策略

MMDetection 里的模型配置基本都是通过纯 Python 文件来定义。以 Faster R-CNN 为例,常见的基础配置文件是faster_rcnn_r50_fpn_1x_coco.py。这个文件里定义了主干网络(ResNet-50)、特征金字塔(FPN)、RPN 部分、RoI 检测头以及训练和测试相关的参数。

我的做法是:不直接修改原始配置,而是新建一个配置文件,继承基础配置,然后只覆盖需要改的部分。例如:

_base_ = 'faster_rcnn_r50_fpn_1x_coco.py' data_root = '/my/data/path/' data = dict( train=dict(data_root=data_root, ann_file='annotations/instances_train.json'), val=dict(data_root=data_root, ann_file='annotations/instances_val.json') )

这样做的好处是,当框架升级或者你想横向比较不同 backbone 时,基础配置可以保持不动,只需要调整覆盖项,非常灵活。

训练最重要的超参数通常包括:

  • samples_per_gpu:单个 GPU 上的批次大小,一般为 2 或 4;
  • workers_per_gpu:数据加载进程数,建议在 4 到 8 之间;
  • total_epochs/max_epochs:训练轮数;
  • optimizer:优化器参数,默认 SGD 和初始学习率 0.02。

如果显存不够,优先降低samples_per_gpu,而不是降低图像分辨率。Faster R-CNN 的默认输入是 1333×800,强行改小会对检测精度产生明显影响。

5.2 训练命令与日志解读

配置完成后,启动训练的命令本身比较简洁:

python tools/train.py /path/to/config/xxx.py --work-dir /path/to/work

这里我特意加了--work-dir,把所有日志、checkpoint 都输出到单独目录,方便之后查看和清理。

训练开始后的第一个现象是数据加载阶段,日志会反复刷新并显示类似这样的内容:

Epoch [1][ 50/ 500] lr: 0.000800, eta: 2:30:00, time: 0.45, data_time: 0.23, memory: 3500, loss_rpn_cls: 0.2100, loss_rpn_reg: 0.3200, loss_cls: 0.1200, loss_reg: 0.5000, loss: 0.6500

看这段日志,我最常关注三个量:

  • loss_rpn_cls和loss_rpn_reg:RPN 网络是否在快速收敛,正常情况会随 epoch 逐步下降;
  • loss_cls和loss_reg:最终检测头的损失;
  • data_time:如果这个值长期大于time的三分之一,就要检查数据加载是否成为瓶颈。

第一个 epoch 完成后,日志中会出现类似Saving checkpoint at epoch N的信息,模型参数保存到 work 目录下的epoch_1.pth等文件。

5.3 训练进程中的资源监控

训练跑起来之后并不是万事大吉。我训练时习惯开两个终端:一个跑训练,另一个用nvidia-smi监控显存和功耗。重点看功耗是否稳定在合理范围内。如果功耗忽高忽低,说明可能频繁在做 CPU 和 GPU 之间的数据拷贝,这会严重拖慢训练。

还有一种情况是显存占用不断上涨,最后出现out of memory错误。这多半不是显存不够,而是 PyTorch 的缓存机制导致。解决办法是在配置里加上torch.cuda.empty_cache(),或者降低批次。如果经常出现这个报错,建议改用小批次多 step 的策略,而不是直接换更大的显存卡。

6. 测试评估与推理结果可视化

6.1 单张图片快速验证模型

训练完成之后,最直接的做法是先用单张图片验证模型能不能出结果。这里我推荐用 MMDetection 自带的推理工具脚本:

python demo/image_demo.py \ /path/to/test.jpg \ /path/to/config/xxx.py \ /path/to/checkpoint/epoch_12.pth \ --out-file /path/to/result.jpg

执行之后,如果输出图片上能看到检测框和置信度,说明整个链路已经跑通。对于初测的模型,有框出来就已经算成功,不要指望第一次就检测得很准。

6.2 跑通批量评估脚本

但单张图片推理只解决了“能跑”的问题。要想知道模型训练效果,需要跑完整评估。命令是:

python tools/test.py /path/to/config/xxx.py \ /path/to/checkpoint/epoch_12.pth \ --out /path/to/results.pkl \ --eval bbox

--eval bbox表示只看目标检测框的评估指标。配合--out,评估结果会保存成 pkl 文件,后续还可以继续折腾分析。

评估完成后,终端会输出一行类似这样的结果:

Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.352 Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.560

这就是 COCO 定义的 mAP。第一个数值0.352是最关键的,它综合了 IoU 从 0.5 到 0.95 的十个阈值,代表模型总体的检测精度。第二个数值 0.560 是 IoU=0.5 下的 AP,相对宽容很多。

6.3 指标背后要读懂的事

刚入门时,看到 mAP 在 0.3 到 0.4 之间,会觉得模型效果不错,但其实这个数值在 COCO 测试集上属于中游水平。对于用 Faster R-CNN 做的第一次训练,我更推荐去关注模型的收敛状态,而不是只看绝对数值。

一个非常值得检查的字段是评估结果里的AR(Average Recall):

Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.420

如果 AR 远高于 AP,说明模型有潜力,只是置信度阈值设置偏高,或者分类不够准确。如果 AR 本身很低,说明检测头没有学到足够的候选目标,这时应该回去检查数据质量或增加训练轮数,而不是盲目调置信度阈值。

7. 我实际踩过的一些坑和对应解决办法

7.1 提示找不到动态链接库

在我第二次复装MMDetection时,遇到过启动训练时报libtorch_cuda_cu.so找不到。起因是从源码编译版切到 wheel 安装版时,旧的库文件被覆盖,但链接缓存没有更新。解决方法是彻底删除环境,重建,并且完全不混用 prebuilt 和源码编译的 MMCV。

如果不方便重装环境,可以先尝试清理缓存:

pip uninstall mmcv mmdet rm -rf ~/.cache/pip pip install mmcv==2.0.0 -f <对应的索引>

7.2 数据加载比计算还慢

训练日志里如果data_time一直偏高,最常见的原因是数据格式太复杂。图片读取如果全走 JPEG,IO 很容易成为瓶颈。我的处理策略是:把数据转成内存映射格式或者使用更高效的图片方式,同时把workers_per_gpu调高一些。

但也要注意,workers_per_gpu调太高会带来明显的 CPU 内存开销,导致系统整体变慢。我一般从 4 开始,逐步升到 8,观察是data_time降得快还是内存涨得快。

7.3 模型收敛但精度没提升

这个现象主要出现在训练轮数太少或学习率策略不合适时。Faster R-CNN 默认配置下,1x 的训练计划是 12 epoch,如果你的数据量很少,可以尝试调低初始学习率,比如从 0.02 降到 0.01,并观察验证集 AP 是否在波动后继续上升。

有时模型看起来在收敛,但 AP 一直上不去,也有可能是预训练权重没有正确加载。训练日志里如果出现load checkpoint from ...之后紧跟着unexpected keys这种话,就要检查是否是 backbone 预训练权重没有用上。

检查方式很简单,在配置里打开:

model = dict( backbone=dict( init_cfg=dict(type='Pretrained', checkpoint='torchvision://resnet50') ) )

预训练加载成功后,train 日志里会明确写load Pretrained from torchvision。如果没有这行日志,那基本等于随机初始化训练,精度自然不会高。

8. 总结一下我的实操体会

在 MMDetection 上完整跑通 Faster R-CNN 的安装、训练和测试,整个链路说简单也简单,说复杂也确实费精力。最核心的体会是:耐心处理依赖关系。我在安装和测试过程中花掉的时间,三分之一在版本配套上,三分之一在数据路径和格式上,真正被模型本身难住的时间反而最少。

对新手来说,不必一上来就追求较新的版本,选择一个成熟度高的组合(比如我用的 Python 3.8 + PyTorch 1.13 + MMCV 2.0 + MMDetection 2.25),按本文顺序走一遍,一般几个小时内就能看见第一个 checkpoint 输出。中途遇到问题,优先回看环境验证环节,确认 PyTorch、MMCV、MMDetection 三者是否真的对齐,再做其他假设。

最后还建议训练脚本时顺手养成好习惯:每次运行都固定随机种子、保存完整命令行和配置备份。很多莫名其妙的差异,其实都跟环境出入或配置差异有关。这套流程跑熟之后,换数据集、换模型就只是改配置的事,中间那些安装排坑经验可以长期复用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询