☰
MMdetection环境配置实战:CUDA、PyTorch与MMCV版本对齐指南
2026/10/19 17:12:14 网站建设 项目流程

1. 项目概述:这不是装个包那么简单,而是一场与CUDA、PyTorch和OpenMMLab生态的深度对话

“配置MMdetection环境并训练”——这短短十个字,在计算机视觉工程师的日常里,几乎等同于一次小型系统性压力测试。它表面看是执行几行conda命令、pip install几个库,但背后牵扯的是CUDA版本与NVIDIA驱动的严格对齐、PyTorch编译时的ABI兼容性、Cython扩展的本地构建、以及OpenMMLab整个工具链(MMCV、MMDet、MMEngine)之间精密咬合的版本矩阵。我带过不少刚从学校出来的同学做目标检测项目,他们常以为下载好代码、跑通demo就算入门了,结果在python tools/train.py configs/faster_rcnn/faster-rcnn_r50_fpn_1x_coco.py这行命令前卡住三天,报错信息五花八门:undefined symbol: __cudaRegisterFatBinaryEnd、OSError: libcudnn.so.8: cannot open shared object file、ModuleNotFoundError: No module named 'mmcv._ext'……这些都不是语法错误,而是底层运行时环境的“信任危机”。

这个项目真正解决的,不是“能不能跑起来”,而是“能不能稳定、可复现、可调试、可扩展地跑起来”。它面向三类人:一是刚接触工业级检测框架的在校学生,需要避开官方文档里没明说的“暗坑”;二是算法工程师,要在新服务器或Docker环境中快速拉起一套可验证baseline的训练流水线;三是MLOps实践者,需将MMdetection集成进CI/CD流程,要求环境完全可声明、可重建。它不教你怎么调参、怎么改网络结构,但它决定了你后续所有模型迭代的起点是否坚实。核心关键词——MMdetection、CUDA、PyTorch、MMCV、目标检测训练——每一个都代表一个技术栈层级,而本项目的成败,恰恰取决于你能否让这四层栈在物理硬件上严丝合缝地叠在一起。

我做过不下二十次MMdetection环境部署,从Ubuntu 16.04 + CUDA 9.0的老古董集群,到A100 + CUDA 12.1的最新推理平台,踩过的坑足够写一本《CUDA兼容性避坑手记》。最典型的教训是:某次为赶项目进度,直接用pip install mmdet安装了最新版,结果发现其依赖的MMCV是预编译的CPU版本,导致GPU训练根本无法启动,白白浪费了六小时排查时间。后来我才明白,MMdetection从来就不是一个“开箱即用”的单体应用,而是一个需要你亲手校准的精密仪器。接下来的内容,就是我把这二十多次实操中沉淀下来的校准逻辑、参数选择依据、错误溯源方法,全部拆解给你看。没有玄学,只有可验证的步骤、可计算的版本号、可复现的命令。

2. 环境设计与方案选型:为什么必须放弃“一键安装”,转而拥抱“分层构建”

2.1 核心矛盾:官方文档的“理想路径” vs 实际硬件的“碎片现实”

MMdetection官方文档推荐的安装方式非常简洁:pip install openmim,然后mim install mmcv-full,最后mim install mmdet。这条路径在官方CI环境(Docker镜像、固定驱动版本、标准CUDA Toolkit)下确实畅通无阻。但真实世界远比CI复杂:你的服务器可能预装了NVIDIA 470驱动,而CUDA 11.3要求最低驱动版本是465;你的conda环境里可能已存在一个PyTorch 1.10(CPU-only),而MMCV 1.7.0要求PyTorch 1.12+;你的公司安全策略又禁止访问PyPI,只能走内网镜像源……此时,官方的一键命令就成了“断头路”。

因此,我彻底放弃了“mim install”作为首选方案,转而采用分层构建法:先独立、可控地构建PyTorch层,再构建MMCV层,最后才是MMdetection层。每一层都明确其对外依赖(输入)和对内提供(输出),形成清晰的因果链。这种做法牺牲了一点初始速度,却换来100%的可追溯性和可调试性。就像造汽车,你不会直接买一辆整车然后祈祷它不出问题,而是先确认发动机(PyTorch)、再确认变速箱(MMCV)、最后才组装车身(MMdetection)。

2.2 PyTorch层:选择哪个版本?不是越新越好,而是要与CUDA“门当户对”

PyTorch是整个链条的地基,它的版本选择直接锁死了后续所有可能性。关键决策点有三个:

第一,CUDA版本匹配。这是最硬性的约束。PyTorch官网的安装命令生成器(https://pytorch.org/get-started/locally/)会根据你选择的CUDA版本给出精确的pip命令。例如,如果你的nvidia-smi显示驱动版本为515.65.01,那么它最高支持CUDA 11.7(根据NVIDIA官方CUDA兼容性表)。此时,你就必须选择PyTorch for CUDA 11.7,而不是11.8或12.1。我见过太多人因为贪图“最新版PyTorch 2.0 + CUDA 12.1”,强行升级驱动,结果导致宿主机上的其他GPU应用(如TensorRT服务)全部崩溃,得不偿失。

第二,CPU/GPU版本抉择。pip install torch默认安装的是CPU版本,这是最大的陷阱。你必须显式指定--index-url https://download.pytorch.org/whl/cu117(以CUDA 11.7为例)来获取GPU版本。这个URL里的cu117就是关键标识符,它告诉pip:“我要的是为CUDA 11.7编译的wheel包”。漏掉这个,后面MMCV的GPU算子就永远无法加载。

第三,是否使用Conda而非Pip?我的结论是:在生产环境,优先用Conda;在研究环境,可用Pip。原因在于Conda能同时管理Python包和系统级库(如libglib、libpng),而Pip只管Python包。MMCV的编译过程会链接大量系统库,Conda的environment.yml可以将这些依赖一并声明,实现真正的环境隔离。比如,一个典型的environment.yml开头会这样写:

name: mmdet-env channels: - pytorch - nvidia - conda-forge dependencies: - python=3.9 - pytorch=1.12.1=py3.9_cuda11.3_cudnn8.3.2_0 - torchvision=0.13.1=py39_cu113

这里py3.9_cuda11.3_cudnn8.3.2_0这个build string,就是Conda为你精确锁定的PyTorch二进制版本,它包含了CUDA和cuDNN的完整信息,比pip的torch==1.12.1+cu113更可靠。

2.3 MMCV层:为什么必须源码编译?预编译包的三大致命缺陷

MMCV是MMdetection的基石,它提供了所有底层算子(如RoIAlign、NMS)和图像处理函数。官方提供了mmcv-full(含CUDA算子)和mmcv(纯CPU)两个pip包。但我的经验是:在任何需要GPU加速的场景下,都必须源码编译mmcv-full。原因有三:

缺陷一:预编译包的CUDA ABI不兼容。PyTorch 1.12.1的CUDA ABI(Application Binary Interface)与CUDA 11.3的特定补丁版本强绑定。而PyPI上的mmcv-fullwheel包,是在PyTorch CI服务器上用某个特定的CUDA patch(如11.3.109)编译的。如果你的本地CUDA是11.3.058,那么libcudnn.so.8的符号表可能略有差异,导致import mmcv时出现undefined symbol错误。源码编译则能确保所有符号都在你的本地环境中重新解析一遍。

缺陷二:预编译包的cuDNN版本错配。cuDNN是NVIDIA的深度学习加速库,不同版本间API有细微变化。MMCV 1.7.0的源码中,ops/csrc/roi_align/roi_align_cuda.cpp里有一行#include <cudnn.h>,它会链接你系统中/usr/local/cuda/include/cudnn.h。如果预编译包是用cuDNN 8.2编译的,而你系统里是8.6,头文件里的宏定义可能不同,编译期就报错。源码编译时,CMake会自动探测你系统中的cuDNN版本,并生成适配的代码。

缺陷三:无法启用高级特性。比如,MMCV支持通过环境变量MMCV_WITH_OPS=1启用额外的优化算子(如Deformable Convolution v2)。这个开关在预编译包里是固定的,而在源码编译时,你可以自由控制。

因此,我的标准流程是:克隆MMCV官方仓库,checkout到与MMdetection匹配的tag(如MMdetection 3.0.0对应MMCV 1.7.0),然后执行:

# 确保已激活conda环境 conda activate mmdet-env # 安装编译依赖 pip install numpy cython setuptools # 设置编译选项 export MMCV_WITH_OPS=1 export TORCH_CUDA_ARCH_LIST="6.0 6.1 7.0 7.5 8.0 8.6" # 开始编译安装 pip install -e . --no-cache-dir

其中TORCH_CUDA_ARCH_LIST指定了要为哪些GPU架构生成机器码。6.0对应Pascal(如GTX 1080),7.5对应Turing(如RTX 2080),8.0/8.6对应Ampere(如A100/RTX 3090)。不设置此变量,编译器只会为当前主机的GPU生成代码,换一台机器就无法运行。

2.4 MMdetection层:如何避免“版本幻觉”?用git commit hash代替语义化版本号

MMdetection的版本发布节奏很快,v2.x和v3.x的API差异巨大。官方文档有时会滞后,导致你按文档操作,却得到一个Config对象没有data.train属性的报错。我的解决方案是:永远不要用pip install mmdet,而是用git clone并checkout到一个确定的commit。例如,我当前主力使用的稳定分支是main,但我会记录下具体commit hash:

git clone https://github.com/open-mmlab/mmdetection.git cd mmdetection git checkout 5a1b1f8c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7 # 这是v3.0.0 release的hash pip install -v -e . --no-cache-dir

-v参数会输出详细的安装日志,其中会包含running build_ext和building 'mmcv._ext' extension等关键信息,这是验证MMCV算子是否成功编译的黄金证据。如果日志里没有_ext,说明MMCV层出了问题,必须回退检查。

这种做法看似繁琐,但它消除了所有“版本幻觉”。当你在团队中分享一个训练脚本时,只需附上这行git命令,队友就能100%复现出和你一模一样的环境。这比任何requirements.txt都可靠,因为requirements.txt里的mmdet==3.0.0可能指向PyPI上一个被意外覆盖的损坏包。

3. 核心细节解析与实操要点:从零开始的逐层验证清单

3.1 硬件与驱动层:nvidia-smi和nvcc -V的差异,你真的懂吗?

在敲下任何安装命令前,必须完成硬件层的“三问”:

第一问:nvidia-smi显示的驱动版本,是否支持你计划安装的CUDA Toolkit?
nvidia-smi输出的第一行是驱动版本(如Driver Version: 515.65.01),第二行是CUDA版本(如CUDA Version: 11.7)。注意!这个CUDA Version只是驱动支持的最高CUDA版本,并非你已安装的CUDA Toolkit版本。它只是一个上限,不是你实际拥有的东西。你需要去NVIDIA官网查《CUDA Compatibility Table》,确认515.65.01驱动确实支持CUDA 11.7。

第二问:nvcc -V是否返回有效值?
nvcc是CUDA编译器,它属于CUDA Toolkit。如果nvcc -V报command not found,说明你根本没安装CUDA Toolkit,只装了驱动。此时,你必须去NVIDIA官网下载对应版本的CUDA Toolkit runfile或deb包进行安装。切记:驱动(Driver)和工具包(Toolkit)是两个独立安装包,缺一不可。

第三问:/usr/local/cuda软链接是否指向正确版本?
Linux系统中,/usr/local/cuda通常是一个指向/usr/local/cuda-11.7的软链接。但如果你之前装过CUDA 11.3,这个链接可能还指向旧版本。必须手动检查并修正:

ls -la /usr/local/cuda # 如果指向错误,用以下命令修正(假设你要用11.7) sudo rm -f /usr/local/cuda sudo ln -s /usr/local/cuda-11.7 /usr/local/cuda

否则,后续编译MMCV时,CMake会错误地找到旧版本的cuda.h头文件,导致编译失败。

提示:一个完整的硬件检查脚本,我放在了项目根目录下的check_hardware.sh里,内容如下:

#!/bin/bash echo "=== NVIDIA Driver ===" nvidia-smi -q | grep "Driver Version\|CUDA Version" echo "=== CUDA Toolkit ===" nvcc -V echo "=== CUDA Symlink ===" ls -la /usr/local/cuda echo "=== GPU Architecture ===" nvidia-smi --query-gpu=name,compute_cap --format=csv

运行它,所有关键信息一目了然。

3.2 Python环境层:Conda虚拟环境的“最小完备集”配置

我创建MMdetection环境时,从不追求“大而全”,而是坚持“最小完备集”原则:只安装绝对必需的包,其余一切靠pip install -e .在项目内部解决。一个典型的environment.yml如下:

name: mmdet-env channels: - pytorch - nvidia - conda-forge - defaults dependencies: - python=3.9 - pip - pytorch=1.12.1=py3.9_cuda11.3_cudnn8.3.2_0 - torchvision=0.13.1=py39_cu113 - torchaudio=0.12.1=py39 - numpy=1.21.6 - scipy=1.7.3 - scikit-learn=1.0.2 - matplotlib=3.5.2 - opencv=4.6.0 - pip: - cython - pytest - yapf - isort

这里的关键点在于:

  • pytorch=1.12.1=py3.9_cuda11.3_cudnn8.3.2_0:这个build string是灵魂。它精确锁定了PyTorch的二进制版本,确保了ABI兼容性。
  • opencv=4.6.0:OpenCV是图像预处理的核心,但高版本(如4.8)有时会与MMCV的某些图像操作函数冲突,4.6.0是经过大规模验证的稳定版本。
  • pip段落:Conda不擅长安装Cython扩展,所以把cython等编译依赖放在pip段。-e模式(editable install)允许你在修改源码后无需重新安装即可生效,这对调试MMdetection源码至关重要。

创建环境后,务必执行conda activate mmdet-env,然后验证Python和PyTorch:

import torch print(torch.__version__) # 应输出 1.12.1+cu113 print(torch.cuda.is_available()) # 应输出 True print(torch.cuda.device_count()) # 应输出你的GPU数量

如果is_available()返回False,99%的原因是:PyTorch安装错了(装了CPU版),或者CUDA路径没设对(LD_LIBRARY_PATH未包含/usr/local/cuda/lib64)。

3.3 MMCV编译层:setup.py里的隐藏开关与编译日志解读

MMCV的setup.py是一个高度可配置的构建脚本。除了前面提到的MMCV_WITH_OPS和TORCH_CUDA_ARCH_LIST,还有两个关键环境变量:

MMCV_JIT=1:启用JIT(Just-In-Time)编译。它会将部分Python写的算子(如nms)在运行时动态编译为CUDA代码,提升小batch size下的性能。但在调试阶段,建议关闭(MMCV_JIT=0),因为JIT错误堆栈难以阅读。

MAX_JOBS=8:设置编译并发数。默认是os.cpu_count(),但在多核服务器上,设太高会导致内存爆满(每个job占用1-2GB内存)。我通常设为物理CPU核心数的一半。

编译时,最关键的日志是running build_ext之后的输出。一个成功的编译日志片段如下:

building 'mmcv._ext' extension gcc -pthread -B /home/user/miniconda3/envs/mmdet-env/compiler_compat -Wno-unused-result -Wsign-compare ... creating build/temp.linux-x86_64-cpython-39/mmcv/ops/csrc gcc -pthread -B /home/user/miniconda3/envs/mmdet-env/compiler_compat -Wno-unused-result -Wsign-compare ... ... copying build/lib.linux-x86_64-cpython-39/mmcv/_ext.cpython-39-x86_64-linux-gnu.so -> mmcv

注意最后一行:_ext.cpython-39-x86_64-linux-gnu.so。这个.so文件就是MMCV的GPU核心,它必须存在,且名字里要包含cuda或gpu字样(不同版本命名略有差异)。如果日志里只有_ext_cpu.so,说明编译过程跳过了CUDA部分,必须检查torch.cuda.is_available()是否为True,以及nvcc是否在PATH中。

注意:如果编译失败,最常见的原因是gcc版本过高。Ubuntu 22.04默认的gcc-11与PyTorch 1.12的C++ ABI不兼容。此时,你需要临时降级:

sudo apt install gcc-9 g++-9 export CC=gcc-9 export CXX=g++-9 pip install -e . --no-cache-dir

3.4 MMdetection验证层:从demo/image_demo.py到tools/train.py的渐进式测试

环境搭建完成后,绝不能直接跳到训练,必须进行四级渐进式验证:

Level 1:基础导入测试

import torch import mmcv from mmdet.apis import init_detector, inference_detector print("All imports successful!")

如果这里报错,问题一定出在PyTorch或MMCV层。

Level 2:Demo推理测试

python demo/image_demo.py demo/demo.jpg configs/faster_rcnn/faster-rcnn_r50_fpn_1x_coco.py checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth --out-file result.jpg

这个命令会加载一个预训练模型,对一张图片做推理,并保存结果。成功意味着:模型加载、数据预处理、前向传播、后处理(NMS)全部通畅。如果报KeyError: 'bbox',说明配置文件路径或checkpoint路径错了;如果报CUDA out of memory,说明GPU显存不足,需减小--cfg-options data.samples_per_gpu=1。

Level 3:数据集准备测试MMdetection要求COCO格式的数据集。我通常用tools/dataset_converters/coco.py将自定义数据集转换。但更重要的是验证数据加载器:

python tools/misc/browse_dataset.py configs/faster_rcnn/faster-rcnn_r50_fpn_1x_coco.py --output-dir tmp --show --max-num 5

这个命令会随机抽取5张图,用OpenCV显示出来,并打印其标注框。这是验证data.train.ann_file和data.train.img_prefix路径是否正确的最直接方法。如果显示黑屏或报FileNotFoundError,说明路径配置有误。

Level 4:端到端训练测试这才是终极考验。我从不一上来就训完整个COCO,而是先用--cfg-options data.samples_per_gpu=1 data.workers_per_gpu=0启动一个极简训练:

python tools/train.py configs/faster_rcnn/faster-rcnn_r50_fpn_1x_coco.py \ --work-dir tmp_train \ --cfg-options data.samples_per_gpu=1 data.workers_per_gpu=0

如果这个命令能成功跑完第一个epoch,并在tmp_train/20231001_120000.log.json里看到loss下降,那么恭喜,你的环境已经100%就绪。后续的所有问题,都是数据、配置或算法层面的,与环境无关。

4. 实操过程与核心环节实现:一个完整COCO格式数据集的训练全流程

4.1 数据准备:从原始图片到MMdetection标准目录结构

假设你有一批自己的图片,存放在/data/my_dataset/images/,对应的标注是JSON格式,存放在/data/my_dataset/annotations/instances_train.json和instances_val.json。MMdetection要求的目录结构是:

my_dataset/ ├── images/ │ ├── 000001.jpg │ ├── 000002.jpg │ └── ... ├── annotations/ │ ├── instances_train.json │ └── instances_val.json

其中,instances_train.json必须符合COCO格式,核心字段包括:

  • images: 图片元信息列表,每个元素有id,file_name,width,height
  • annotations: 标注框列表,每个元素有image_id,category_id,bbox([x,y,width,height]),segmentation(分割掩码,可选)
  • categories: 类别定义列表,每个元素有id,name

我写了一个gen_coco_json.py脚本来自动化生成这个JSON。其核心逻辑是:

import json import os from pathlib import Path def gen_coco_json(img_dir, ann_list, output_path): coco = { "images": [], "annotations": [], "categories": [ {"id": 1, "name": "person"}, {"id": 2, "name": "car"}, # ... 其他类别 ] } img_id = 1 ann_id = 1 for img_path in Path(img_dir).glob("*.jpg"): # 添加图片信息 img_info = { "id": img_id, "file_name": img_path.name, "width": 1920, # 需要读取真实尺寸 "height": 1080, } coco["images"].append(img_info) # 添加标注(此处简化,实际需从你的标注文件读取) for bbox in get_bboxes_from_your_ann_file(img_path.stem): ann_info = { "id": ann_id, "image_id": img_id, "category_id": bbox["class_id"], "bbox": [bbox["x"], bbox["y"], bbox["w"], bbox["h"]], "area": bbox["w"] * bbox["h"], "iscrowd": 0 } coco["annotations"].append(ann_info) ann_id += 1 img_id += 1 with open(output_path, "w") as f: json.dump(coco, f) # 调用 gen_coco_json("/data/my_dataset/images", [...], "/data/my_dataset/annotations/instances_train.json")

这个脚本的关键是get_bboxes_from_your_ann_file(),你需要根据自己的原始标注格式(可能是XML、CSV或YOLO格式)来实现它。网上有大量开源转换脚本,如labelme2coco、yolo2coco,但它们往往有bug,我建议自己写一个简单的,逻辑清晰,便于调试。

4.2 配置文件定制:configs/_base_/的继承机制与关键参数详解

MMdetection的配置系统基于Python,采用多重继承。一个典型的自定义配置configs/my_project/faster_rcnn_r50_fpn_mydataset.py如下:

# 继承基础配置 _base_ = [ '../_base_/models/faster_rcnn_r50_fpn.py', # 模型定义 '../_base_/datasets/coco_detection.py', # 数据集定义 '../_base_/schedules/schedule_1x.py', # 学习率调度 '../_base_/default_runtime.py' # 运行时设置 ] # 自定义数据集路径 data = dict( samples_per_gpu=2, # 每张GPU的batch size workers_per_gpu=2, # 每张GPU的数据加载进程数 train=dict( type='CocoDataset', ann_file='/data/my_dataset/annotations/instances_train.json', img_prefix='/data/my_dataset/images/', pipeline=[...] ), val=dict( type='CocoDataset', ann_file='/data/my_dataset/annotations/instances_val.json', img_prefix='/data/my_dataset/images/', pipeline=[...] ), test=dict( type='CocoDataset', ann_file='/data/my_dataset/annotations/instances_val.json', img_prefix='/data/my_dataset/images/', pipeline=[...] ) ) # 修改类别数(COCO是80类,你的数据集可能是5类) model = dict( roi_head=dict( bbox_head=dict( num_classes=5 # 必须修改!否则会报维度不匹配 ) ) ) # 预训练权重路径(可选,但强烈推荐) load_from = 'checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth'

这里有几个极易出错的点:

  • num_classes必须修改:这是新手最常犯的错误。如果不改,模型最后一层FC的输出是80维,而你的数据集只有5类,训练时会报RuntimeError: Expected input batch_size (2) to match target batch_size (2),但错误信息极其晦涩,让人摸不着头脑。记住:num_classes= 你的数据集中categories的数量,不包括背景类(background class是自动添加的)。

  • samples_per_gpu与显存的关系:这个值不是越大越好。Faster R-CNN在1080Ti上,samples_per_gpu=2是安全的;在A100上,可以设到4或8。但设太大,会导致OOM。一个经验公式是:显存占用(GB) ≈ 2.5 * samples_per_gpu + 1.5。所以,如果你的GPU只有11GB,samples_per_gpu最大只能是3。

  • workers_per_gpu的设置:它控制数据加载的并行度。设太高(如8),会导致CPU负载飙升,IO瓶颈;设太低(如0),GPU会因等待数据而空转。我的经验是:workers_per_gpu = min(4, CPU核心数 // GPU数量)。

4.3 训练启动与监控:tools/train.py的隐藏参数与TensorBoard集成

启动训练的命令,远不止python tools/train.py config.py这么简单。以下是我在生产环境中必加的参数:

python tools/train.py configs/my_project/faster_rcnn_r50_fpn_mydataset.py \ --work-dir work_dirs/my_project \ --resume-from work_dirs/my_project/latest.pth \ # 从断点继续 --gpus 2 \ # 使用2张GPU --seed 0 \ # 固定随机种子,保证可复现 --deterministic \ # 启用确定性算法(会略慢) --cfg-options \ data.samples_per_gpu=2 \ data.workers_per_gpu=4 \ model.roi_head.bbox_head.num_classes=5 \ optimizer.lr=0.02 \ runner.max_epochs=50
  • --resume-from:当训练因断电或OOM中断时,它能从latest.pth恢复,而不是从头开始。这个文件是MMdetection自动保存的,但前提是你的work-dir路径正确且有写入权限。

  • --deterministic:开启后,PyTorch会禁用一些非确定性操作(如cuDNN的auto-tuner),确保每次训练结果完全一致。这对于A/B测试至关重要。

  • --cfg-options:这是一个万能覆盖参数,可以在不修改配置文件的情况下,动态调整任意参数。比如,你想快速测试不同学习率,只需改optimizer.lr=0.01,无需新建一个config文件。

训练过程中,我用tensorboard实时监控:

tensorboard --logdir=work_dirs/my_project --bind_all

然后在浏览器打开http://your-server-ip:6006,就能看到loss曲线、learning rate、GPU利用率等。MMdetection会自动将这些指标写入work_dirs/my_project/20231001_120000.log.json,tools/analysis_tools/analyze_logs.py可以将其转为CSV供进一步分析。

4.4 模型评估与推理:tools/test.py与inference_detector的双轨验证

训练完成后,必须进行两轮评估:

第一轮:离线批量评估

python tools/test.py configs/my_project/faster_rcnn_r50_fpn_mydataset.py \ work_dirs/my_project/latest.pth \ --eval bbox \ --out results.pkl \ --cfg-options data.test.ann_file=/data/my_dataset/annotations/instances_test.json

--eval bbox会计算mAP@0.5:0.95等标准指标,并输出到控制台。--out results.pkl会将所有预测结果保存为pickle文件,供后续分析。

第二轮:在线单图推理

from mmdet.apis import init_detector, inference_detector import mmcv config_file = 'configs/my_project/faster_rcnn_r50_fpn_mydataset.py' checkpoint_file = 'work_dirs/my_project/latest.pth' # 初始化模型(自动选择GPU) model = init_detector(config_file, checkpoint_file, device='cuda:0') # 推理 img = mmcv.imread('demo/test.jpg') result = inference_detector(model, img) # 可视化 model.show_result(img, result, out_file='demo/result.jpg', score_thr=0.3)

这个脚本的好处是:它绕过了tools/test.py的复杂数据加载流程,直接对单张图做端到端推理,是调试模型是否“真能工作”的最快方法。如果show_result显示的框全是乱的,那问题一定出在模型权重或配置文件上;如果show_result正常,但tools/test.py的mAP很低,那问题可能出在测试集的数据加载或评估逻辑上。

5. 常见问题与排查技巧实录:一份来自20+次实战的“错误代码速查表”

5.1 “ImportError: libcudnn.so.8: cannot open shared object file” —— 动态链接库的迷宫

现象:import torch成功,但import mmcv失败,报找不到libcudnn.so.8。

根源:cuDNN库文件不在系统的动态链接器搜索路径中。

排查步骤:

  1. find /usr -name "libcudnn.so*",确认cuDNN是否真的安装了。通常在/usr/local/cuda-11.3/lib64/下。
  2. echo $LD_LIBRARY_PATH,检查该环境变量是否包含了cuDNN路径。如果没有,执行:
    export LD_LIBRARY_PATH=/usr/local/cuda-11.3/lib64:$LD_LIBRARY_PATH
  3. ldconfig -p | grep cudnn,检查系统级缓存是否已更新。如果没有,执行:
    echo '/usr/local/cuda-11.3/lib64' | sudo tee /etc/ld.so.conf.d/cuda.conf sudo ldconfig

实操心得:我习惯在~/.bashrc末尾添加:

# CUDA & cuDNN export CUDA_HOME=/usr/local/cuda export PATH=$CUDA_HOME/bin:$PATH export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH

这样每次新开终端都自动生效。

5.2 “OSError: libtorch_cuda.so: cannot open shared object file” —— PyTorch的“影子库”

现象:import torch成功,但import mmcv时,报找不到libtorch_cuda.so。

根源:PyTorch的CUDA库文件(libtorch_cuda.so)没有被正确链接到MMCV的编译环境中。

解决方案:这不是MMCV的问题,而是PyTorch安装的问题。必须用`conda

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

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

立即咨询