MMDetection 中的 DetectoRS:递归特征金字塔 RFP 与可切换空洞卷积 SAC 完整解析与实战指南

发布时间:2026/9/19 4:23:11
MMDetection 中的 DetectoRS:递归特征金字塔 RFP 与可切换空洞卷积 SAC 完整解析与实战指南 MMDetection 中的 DetectoRS递归特征金字塔 RFP 与可切换空洞卷积 SAC 完整解析与实战指南【免费下载链接】mmdetectionOpenMMLab Detection Toolbox and Benchmark项目地址: https://gitcode.com/gh_mirrors/mm/mmdetection本文以configs/detectors/目录为核心系统讲解 DetectoRSDetecting Objects with Recursive Feature Pyramid and Switchable Atrous Convolution算法在 MMDetection 中的实现、配置与使用。你将掌握 RFP 与 SAC 两大组件各自的原理、如何独立或组合启用它们、7 个官方配置文件的每一项参数含义、COCO COCO-stuff 数据准备流程以及底层源码的实现细节从而能够在自己的检测与分割任务中直接复现和迁移这一经典结构。DetectoRS 算法概述DetectoRS 出自论文《DetectoRS: Detecting Objects with Recursive Feature Pyramid and Switchable Atrous Convolution》arXiv:2006.02334作者 Siyuan Qiao 等其核心思想是让目标检测骨干网络多看多想几遍looking and thinking twice。这一思想分别在两个尺度上落地宏观层面在 FPN 特征金字塔之上引入额外的反馈连接把高层语义信息递归地回传给自底向上的骨干网络形成Recursive Feature PyramidRFP递归特征金字塔微观层面在每个卷积位置自适应地在不同空洞率之间切换形成Switchable Atrous ConvolutionSAC可切换空洞卷积。两者结合即为 DetectoRS。原论文在 COCO test-dev 上取得了当时领先的精度目标检测 box AP 55.7%、实例分割 mask AP 48.5%、全景分割 PQ 50.0%该精度数据来自论文原文与官方文档说明。在 MMDetection 中RFP 与 SAC 是两个相互独立、可单独启用的模块也可以叠加组合使用这是本目录配置设计上最值得注意的特点。两大核心组件原理解读RFP递归特征金字塔传统 FPN 的特征流向是单向的骨干网络自底向上提取特征FPN 自顶向下融合。RFP 在此基础上增加了一条自顶向下的反馈回路第一遍骨干网络如 ResNet提取多尺度特征送入 FPNFPN 输出的各层特征经过一个ASPP空洞空间金字塔池化模块做多尺度上下文增强增强后的特征作为外部输入沿反馈连接再次送入骨干网络的各 stage与骨干内部特征逐层相加通过额外的rfp_conv卷积对齐通道重复上述过程直到达到设定的递归步数rfp_steps每步迭代得到的 FPN 结果通过一个可学习的融合权重sigmoid 门控与上一步结果加权融合。从源码看RFP 的每一步迭代都被显式展开unrollrfp_steps2表示在初始一遍的基础上再递归 1 次见 rfp.py 中for rfp_idx in range(1, rfp_steps)的循环结构。SAC可切换空洞卷积空洞卷积Atrous/Dilated Convolution能在不增加参数量的情况下扩大感受野但固定空洞率无法适应不同尺寸的物体。SAC 的思路是让同一位置的特征并行通过多个不同空洞率的卷积结合 ConvAWS 卷积与可变形卷积的偏移能力用一个**开关函数switch function**逐空间位置、逐通道地学习如何混合各路结果从而根据输入内容自适应地调整感受野。在配置中对应sacdict(typeSAC, use_deformTrue)与stage_with_sac(False, True, True, True)前者的use_deformTrue表示开关分支采用可变形卷积实现偏移更灵活后者表示在 ResNet 的 stage2/3/4即 layer2/layer3/layer4启用 SAC而 stage1stem 之后的第一组残差块保持普通卷积。环境与数据准备COCO COCO-stuffDetectoRS 的训练除了常规 COCO 目标检测/实例分割标注外还需要COCO-stuff的 stuff 标注thing 之外的背景类别像素级标注因此其目录结构比普通 COCO 多一个stuffthingmaps目录。官方文档给出的目录结构如下mmdetection ├── mmdet ├── tools ├── configs ├── data │ ├── coco │ │ ├── annotations │ │ ├── train2017 │ │ ├── val2017 │ │ ├── test2017 │ │ └── stuffthingmaps对应到本仓库仓库根目录即 mmdetection 项目根实际使用的数据根路径由基础数据集配置configs/_base_/datasets/coco_detection.py中的data_root data/coco/指定。操作步骤下载 COCO 2017 数据集train2017 / val2017 / test2017 图片与 annotations 标注下载 COCO-stuff 的 stuffthingmaps_trainval2017 压缩包解压后放入data/coco/stuffthingmaps/确保data/coco/annotations/下有instances_train2017.json、instances_val2017.json等标准标注文件。需要注意本文介绍的检测配置主要消费 bbox 标注而 HTC 变体htc_r50-rfp_1x_coco.py等为实例分割模型还需要 mask 标注与 stuff 标注配合因此完整准备上述目录是复现所有配置的前提。配置文件全解析7 个官方配置一网打尽configs/detectors/目录下共有 7 个配置文件与 1 个metafile.yml元信息文件按组件组合 × 检测器两个维度组织配置文件组件组合基检测器调度cascade-rcnn_r50-rfp_1x_coco.py仅 RFPCascade R-CNN ResNet-501xcascade-rcnn_r50-sac_1x_coco.py仅 SACCascade R-CNN ResNet-501xdetectors_cascade-rcnn_r50_1x_coco.pyRFP SAC完整 DetectoRSCascade R-CNN ResNet-501xhtc_r50-rfp_1x_coco.py仅 RFPHTC ResNet-501xhtc_r50-sac_1x_coco.py仅 SACHTC ResNet-501xdetectors_htc-r50_1x_coco.pyRFP SACHTC ResNet-501xdetectors_htc-r101_20e_coco.pyRFP SACHTC ResNet-10120e基础配置继承链所有配置都基于 MMDetection 的_base_继承机制Cascade 系列继承configs/_base_/models/cascade-rcnn_r50_fpn.py三阶段 Cascade R-CNNRPN 3 个级联Shared2FCBBoxHeadIoU 阈值 0.5/0.6/0.7、configs/_base_/datasets/coco_detection.py、configs/_base_/schedules/schedule_1x.py、configs/_base_/default_runtime.pyHTC 系列直接继承configs/htc/htc_r50_fpn_1x_coco.py或 101 变体复用其完整的混合任务级联结构。schedule_1x.py的调度细节12 个 epochSGD 优化器lr0.02、momentum0.9、weight_decay0.0001前 500 次迭代 warmupLinearLRstart_factor0.001第 8 与第 11 epoch 学习率衰减 10 倍MultiStepLRgamma0.1并支持按base_batch_size16自动缩放学习率。仅启用 RFP 的配置以 cascade-rcnn_r50-rfp_1x_coco.py 为例_base_ [ ../_base_/models/cascade-rcnn_r50_fpn.py, ../_base_/datasets/coco_detection.py, ../_base_/schedules/schedule_1x.py, ../_base_/default_runtime.py ] model dict( backbonedict( typeDetectoRS_ResNet, # 支持 RFP/SAC 的 ResNet 变体 conv_cfgdict(typeConvAWS), # 由 mmcv 提供的卷积实现SAC 的基础卷积 output_imgTrue), # 关键把输入原图放进输出列表供 RFP 递归使用 neckdict( typeRFP, # 替换标准 FPN 为递归特征金字塔 rfp_steps2, # 递归步数初始一遍 1 次递归 aspp_out_channels64, # ASPP 每分支输出通道数 aspp_dilations(1, 3, 6, 1), # 四个分支的空洞率最后一位 1 配合全局池化分支 rfp_backbonedict( # 递归用的第二个骨干网络与主骨干同构 rfp_inplanes256, typeDetectoRS_ResNet, depth50, num_stages4, out_indices(0, 1, 2, 3), frozen_stages1, norm_cfgdict(typeBN, requires_gradTrue), norm_evalTrue, conv_cfgdict(typeConvAWS), pretrainedtorchvision://resnet50, stylepytorch)))关键点仅启用 RFP 时不需要 SAC 相关字段但骨干必须设置output_imgTrue因为 RFP 的forward期望输入列表比 FPN 多一项len(inputs) len(self.in_channels) 1见 rfp.py第一项就是原始输入图像。仅启用 SAC 的配置cascade-rcnn_r50-sac_1x_coco.py 的模型部分model dict( backbonedict( typeDetectoRS_ResNet, conv_cfgdict(typeConvAWS), sacdict(typeSAC, use_deformTrue), # 启用 SAC开关分支用可变形卷积 stage_with_sac(False, True, True, True))) # stage2/3/4 启用stage1 不用这里neck保持不变仍是基础 FPN仅骨干替换为带 SAC 的DetectoRS_ResNet是开销最小论文报告约 5.6 GB 训练显存的增强方式。完整 DetectoRSRFP SACdetectors_cascade-rcnn_r50_1x_coco.py 将两者叠加骨干同时配置sac/stage_with_sac与output_imgTruerfp_backbone内部也带上sac/stage_with_sac递归用的第二个骨干同样享受 SAC 增强形成完整 DetectoRS。其结构为model dict( backbonedict( typeDetectoRS_ResNet, conv_cfgdict(typeConvAWS), sacdict(typeSAC, use_deformTrue), stage_with_sac(False, True, True, True), output_imgTrue), neckdict( typeRFP, rfp_steps2, aspp_out_channels64, aspp_dilations(1, 3, 6, 1), rfp_backbonedict( rfp_inplanes256, typeDetectoRS_ResNet, depth50, num_stages4, out_indices(0, 1, 2, 3), frozen_stages1, norm_cfgdict(typeBN, requires_gradTrue), norm_evalTrue, conv_cfgdict(typeConvAWS), sacdict(typeSAC, use_deformTrue), stage_with_sac(False, True, True, True), pretrainedtorchvision://resnet50, stylepytorch)))HTC 系列detectors_htc-r50_1x_coco.py、detectors_htc-r101_20e_coco.py结构完全一致只是把 Cascade R-CNN 换成 HTC 并相应继承不同基配置101 版本将depth、pretrained改为 101 并将调度改为 20e继承htc_r101_fpn_20e_coco.py的调度训练更长、精度更高。关键参数速查表参数位置取值官方配置作用conv_cfgbackbonedict(typeConvAWS)由 mmcv 注册表构建的基础卷积层是 SAC 的构成单元sacbackbonedict(typeSAC, use_deformTrue)启用可切换空洞卷积use_deform决定开关分支是否用可变形卷积stage_with_sacbackbone(False, True, True, True)各 stage 是否启用 SACoutput_imgbackboneTrue将原图插入输出序列首位RFP 必需rfp_stepsneck2递归展开步数aspp_out_channelsneck64ASPP 各分支输出通道aspp_dilationsneck(1, 3, 6, 1)ASPP 四分支空洞率末位恒为 1配合全局平均池化rfp_inplanesrfp_backbone256RFP 反馈特征进入骨干前的通道数用于构建rfp_convfrozen_stagesrfp_backbone1冻结前 1 个 stage 的 BN 等参数降低显存与训练成本norm_evalrfp_backboneTrue推理/验证时 BN 使用统计量而非批统计量源码级原理剖析DetectoRS_ResNet可插拔的骨干变体DetectoRS_ResNet定义在 detectors_resnet.py继承自标准ResNet核心新增四个构造参数sacSAC 配置字典非空时各 stage 的 Bottleneck 会用build_conv_layer(self.sac, ...)构建conv2见 detectors_resnet.py即把普通 3×3 卷积替换为 SAC 卷积stage_with_sac与sac配合逐 stage 决定是否启用rfp_inplanes非空时每个 Bottleneck 额外挂一个 1×1 的rfp_convrfp_inplanes → planes*expansion用于对齐 RFP 反馈特征的通道数见 detectors_resnet.py且该卷积默认以零初始化output_img为True时forward会在输出元组头部插入原始输入图像见 detectors_resnet.py供 RFP 迭代使用。arch_settings支持 depth 50/101/152 三种规格detectors_resnet.py另有 detectors_resnext.py 提供DetectoRS_ResNeXt变体继承DetectoRS_ResNet方便替换为 ResNeXt 骨干。Bottleneck 中的递归融合当rfp_inplanes非空时Bottleneck 走专门的rfp_forwarddetectors_resnet.py先做标准的残差计算out _inner_forward(x)然后执行if self.rfp_inplanes: rfp_feat self.rfp_conv(rfp_feat) # 通道对齐 out out rfp_feat # 反馈特征与内部特征逐元素相加 out self.relu(out)即 RFP 反馈信息以逐 stage 相加的方式注入骨干。注意第一个 stagei 0不接收反馈rfp_inplanesrfp_inplanes if i 0 else None见 detectors_resnet.py与论文低频细节无需反馈的设计一致。RFP 神经网络的迭代计算流程RFP定义在 rfp.py继承自FPN因此天然具备 FPN 的全部行为lateral 连接、top-down 融合、5 层输出。其构造阶段会为除第一次外的每次递归各构建一份rfp_backboneModuleList保证预训练权重可加载self.rfp_modules ModuleList() for rfp_idx in range(1, rfp_steps): rfp_module MODELS.build(rfp_backbone) self.rfp_modules.append(rfp_module)forward的完整流程rfp.py从输入序列中弹出第一项img即骨干output_img插入的原图对剩余的多尺度特征先跑一遍标准 FPN得到x对每个递归步把x[0]与经 ASPP 增强的x[1:]组成rfp_feats喂给对应rfp_backbone.rfp_forward(img, rfp_feats)得到新多尺度特征再跑一遍 FPN 得到x_idx用可学习的融合权重对x与x_idx做逐层加权add_weight torch.sigmoid(self.rfp_weight(x_idx[ft_idx])) x_new.append(add_weight * x_idx[ft_idx] (1 - add_weight) * x[ft_idx])rfp_weight是一个 1×1 卷积输出单通道见 rfp.pyinit_weights中将其零初始化rfp.py使训练初期加权结果等于上一次 FPN 输出保证稳定起步。ASPP多尺度上下文增强RFP 内部的ASPP模块rfp.py包含四个分支前三个为 3×3 空洞卷积空洞率来自aspp_dilations的前三项如 1/3/6最后一个分支为 1×1 卷积 全局平均池化AdaptiveAvgPool2d(1)其输出会expand_as恢复空间尺寸后与其他分支拼接。整体把 FPN 的 256 通道特征压缩为aspp_out_channels64× 4 分支 256 通道的增强特征。源码断言dilations[-1] 1与配置中(1, 3, 6, 1)末位为 1 完全对应。初始化约束与测试验证RFP.__init__明确禁止外部传入init_cfgrfp.py防止破坏递归骨干的预训练加载DetectoRS_ResNet.init_weights也刻意不调用父类初始化detectors_resnet.py只允许pretrained字符串或None两种初始化方式。这些约束被 test_detectors_resnet.py 的test_detectorrs_resnet_backbone用例显式覆盖测试验证了pretrained与init_cfg同时指定会抛AssertionError、init_cfg非 dict 会抛错、缺少type键会抛KeyError、非 Pretrained 类型会抛AssertionError、pretrained传列表会抛TypeError。这些断言也提醒使用者配置 DetectoRS 骨干时请使用pretrainedtorchvision://resnet50的写法不要混用init_cfg。模型结果与基准COCO 2017 val官方文档在 COCO 2017 val 上的结果如下对应configs/detectors/各配置MethodDetectorLr schdMem (GB)Inf time (fps)box APmask APConfigRFPCascade ResNet-501x7.5-44.8configSACCascade ResNet-501x5.6-45.0configDetectoRSCascade ResNet-501x9.9-47.4configRFPHTC ResNet-501x11.2-46.640.9configSACHTC ResNet-501x9.3-46.440.9configDetectoRSHTC ResNet-501x13.6-49.142.6configDetectoRSHTC ResNet-10120e19.650.543.9config从表中可以读出清晰的规律单独看在 Cascade R-CNN ResNet-50 上仅 RFP 带来 44.8 box AP仅 SAC 带来 45.0 box AP均高于基础 Cascade R-CNN叠加看RFP SAC 组合完整 DetectoRS达到 47.4 box AP比任一单独组件都高约 2.4~2.6 个点说明两个机制互补换检测器与 HTC 结合后精度更高50.5 box AP / 43.9 mask APResNet-101 20e但显存开销也显著增长最高 19.6 GB部署前需评估显存预算所有模型的官方权重与训练日志可通过各配置对应的下载链接获取链接详情见 metafile.yml 中的Weights字段可用于直接复现评测。需要说明的是这些结果是官方仓库基于 MMDetection-V2 的重新实现结果README 明确注明 This is a re-implementation based on MMDetection-V2原论文实现基于 MMDetection-V1与论文报告值COCO test-dev 55.7 box AP存在评测集与实现上的差异对比精度时应注意口径。训练、测试与推理实战单机多卡训练使用仓库自带的分布式训练脚本假设 8 卡启动完整 DetectoRSCascade R50bash tools/dist_train.sh configs/detectors/detectors_cascade-rcnn_r50_1x_coco.py 8单卡训练则为python tools/train.py configs/detectors/detectors_cascade-rcnn_r50_1x_coco.py官方模型采用 SGD with Momentum Weight Decay见 schedule_1x.py训练资源为 8×V100 GPU见 metafile.yml 的Training Resources字段。训练日志、checkpoint 默认输出到work_dirs/下以配置名为前缀的目录。评测与推理对已训练或下载的官方checkpoint 进行评测python tools/test.py configs/detectors/detectors_cascade-rcnn_r50_1x_coco.py \ /path/to/detectors_cascade_rcnn_r50_1x_coco-32a10ba0.pth对单张图片做可视化推理可使用仓库的 image_demo.pypython demo/image_demo.py demo/demo.jpg \ configs/detectors/detectors_cascade-rcnn_r50_1x_coco.py \ /path/to/detectors_cascade_rcnn_r50_1x_coco-32a10ba0.pth选择建议显存紧张、想快速验证选 SAC 单独配置约 5.6 GB改动最小、收益直接追求检测精度Cascade 完整 DetectoRS9.9 GB47.4 box AP需要实例分割选 HTC 系列RFP 或完整 DetectoRS同时产出 box 与 mask 结果资源充足、追求极致detectors_htc-r101_20e_coco.py50.5 box AP / 43.9 mask AP但需约 19.6 GB 显存训练调度为 20e。注意事项与常见问题pretrained与init_cfg互斥DetectoRS_ResNet只接受字符串pretrained如torchvision://resnet50或init_cfg中typePretrained一种方式二者同时出现会直接报错这也是测试用例重点覆盖的初始化契约test_detectors_resnet.py。RFP 需要完整的rfp_backbone配置它本质上是第二个骨干网络depth、num_stages、out_indices、norm_cfg、conv_cfg等必须与主骨干保持同构否则特征层级与通道数无法对齐。output_imgTrue是 RFP 的硬性前提缺少该字段会导致 RFP 前向断言失败输入层级数不匹配。不要给 RFP 传init_cfg源码中明确init_cfg is not allowed to be set以免破坏递归骨干的权重加载。显存与训练时间成本RFP 每次递归都要完整跑一遍骨干 FPNDetectoRS 的显存约为单独组件的 1.5~2 倍若显存受限可将frozen_stages提高、或考虑梯度 checkpoint。数据要求HTC 系列需要 COCO 实例分割标注mask与 COCO-stuff stuff 标注仅下载检测标注无法训练完整配置。引用若在你的研究或工程中使用本目录配置请引用原论文README 提供的 BibTeXarticle{qiao2020detectors, title{DetectoRS: Detecting Objects with Recursive Feature Pyramid and Switchable Atrous Convolution}, author{Qiao, Siyuan and Chen, Liang-Chieh and Yuille, Alan}, journal{arXiv preprint arXiv:2006.02334}, year{2020} }更多源码细节可继续阅读detectors_resnet.py、rfp.py、detectors_resnext.py以及配置元信息 metafile.yml。【免费下载链接】mmdetectionOpenMMLab Detection Toolbox and Benchmark项目地址: https://gitcode.com/gh_mirrors/mm/mmdetection创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考