MMDetection 中的 DAB-DETR:动态锚框作为 Transformer 解码器查询的完整解读与实践指南
2026/9/19 21:04:45 网站建设 项目流程

MMDetection 中的 DAB-DETR:动态锚框作为 Transformer 解码器查询的完整解读与实践指南

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

导读

DAB-DETR(Dynamic Anchor Boxes are Better Queries for DETR)是 DETR 系列目标检测算法的重要演进,其核心洞察在于:将 Transformer 解码器的 query 直接定义为可学习的动态锚框(anchor box)坐标,并逐层迭代更新,从而显著缓解了原始 DETR 训练收敛缓慢的问题,同时带来了更优的检测精度。本文以 MMDetection 仓库中的configs/dab_detr/配置与对应源码实现为依托,系统讲解 DAB-DETR 的算法原理、完整配置参数、底层实现细节以及训练与推理方法,帮助读者在 MMDetection 框架中快速上手并深入理解这一模型。

DAB-DETR 算法核心思想

DAB-DETR 论文(DAB-DETR: Dynamic Anchor Boxes are Better Queries for DETR,发表于 ICLR 2022)提出了一种全新的 query 构造方式:直接使用边界框坐标(box coordinates)作为 Transformer 解码器的 query,并在解码器的每一层动态更新这些坐标。这一设计带来了三个层面的关键收益:

  1. 显式的位置先验(explicit positional priors):将 query 与目标位置直接绑定,提升了 query 与特征之间的相似度(query-to-feature similarity),从而消除了原始 DETR 训练收敛缓慢的问题;
  2. 可调制的空间注意力(modulated positional attention):利用锚框的宽高(width/height)信息对位置注意力图进行调制,使注意力分布与目标形状相适应;
  3. 级联的软 ROI 池化视角:该设计表明,DETR 中的 query 本质上是逐层执行"软 ROI 池化"(soft ROI pooling)的级联过程,为理解 DETR 解码器提供了新的理论视角。

从论文报告的实验结果看,在相同设置下,DAB-DETR 在 MS-COCO 基准上达到了当时 DETR 类检测模型的最优性能,例如使用 ResNet50-DC5 骨干、训练 50 epochs 时达到 AP 45.7%。MMDetection 中官方复现的 ResNet-50 + FPN 版本在 50 epochs 训练下取得box AP 42.3(详见下文"模型结果"一节)。

配置总览:dab-detr_r50_8xb2-50e_coco.py 逐段解析

MMDetection 中 DAB-DETR 的官方配置位于 configs/dab_detr/dab-detr_r50_8xb2-50e_coco.py,文件名中的8xb2表示 8 张 GPU、每张 2 张样本,50e表示训练 50 个 epoch。该配置基于coco_detection数据集配置与default_runtime运行时配置组合而成。

模型主体:DABDETR 检测器

model = dict( type='DABDETR', num_queries=300, with_random_refpoints=False, num_patterns=0, data_preprocessor=dict( type='DetDataPreprocessor', mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], bgr_to_rgb=True, pad_size_divisor=1), ... )

关键参数说明:

  • type='DABDETR':对应注册在 mmdet/models/detectors/dab_detr.py 的DABDETR检测器类,它继承自DETR
  • num_queries=300:解码器 query 的数量,即每张图最多输出的目标候选数;
  • with_random_refpoints=False:若为True,则随机初始化 query 嵌入且训练中不再更新(论文的消融设置);False时 query 作为可学习参数正常参与训练,这也是该配置的默认行为;
  • num_patterns=0:受 Anchor-DETR 启发的 pattern 数量,默认为 0 即不启用;启用时每个 query 会扩展为num_queries × num_patterns组。

骨干与颈部:ResNet-50 + ChannelMapper

backbone=dict( type='ResNet', depth=50, num_stages=4, out_indices=(3, ), frozen_stages=1, norm_cfg=dict(type='BN', requires_grad=False), norm_eval=True, style='pytorch', init_cfg=dict(type='Pretrained', checkpoint='torchvision://resnet50')), neck=dict( type='ChannelMapper', in_channels=[2048], kernel_size=1, out_channels=256, act_cfg=None, norm_cfg=None, num_outs=1),

与普通两阶段检测器不同,DAB-DETR 的骨干只取最后一层特征(out_indices=(3, )),随后由一个 1×1 卷积的ChannelMapper将其投影为 256 维的单一尺度特征图送入 Transformer 编码器。这种设计意味着该版本是单尺度(single-scale)的 DETR 架构。

Transformer 编码器与解码器

encoder=dict( num_layers=6, layer_cfg=dict( self_attn_cfg=dict( embed_dims=256, num_heads=8, dropout=0., batch_first=True), ffn_cfg=dict( embed_dims=256, feedforward_channels=2048, num_fcs=2, ffn_drop=0., act_cfg=dict(type='PReLU')))), decoder=dict( num_layers=6, query_dim=4, query_scale_type='cond_elewise', with_modulated_hw_attn=True, layer_cfg=dict( self_attn_cfg=dict( embed_dims=256, num_heads=8, attn_drop=0., proj_drop=0., cross_attn=False), cross_attn_cfg=dict( embed_dims=256, num_heads=8, attn_drop=0., proj_drop=0., cross_attn=True), ffn_cfg=dict( embed_dims=256, feedforward_channels=2048, num_fcs=2, ffn_drop=0., act_cfg=dict(type='PReLU'))), return_intermediate=True),

这里集中体现了 DAB-DETR 的核心配置:

  • query_dim=4:query 位置使用 (cx, cy, w, h) 的四维锚框格式;源码 mmdet/models/layers/transformer/dab_detr_layers.py 中 assert 该值只能取 2(点先验)或 4(锚框先验);
  • query_scale_type='cond_elewise':内容 query 的变换方式,源码支持cond_elewise(逐元素条件变换,MLP 输出与 embed_dims 同维)、cond_scalar(标量条件缩放)和fix_elewise(固定的逐层可学习向量)三种;
  • with_modulated_hw_attn=True:启用宽高调制的交叉注意力,通过ref_anchor_head预测相对宽高比并对正弦位置编码做调制;
  • return_intermediate=True:解码器输出所有中间层结果,供各层辅助监督损失使用。

位置编码与检测头

positional_encoding=dict(num_feats=128, temperature=20, normalize=True), bbox_head=dict( type='DABDETRHead', num_classes=80, embed_dims=256, loss_cls=dict( type='FocalLoss', use_sigmoid=True, gamma=2.0, alpha=0.25, loss_weight=1.0), loss_bbox=dict(type='L1Loss', loss_weight=5.0), loss_iou=dict(type='GIoULoss', loss_weight=2.0)),
  • positional_encoding采用正弦位置编码(SinePositionalEncoding),num_feats=128满足源码中的约束num_feats * 2 == embed_dims(见 dab_detr.py);
  • 检测头DABDETRHead继承自ConditionalDETRHead,分类使用带 sigmoid 的 Focal Loss,回归使用 L1 Loss(权重 5.0)与 GIoU Loss(权重 2.0);
  • 头部的回归分支fc_reg是一个输出 4 维的 3 层 MLP(见 dab_detr_head.py),正是它承担了"动态更新锚框"的职责——它同时被传入解码器作为reg_branches,在每个解码层输出锚框增量(详见下文解码流程)。

训练/测试设置:Hungarian 匹配

train_cfg=dict( assigner=dict( type='HungarianAssigner', match_costs=[ dict(type='FocalLossCost', weight=2., eps=1e-8), dict(type='BBoxL1Cost', weight=5.0, box_format='xywh'), dict(type='IoUCost', iou_mode='giou', weight=2.0) ])), test_cfg=dict(max_per_img=300)

DAB-DETR 沿用 DETR 的二分图匹配训练范式,通过 Hungarian 算法在预测与真值之间建立一对一匹配,匹配代价由分类代价(FocalLossCost)、L1 框代价(BBoxL1Cost)与 GIoU 代价(IoUCost)加权求和组成,各权重与对应损失权重保持一致。推理时每张图最多输出 300 个检测框。

训练流水线、优化器与学习率

配置中的训练流水线与默认 COCO 配置不同,采用多尺度训练策略:

train_pipeline = [ dict(type='LoadImageFromFile', backend_args={{_base_.backend_args}}), dict(type='LoadAnnotations', with_bbox=True), dict(type='RandomFlip', prob=0.5), dict( type='RandomChoice', transforms=[[ dict( type='RandomChoiceResize', scales=[(480, 1333), (512, 1333), ..., (800, 1333)], keep_ratio=True) ], [ # 随机裁剪增强分支:先缩放到较短边 400/500/600, # 再在 384x600 绝对范围内随机裁剪,最后再随机缩放 dict(type='RandomChoiceResize', scales=[(400, 1333), (500, 1333), (600, 1333)], keep_ratio=True), dict(type='RandomCrop', crop_type='absolute_range', crop_size=(384, 600), allow_negative_crop=True), dict(type='RandomChoiceResize', scales=[(480, 1333), (512, 1333), ..., (800, 1333)], keep_ratio=True) ]]), dict(type='PackDetInputs') ]

注意配置中特意注明:这里的img_scalePadsize_divisor(此处为 1)与 MMDetection 默认设置不同。

优化与学习率调度部分:

optim_wrapper = dict( type='OptimWrapper', optimizer=dict(type='AdamW', lr=0.0001, weight_decay=0.0001), clip_grad=dict(max_norm=0.1, norm_type=2), paramwise_cfg=dict( custom_keys={'backbone': dict(lr_mult=0.1, decay_mult=1.0)})) max_epochs = 50 param_scheduler = [ dict( type='MultiStepLR', begin=0, end=max_epochs, by_epoch=True, milestones=[40], gamma=0.1) ]
  • 优化器采用 AdamW(lr=1e-4,weight_decay=1e-4),并启用梯度裁剪(max_norm=0.1);
  • 骨干网络学习率缩放为 0.1 倍(lr_mult=0.1),这是 DETR 系模型的常见做法;
  • 学习率在 40 epoch 处下降 10 倍(MultiStepLR,milestones=[40]);
  • auto_scale_lr = dict(base_batch_size=16, enable=False):以 8 GPU × 2 样本 = 16 的 batch size 为基准,供需要自动缩放学习率时参考(该配置默认关闭)。

源码级原理:动态锚框如何"动态"更新

MMDetection 对 DAB-DETR 的实现分布在三个文件中:检测器 mmdet/models/detectors/dab_detr.py、检测头 mmdet/models/dense_heads/dab_detr_head.py 以及 Transformer 层 mmdet/models/layers/transformer/dab_detr_layers.py。

查询初始化:锚框嵌入而非内容嵌入

在 dab_detr.py 的 pre_decoder 中可以看到,query_embedding是一个维度为(num_queries, query_dim)的 Embedding,即每个 query 直接对应一组 4 维锚框坐标(的逆 sigmoid 形式)。进入解码器前:

  • query_pos直接取query_embedding.weight并按 batch 复制;
  • query(内容查询)在num_patterns=0时初始化为全零张量,由解码器逐层生成;
  • with_random_refpoints=True,则对query_embedding做均匀分布初始化,并且冻结前两维(中心点坐标)不参与训练(见 init_weights)。

解码器的逐层锚框迭代

DABDetrTransformerDecoder.forward 完整实现了"动态锚框"的迭代过程:

  1. 锚框 → 位置编码:将当前参考点reference_points(sigmoid 归一化的锚框)通过coordinate_to_encoding转为正弦位置编码ref_sine_embed,再经ref_point_headMLP 得到 query 位置嵌入;
  2. 内容查询缩放:除第一层外,用query_scaleMLP 从内容查询output生成逐元素变换系数pos_transformation调制位置编码(即query_scale_type='cond_elewise'的含义);
  3. 宽高调制:启用with_modulated_hw_attn时,ref_anchor_head预测相对宽高比ref_hw,分别对位置编码的前后半部分按ref_hw[...,1]/obj_center[...,3]ref_hw[...,0]/obj_center[...,2]缩放,从而让注意力感知目标形状;
  4. 层内更新:解码层输出经reg_branches(即检测头fc_reg)预测增量,与当前参考点相加后过 sigmoid 得到新的锚框;该新锚框作为下一层的query_pos输入,实现逐层迭代精修(iterative refinement)。值得注意的是,reference_points在层间传递时执行了.detach(),防止梯度跨层传播。

检测头的残差式框预测

DABDETRHead.forward 展示了最终的预测逻辑:分类分支fc_cls输出类别分数;回归分支先将参考锚框做inverse_sigmoid逆变换,与 MLP 预测的残差相加后再 sigmoid,得到归一化的 (cx, cy, w, h) 坐标。每个解码层都会产出一组预测(return_intermediate=True时共 6 组),全部参与损失计算。该头还覆写了predict方法以支持测试阶段仅取最后一层输出进行后处理。

编码器中的位置缩放

值得注意的细节是,DAB-DETR 的编码器 DABDetrTransformerEncoder 也不是标准实现:每层在自注意力前会用可学习的query_scaleMLP 对位置编码做逐元素缩放(query_pos * pos_scales),这是论文中提升收敛速度的配套设计之一。

模型结果与预训练权重

MMDetection 官方提供了 DAB-DETR 的 COCO 检测结果,记录于 configs/dab_detr/metafile.yml:

Backbone模型训练计划box AP配置文件
R-50DAB-DETR50e42.3config

元数据信息还显示:

  • 训练数据:COCO;训练技术:AdamW、多尺度训练、梯度裁剪;
  • 训练资源:8× A100 GPU;架构:ResNet + Transformer;
  • 实现版本:对应 MMDetection v3.0.0rc6 的 dab_detr.py 实现。

预训练权重与训练日志由 OpenMMLab 官方托管,可通过 metafile 中的Weights字段获取(dab-detr_r50_8xb2-50e_coco_20221122_120837-c1035c8c.pth),用于直接微调或离线推理。

训练与推理实操

在 MMDetection v3.x 中,训练 DAB-DETR 直接使用仓库自带的训练脚本,8 卡分布式训练可执行:

bash tools/dist_train.sh configs/dab_detr/dab-detr_r50_8xb2-50e_coco.py 8

单卡训练则运行python tools/train.py configs/dab_detr/dab-detr_r50_8xb2-50e_coco.py。注意配置中auto_scale_lr默认关闭,直接沿用 lr=1e-4 即可;若需以其他 batch size 训练,可参考该字段的基准 batch size 16 手动换算学习率。

推理与评估使用统一的测试脚本:

python tools/test.py configs/dab_detr/dab-detr_r50_8xb2-50e_coco.py \ /path/to/dab-detr_r50_8xb2-50e_coco.pth \ --out results.pkl --eval bbox

此外,DAB-DETR 作为标准注册模型,也可直接配合 demo/image_demo.py 对单张图片做可视化推理:

python demo/image_demo.py demo/demo.jpg \ configs/dab_detr/dab-detr_r50_8xb2-50e_coco.py \ /path/to/dab-detr_r50_8xb2-50e_coco.pth

总结

DAB-DETR 通过将解码器查询显式化为动态锚框,用坐标先验与逐层迭代精修解决了 DETR 收敛慢的痛点,其"查询即锚框、锚框即查询"的设计思想深刻影响了后续 Conditional DETR、DN-DETR、DINO 等系列工作。在 MMDetection 中,DAB-DETR 的实现与配置高度模块化——从DABDETR检测器、DABDETRHead头部到DABDetrTransformerDecoder层,每个组件均可独立复用与定制。读者若想进一步探索,可以重点对比 conditional_detr_head.py(DAB-DETR 头部的父类实现)与 dab_detr_layers.py 中的coordinate_to_encodinginverse_sigmoid等工具函数,从而把握 DETR 系列 query 设计的演进脉络。

引用

若在学术工作中使用 DAB-DETR,请按论文作者提供的 BibTeX 引用(原始出处见 configs/dab_detr/README.md):

@inproceedings{ liu2022dabdetr, title={{DAB}-{DETR}: Dynamic Anchor Boxes are Better Queries for {DETR}}, author={Shilong Liu and Feng Li and Hao Zhang and Xiao Yang and Xianbiao Qi and Hang Su and Jun Zhu and Lei Zhang}, booktitle={International Conference on Learning Representations}, year={2022}, url={https://openreview.net/forum?id=oMI9PjOb9Jl} }

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

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

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

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

立即咨询