MMDetection 接入 timm 骨干网络实战:基于 TIMMBackbone 的 RetinaNet 配置与调试指南
2026/9/19 16:44:04 网站建设 项目流程

MMDetection 接入 timm 骨干网络实战:基于 TIMMBackbone 的 RetinaNet 配置与调试指南

【免费下载链接】mmdetectionOpenMMLab Detection Toolbox and Benchmark项目地址: https://gitcode.com/gh_mirrors/mm/mmdetection

MMDetection 通过mmpretrain.TIMMBackbone这一封装类,可以在检测模型中直接使用 PyTorch Image Models(timm)社区提供的海量预训练骨干网络。本指南以configs/timm_example/下的两个官方示例(torchvision ResNet-50 与 EfficientNet-B1 + RetinaNet)为主线,完整讲解依赖安装、配置逐行解析、FPN 通道对齐调试,以及 Vision Transformer 等特殊骨干的兼容处理,读完即可在 MMDetection 中替换任意 timm 骨干进行训练与推理。

背景:为什么在 MMDetection 中使用 timm 骨干

timm(PyTorchImageModels)是一个汇集了大量图像模型、网络层、工具函数、优化器、调度器、数据加载与增强方案的模型库,其目标是把各类 SOTA 模型与可复现 ImageNet 训练结果的能力整合到一起。timm 中维护着远超 MMDetection 内置 backbone 列表的预训练权重,因此"在检测框架里复用 timm 骨干"是快速对比不同主干特征提取能力的常见做法。

MMDetection 并未为每个 timm 模型单独实现一遍,而是借助 OpenMMLab 的层级注册表(Hierarchy Registry)机制:MMDet、MMPretrain(原 MMClassification)、MMSeg 的模型注册表都继承自 MMEngine 的根注册表,因此各仓库可以直接使用彼此已实现的模块。MMPretrain 中提供了TIMMBackbone封装类,它在内部调用 timm 的create_model与特征提取接口,把 timm 模型包装成符合 MMDetection backbone 约定的模块。相关机制说明可见 docs/en/advanced_guides/how_to.md,其中既有mmpretrain.MobileNetV3等 MMPretrain 原生骨干的用法,也有mmpretrain.TIMMBackbone的完整示例。

因此,你需要在环境中额外安装两个包:timm(模型来源)与mmpretrain(提供TIMMBackbone封装与注册)。

安装额外依赖

原文档给出的安装命令如下:

pip install 'dataclasses; python_version<"3.7"' pip install timm pip install mmpretrain

三点说明:

  • 第一行带有python_version<"3.7"环境标记,仅在 Python 低于 3.7 的旧环境才会实际安装dataclasses,现代 Python(3.7+)会自动跳过,不会造成副作用。
  • timm是 PyTorch Image Models 本体,提供所有模型结构与预训练权重下载。
  • mmpretrain提供TIMMBackbone封装类,必须安装;若不安装,配置中type='mmpretrain.TIMMBackbone'将无法解析。MMPretrain 的完整安装步骤可参考其官方文档的 Installation 章节。

示例配置逐行解析

configs/timm_example/目录下提供了两个可直接运行的示例(完整代码见 retinanet_timm-efficientnet-b1_fpn_1x_coco.py 与 retinanet_timm-tv-resnet50_fpn_1x_coco.py),二者均以_base_继承 RetinaNet-R50、COCO 检测数据集、1x 训练计划与默认运行配置,再以最小改动替换 backbone:

_base_ = [ '../_base_/models/retinanet_r50_fpn.py', '../_base_/datasets/coco_detection.py', '../_base_/schedules/schedule_1x.py', '../_base_/default_runtime.py' ] # please install mmpretrain # import mmpretrain.models to trigger register_module in mmpretrain custom_imports = dict( imports=['mmpretrain.models'], allow_failed_imports=False) model = dict( backbone=dict( _delete_=True, type='mmpretrain.TIMMBackbone', model_name='efficientnet_b1', features_only=True, pretrained=True, out_indices=(1, 2, 3, 4)), neck=dict(in_channels=[24, 40, 112, 320])) # optimizer optim_wrapper = dict(optimizer=dict(lr=0.01))

各关键字段的作用如下:

配置项含义与取值说明
custom_imports通过 MMEngine 的custom_imports机制在配置加载阶段导入mmpretrain.models,从而触发其中的@MODELS.register_module()注册逻辑,使mmpretrain.TIMMBackbone等类型名可用;allow_failed_imports=False表示导入失败直接报错。这一写法同样适用于引入其他自定义模块(见 docs/en/advanced_guides/customize_models.md)。
_delete_=True覆盖继承规则:删除_base_retinanet_r50_fpn.py定义的ResNetbackbone 字段,避免新旧键合并残留(详见 docs/en/advanced_guides/customize_models.md)。
type='mmpretrain.TIMMBackbone'类型名中的mmpretrain指明实现位于 MMPretrain 仓库,TIMMBackbone是该仓库中封装 timm 的 backbone 类名。
model_name='efficientnet_b1'指定 timm 中的模型名称;另一个示例使用tv_resnet50,即加载 torchvision 权重的 ResNet-50。可换成任意 timm 支持的模型名。
features_only=True让 backbone 仅输出特征图(feature map)而非分类 logits,这是检测场景必需的开关,对应 timm 的features_only特征提取模式。
pretrained=True自动加载该模型在 timm 中的预训练权重。
out_indices=(1, 2, 3, 4)指定输出第 1 到第 4 个阶段的特征图(EfficientNet-B1 共 5 个 stage,取后 4 个作为 FPN 输入)。
neck=dict(in_channels=[24, 40, 112, 320])必须与 backbone 实际输出通道数一致:EfficientNet-B1 第 1~4 个输出 stage 的通道数分别为 24、40、112、320。
optim_wrapper.optimizer.lr=0.01覆盖_base_中 1x 计划默认的 0.02;更换 backbone 后参数量与收敛特性改变,示例统一将学习率下调为 0.01。

两个示例的差异集中在 backbone 部分:tv_resnet50版本不显式修改neck.in_channels,因为其输出通道 [256, 512, 1024, 2048] 恰好与_base_中 FPN 默认值一致,而 EfficientNet-B1 版本必须按上表改写。

继承的_base_配置:RetinaNet 全貌

示例配置只覆盖了 backbone 与 neck 的少量字段,其余结构全部来自 configs/base/models/retinanet_r50_fpn.py,理解继承内容有助于排查问题:

  • 数据预处理器DetDataPreprocessor,ImageNet 均值/方差 [123.675, 116.28, 103.53] 与 [58.395, 57.12, 57.375],bgr_to_rgb=Truepad_size_divisor=32
  • 检测头RetinaHead(num_classes=80、4 层 stacked conv、256 维 feat_channels);anchor 由AnchorGenerator生成(octave_base_scale=4、scales_per_octave=3、ratios=[0.5, 1.0, 2.0]、strides=[8, 16, 32, 64, 128]);分类用FocalLoss(gamma=2.0、alpha=0.25),回归用L1Loss
  • 训练/测试设置MaxIoUAssigner(pos/neg IoU 阈值 0.5/0.4)+PseudoSampler(Focal loss 的配套采样器);测试阶段nms_pre=1000score_thr=0.05、NMS IoU 阈值 0.5、max_per_img=100

数据侧继承 configs/base/datasets/coco_detection.py:CocoDatasetdata_root='data/coco/'、train/val 的 pipeline(Resize 1333×800、RandomFlip、PackDetInputs)以及CocoMetric评测配置;训练计划继承 configs/base/schedules/schedule_1x.py:EpochBasedTrainLoop共 12 epochs、500 步LinearLRwarmup、milestones [8, 11] 的MultiStepLR、SGD(momentum=0.9、weight_decay=0.0001),以及auto_scale_lr = dict(enable=False, base_batch_size=16)的自动学习率缩放设定。

关键调试要点:对齐 out_channels 与 out_strides

原文档强调,具体输出哪些特征图取决于所选的 backbone。tim 中不同模型的 stage 划分、各 stage 输出通道数与下采样倍数(stride)各不相同,因此替换骨干后必须验证以下两项,并在必要时修改配置:

  1. backbone out_channels(输出通道数):训练日志会打印 backbone 各输出层的通道数,需将其与model.neck.in_channels对齐。例如 EfficientNet-B1 输出 [24, 40, 112, 320],配置中neck.in_channels必须同步改为这四个数。
  2. backbone out_strides(输出步长):影响 FPN 的start_level与 anchor 的strides设置。若更换后的 backbone 下采样节奏与默认 ResNet(stride 4 起步、逐级 ×2)不同,需相应调整model.neck.start_levelmodel.backbone.out_indices(在 configs/base/models/retinanet_r50_fpn.py 中可看到默认 FPN 的start_level=1add_extra_convs='on_input'num_outs=5)。

简言之:先跑一个短训练或直接查看日志中的 backbone 结构信息,再回头核对out_indicesin_channels,这是替换 timm 骨干时最常遇到的坑。

特殊情形:Vision Transformer 骨干与 NumClassCheckHook

MMDetection 默认启用NumClassCheckHook(注册与实现见 mmdet/engine/hooks/num_class_check_hook.py),该 Hook 在before_train_epochbefore_val_epoch时遍历模型中所有含num_classes属性的模块,断言其数值与dataset.metainfo['classes']的长度一致,用于提前发现类别数不匹配的配置错误。

问题在于:部分Vision Transformer 模型不支持features_only=True(即无法通过 timm 特征提取接口直接产出多尺度特征图),这类模型在 Hook 检查阶段可能因特征行为不符合预期而报错。针对此类 backbone,原文档给出的处理方法是:在配置中加入custom_hooks = [],显式清空默认 Hook 列表,从而禁用NumClassCheckHook,使训练流程得以继续。

同时要理解该 Hook 的检查前提:它要求数据集metainfo中设置classes字段(且必须是 tuple 而非字符串),若classes缺失则只输出 warning。因此即便不禁用 Hook,为自定义数据集正确声明classes也是规范做法。

训练、测试与推理

仓库提供了标准入口脚本(tools/train.py、tools/test.py 以及 demo/image_demo.py),配置替换完成后即可按 MMDetection 通用流程使用:

# 训练(单卡,EfficientNet-B1 示例) python tools/train.py configs/timm_example/retinanet_timm-efficientnet-b1_fpn_1x_coco.py # 多卡分布式训练 bash tools/dist_train.sh configs/timm_example/retinanet_timm-efficientnet-b1_fpn_1x_coco.py 8 # 使用训练好的 checkpoint 在 COCO val 上评测 python tools/test.py configs/timm_example/retinanet_timm-efficientnet-b1_fpn_1x_coco.py <checkpoint路径> # 单图推理 python demo/image_demo.py demo/demo.jpg configs/timm_example/retinanet_timm-efficientnet-b1_fpn_1x_coco.py <checkpoint路径>

需要说明:更换 backbone 后由于预训练分布、参数量与输出结构的变化,直接沿用 1x 计划并不保证与内置 ResNet 基线同等精度,更稳妥的做法是以此配置为起点,调整lrout_indices与 FPN 相关参数进行针对性实验。两个示例当前记录的box AP尚待补齐,属正常的示例占位状态。

结果与模型

RetinaNet

BackboneStyleLr schdMem (GB)Inf time (fps)box APConfigDownload
R-50(tv_resnet50)pytorch1xconfig
EfficientNet-B1-1xconfig

引用

若在研究中引用 timm 或本示例,可使用如下 BibTeX:

@misc{rw2019timm, author = {Ross Wightman}, title = {PyTorch Image Models}, year = {2019}, publisher = {GitHub}, journal = {GitHub repository}, doi = {10.5281/zenodo.4414861}, howpublished = {\url{https://github.com/rwightman/pytorch-image-models}} }

小结

在 MMDetection 中使用 timm 骨干的本质是"通过mmpretrain.TIMMBackbone复用另一个 OpenMMLab 仓库的封装",因此安装mmpretraintimm是前提,custom_imports触发注册、_delete_=True覆盖_base_中的 backbone 是配置骨架,而根据日志中的out_channels/out_strides对齐neck.in_channelsbackbone.out_indices是调试的核心环节;遇到不支持features_only=True的 Vision Transformer 时,用custom_hooks = []禁用NumClassCheckHook即可绕过检查。以 retinanet_timm-efficientnet-b1_fpn_1x_coco.py 为模板,你可以在 RetinaNet 乃至其他检测器上自由尝试 timm 社区的各种骨干。

【免费下载链接】mmdetectionOpenMMLab Detection Toolbox and Benchmark项目地址: https://gitcode.com/gh_mirrors/mm/mmdetection

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询