首页
/ Deformable DETR 完全指南:基于可变形注意力的高效目标检测与 Transformer 实现解析

Deformable DETR 完全指南:基于可变形注意力的高效目标检测与 Transformer 实现解析

2026-09-07 17:35:31作者:齐冠琰

本指南以 Deformable DETR 模型文档 为核心主线,结合 🤗 Transformers 仓库中 deformable_detr 模块的完整源码(模型实现、配置类、图像处理器与测试用例),系统讲解 Deformable DETR 的核心原理、AutoModel/Pipeline 实战调用、关键配置项语义、底层多尺度可变形注意力实现、两阶段与边界框迭代精修等高级训练选项。读者完成后将能使用 DeformableDetrForObjectDetection 完成开箱即用的目标检测推理,理解其与 DETR 的本质差异,并具备基于 DeformableDetrConfig 自定义训练配置的能力。

Deformable DETR 是什么:从 DETR 的收敛瓶颈说起

Deformable DETR(原论文发表于 2020 年 10 月 8 日,于 2022 年 9 月 14 日由 nielsr 贡献进入本仓库)是原始 DETR 的直接后继模型。正如其模型文档开篇所概括的:

Deformable DETR 通过在模型中引入可变形注意力模块(deformable attention module)改进原版 DETR——该机制只选择性地关注每个参考点(reference point)周围的一小簇关键采样点,从而提升训练速度并改善检测精度

原版 DETR 的注意力在整张特征图上进行全局密集交互,收敛慢、对特征分辨率敏感;Deformable DETR 则将注意力限定在采样点上,使模型可以同时聚合多个尺度的特征,这是其在检测精度与收敛效率上取得双重提升的根本原因。

在 Hugging Face 生态中,官方权重由 SenseTime(商汤)组织发布,仓库内所有公开可用的 Deformable DETR checkpoint 均可在 SenseTime 组织下找到,例如最常用的 SenseTime/deformable-detr

从代码库整体归属看,Deformable DETR 的实现被组织在 src/transformers/models/deformable_detr 目录下,共包含以下核心文件:

文件 职责
configuration_deformable_detr.py 定义 DeformableDetrConfig 配置类,约 30 个可调超参数
modeling_deformable_detr.py 约 1700 行的 PyTorch 模型实现,含全部网络子模块与两个顶层入口模型
image_processing_deformable_detr.py Torchvision 后端的 DeformableDetrImageProcessor
image_processing_pil_deformable_detr.py PIL 后端的 DeformableDetrImageProcessorPil
convert_deformable_detr_to_pytorch.py 将原版(SenseTime 官方)权重转换为 Transformers 格式的脚本
modular_deformable_detr.py 模型生成的 modular 源文件
__init__.py 模块公开导出

两种最简上手方式:Pipeline 与 AutoModel

文档给出了两条并行的推理路径,二者都可在拿到一张 COCO 样图后立即输出检测框。

方式一:Pipeline 一行代码

from transformers import pipeline

pipeline = pipeline(
    "object-detection",
    model="SenseTime/deformable-detr",
    device_map=0
)

pipeline("http://images.cocodataset.org/val2017/000000039769.jpg")

device_map=0 会把模型放置到 GPU 0 上。Hugging Face 的 pipeline 框架会自动完成图像下载/加载、预处理、前向推理与后处理(NMS 与反归一化坐标)的串联,适用于快速验证效果。

方式二:AutoModel 手动控制全流程

当需要精细控制每个环节时,推荐使用 AutoImageProcessor + AutoModelForObjectDetection 的组合,它也是后续做自定义数据集微调的基础写法:

import requests
import torch
from PIL import Image

from transformers import AutoImageProcessor, AutoModelForObjectDetection


url = "http://images.cocodataset.org/val2017/000000039769.jpg"
image = Image.open(requests.get(url, stream=True).raw)

image_processor = AutoImageProcessor.from_pretrained("SenseTime/deformable-detr")
model = AutoModelForObjectDetection.from_pretrained("SenseTime/deformable-detr", device_map="auto")

# prepare image for the model
inputs = image_processor(images=image, return_tensors="pt").to(model.device)

with torch.no_grad():
    outputs = model(**inputs)

results = image_processor.post_process_object_detection(outputs, target_sizes=torch.tensor([image.size[::-1]]), threshold=0.3)

for result in results:
    for score, label_id, box in zip(result["scores"], result["labels"], result["boxes"]):
        score, label = score.item(), label_id.item()
        box = [round(i, 2) for i in box.tolist()]
        print(f"{model.config.id2label[label]}: {score:.2f} {box}")

上述代码的每一步都对应一条关键调用链,下面逐一拆解其内部机制:

  1. image_processor(images=image, return_tensors="pt") 会执行 resize → rescale → normalize → pad(并生成 pixel_mask,返回的 dict 包含 pixel_valuespixel_mask 两个键(见 image_processing_deformable_detr.pymodel_input_names = ["pixel_values", "pixel_mask"])。
  2. model(**inputs)DeformableDetrForObjectDetection.forward,内部输出 logits 与归一化的预测框 pred_boxes(格式为 (center_x, center_y, width, height),值域 [0,1],相对于单张原图而非 batch 内 padding)。
  3. post_process_object_detection(outputs, target_sizes=..., threshold=0.3) 负责把归一化坐标还原为 Pascal VOC 格式的绝对像素坐标 (xmin, ymin, xmax, ymax),并在做框解码的同时过滤低置信度结果。

模型自带的 docstring 示例运行后(threshold=0.5)会输出类似的结果:

Detected cat with confidence 0.8 at location [16.5, 52.84, 318.25, 470.78]
Detected cat with confidence 0.789 at location [342.19, 24.3, 640.02, 372.25]
Detected remote with confidence 0.633 at location [40.79, 72.78, 176.76, 117.25]

顶层模型与输出结构

deformable_detr 模块暴露了两个可直接实例化的顶层入口模型,分别对应「纯 Transformer 编码器-解码器」和「带检测头的完整目标检测模型」两种粒度。

DeformableDetrModel:编码器-解码器主干

DeformableDetrModel 由「骨干网络 + 编码器-解码器 Transformer」构成,职责是把图像编码为可供后续任务头使用的 query 表征。其 forward 输出类型为 DeformableDetrModelOutput(定义见 modeling_deformable_detr.py),关键字段包括:

  • last_hidden_state:解码器最后一层输出的 (batch, num_queries, hidden_size) 隐状态;
  • init_reference_points:送入解码器的初始参考点 (batch, num_queries, 4)
  • intermediate_hidden_states / intermediate_reference_points:逐层解码器输出及其参考点的堆叠结果,用于辅助损失;
  • 仅当 with_box_refine=Truetwo_stage=True 时才返回的 enc_outputs_classenc_outputs_coord_logits:两阶段模式下第一阶段的区域提议(region proposal)得分与坐标 logits。

此外它还透传 encoder_*decoder_*cross_attentions 等用于可视化与调试的标准字段。

DeformableDetrForObjectDetection:目标检测完整模型

DeformableDetrForObjectDetection(源码见 modeling_deformable_detr.py)在 DeformableDetrModel 之上叠加了分类头与回归头。从实现细节看:

  • 每个解码器层都配有一组独立的检测头num_pred = decoder_layers + 1(若为两阶段,额外一层用于区域提议生成),否则等于 decoder_layers
  • class_embed 是一组线性层,把 d_model 维隐状态映射为 num_labels 维分类 logits;
  • bbox_embed 是一组 DeformableDetrMLPPredictionHead——一个 3 层的简单 MLP(结构见 DeformableDetrMLPPredictionHead),输出 4 维框回归量;
  • 权重共享的细节值得注意:当 with_box_refine=Truemodel.decoder.bbox_embed 会直接绑定到检测头,当 two_stage=Truemodel.decoder.class_embed 也会被绑定(见 _tied_weights_keys__init__ 中的赋值逻辑),这是权重能紧凑保存的原因。

forward 主流程为:

  1. 调用 DeformableDetrModel 获得每层隐状态与参考点;
  2. 对参考点做 inverse_sigmoid 反变换,将每层隐状态经对应检测头产出「框修正量 delta_bbox + 参考点」的 logits,再经 sigmoid 得到归一化坐标;
  3. 取最后一层结果作为 logitspred_boxes
  4. 若提供了 labels,则计算二分图匹配损失并返回 lossloss_dict 与逐层 auxiliary_outputs

输出类型为 DeformableDetrObjectDetectionOutput源码定义),其中:

  • logits:形状 (batch, num_queries, num_classes + 1),最后一维的 +1 表示「无目标」类别;
  • pred_boxes:归一化的 (center_x, center_y, width, height) 坐标;
  • loss / loss_dict:仅在传入 labels 时出现。总损失是「类别预测的负对数似然」与「框回归 L1 损失 + 尺度不变的广义 IoU(GIoU)损失」的线性组合;
  • auxiliary_outputs:仅当 config.auxiliary_loss=True 且提供 labels 时返回,包含每个解码器层的 logits/pred_boxes,供辅助损失使用。

forward 的完整参数语义

DeformableDetrForObjectDetection.forward 接受以下输入参数(均可查阅方法签名):

  • pixel_values(必填):预处理后的像素张量;
  • pixel_mask:padding 掩码,标注哪些位置是真实图像内容;
  • decoder_attention_mask:形状 (batch, num_queries),默认不用,可用于屏蔽部分 object queries;
  • encoder_outputs:可传入预先计算好的编码器输出以跳过编码器;
  • inputs_embeds:可选,绕过「骨干 + 投影层」直接传入展平的特征图嵌入;
  • decoder_inputs_embeds:可选,绕过「零初始化 query」直接传入查询嵌入;
  • labels:长度为 batch_size 的 dict 列表,每个 dict 至少包含 class_labels(该图所有 GT 框类别,torch.LongTensor)与 boxes(形状 (num_boxes, 4)torch.FloatTensor)。这是训练/微调阶段计算二分图匹配损失所必需的。

DeformableDetrConfig:核心配置逐项解读

配置类 DeformableDetrConfig(见 configuration_deformable_detr.py)继承自 PreTrainedConfig,其 model_type = "deformable_detr",并预设了完整的默认参数集合。下表汇总了与 Deformable DETR 架构强相关、且带有官方 docstring 的核心参数:

参数 默认值 语义
num_queries 300 object queries 数量,即单个图像可检测的最大目标数;若 two_stage=True 则由 two_stage_num_proposals 取代
num_feature_levels 4 输入多尺度特征的层数(配合骨干不同 stage 输出)
encoder_n_points 4 编码器中每个注意力头、每个特征层采样的 key 数
decoder_n_points 4 解码器中每个注意力头、每个特征层采样的 key 数
two_stage False 是否启用两阶段模式:由 Deformable DETR 的一个变体先产生区域提议,再送入解码器做迭代框精修
two_stage_num_proposals 300 两阶段模式下生成的区域提议数
with_box_refine False 是否启用迭代框精修:每个解码器层基于上一层预测继续修正边界框
position_embedding_type "sine" 图像特征上叠加的位置编码类型,可选 "sine""learned"
return_intermediate True 是否返回解码器各中间层状态
dilation False 是否在最后一个卷积块中用膨胀卷积替换 stride(即 DC5 设置),仅在使用 timm 骨干时支持
disable_custom_kernels False 是否禁用自定义 CUDA/CPU kernel(ONNX 导出时必须置为 True,因为 PyTorch ONNX 导出不支持自定义 kernel)

除此之外,配置类还包含一组与模型结构相关的超参数与损失/匹配超参数:

  • 结构类num_channels=3max_position_embeddings=1024encoder_layers=6encoder_ffn_dim=1024encoder_attention_heads=8decoder_layers=6decoder_ffn_dim=1024decoder_attention_heads=8d_model=256dropout=0.1attention_dropout=0.0activation_dropout=0.0encoder_layerdrop=0.0activation_function="relu"init_std=0.02init_xavier_std=1.0
  • 损失与匹配类:二分图匹配代价权重 class_cost=1bbox_cost=5giou_cost=2;损失系数 bbox_loss_coefficient=5giou_loss_coefficient=2mask_loss_coefficient=1dice_loss_coefficient=1(用于分割/全景扩展场景)、无目标类别权重 eos_coefficient=0.1、focal 损失 focal_alpha=0.25
  • 其他is_encoder_decoder=Trueauxiliary_loss=Falsetie_word_embeddings=True

为兼容下游框架,配置类还维护了属性映射:hidden_size → d_modelnum_attention_heads → encoder_attention_heads(见 attribute_map),所以用「标准名」访问这两个属性也能正确落到实际字段。

骨干网络配置与架构合法性校验

DeformableDetrConfig.__post_init__ 负责骨干网络初始化:当未显式指定 backbone_config 时,会以 resnet50 为默认骨干并仅取 stage4 输出特征(见 default_config_kwargs={"out_features": ["stage4"]});而多尺度特征来自 timm 骨干的 out_indices=[2, 3, 4](当 num_feature_levels > 1 时)。若启用 dilation,则额外设置 output_stride=16

配置对象还实现了 validate_architecture() 的约束校验:

if self.two_stage is True and self.with_box_refine is False:
    raise ValueError("If two_stage is True, with_box_refine must be True.")

也就是说,两阶段模式必须搭配迭代框精修,这是一个硬性架构约束,若违反会在加载时报错。

实例化方式与任何预训练模型一致:

from transformers import DeformableDetrConfig, DeformableDetrModel

# 使用默认结构初始化随机权重模型
configuration = DeformableDetrConfig()
model = DeformableDetrModel(configuration)
configuration = model.config

图像处理器:Torchvision 与 PIL 两种后端

文档中将 DeformableDetrImageProcessorDeformableDetrImageProcessorPil 并列列出,二者提供同一套 preprocesspost_process_object_detection API,只是底层图像张量后端不同(前者基于 Torchvision/tvF,后者基于 PIL/numpy)。它们的类属性默认值如下(见 image_processing_deformable_detr.py):

  • size = {"shortest_edge": 800, "longest_edge": 1333}:按最长边不超过 1333、最短边不超过 800 的规则等比缩放(保持宽高比);
  • resample = PILImageResampling.BILINEAR
  • image_mean / image_std:ImageNet 默认均值/方差([0.485, 0.456, 0.406] / [0.229, 0.224, 0.225]);
  • do_resize = Truedo_rescale = Truedo_normalize = Truedo_pad = True:默认四步全开;
  • format = AnnotationFormat.COCO_DETECTION:默认按 COCO Detection 注释格式处理;
  • default_to_square = False:不做正方形填充。

其中值得重点说明的两点是:

  1. resize 的 size 参数支持三种形态{"height", "width"}(精确缩放)、{"shortest_edge", "longest_edge"}(保比例缩放)、{"max_height", "max_width"}(限高限宽),可据任务自行选择;
  2. pad 与 pixel_maskDeformableDetrImageProcessor 默认 do_pad=True(构造时也会把历史参数 pad_and_return_pixel_mask 转写为 do_pad 以保持向后兼容)。pad 会把 batch 内图像统一到同一尺寸,并同步输出 pixel_mask——这正是该模型 model_input_names = ["pixel_values", "pixel_mask"] 的原因:编码器需要 mask 来区分真实内容与 padding 区域。

对于微调任务,处理器还实现了 prepare_annotation 等方法,支持把 COCO 的 polygon 分割标注转成 mask、再由 mask 推导边界框(masks_to_boxes),并可处理全景分割(panoptic)标注——这部分能力在 tests/models/deformable_detr/test_image_processing_deformable_detr.py 中由 @slow 标记的 test_call_pytorch_with_coco_detection_annotationstest_batched_coco_panoptic_annotations 等用例加以验证。

源码级原理:从网络结构到多尺度可变形注意力

为了讲透“可变形注意力为何更快更准”,下面沿 modeling_deformable_detr.py 的模块顺序还原完整的模型流水线。

骨干与批归一化冻结

  • DeformableDetrFrozenBatchNorm2d:把 BatchNorm2d 的 batch 统计量与仿射参数全部固定(见 源码),这是目标检测迁移训练中常见的冻结 BN 技巧;
  • replace_batch_norm(model):递归把普通 BN 替换为冻结 BN;
  • DeformableDetrConvEncoder:负责把骨干输出的多尺度特征做 1x1 通道投影并统一到 d_model 维度,同时加入位置编码与层级嵌入,为编码器准备输入。

位置编码

  • DeformableDetrSinePositionEmbedding:sine/cosine 绝对位置编码,对应 position_embedding_type="sine"
  • DeformableDetrLearnedPositionEmbedding:可学习的相对位置编码,对应 position_embedding_type="learned"

可变形注意力的两种落地形态

  1. MultiScaleDeformableAttention源码):对外暴露统一的算子接口,类上标注了 @use_kernel_forward_from_hub("MultiScaleDeformableAttention")——在可用时它会把前向计算委托给从 Hub 加载的自定义 CUDA/CPU kernel(即 disable_custom_kernels 开关所控制的加速路径),这也是 ONNX 导出必须先置 disable_custom_kernels=True 的原因。它的 eager 实现本质上是一个「按层采样 + 加权聚合」过程:把各层 value 特征与采样网格重组后,用 nn.functional.grid_sample(..., mode="bilinear", padding_mode="zeros") 在每个参考点周围的双线性采样点位置取值,再按注意力权重加权求和;
  2. DeformableDetrSelfAttention / DeformableDetrMultiscaleDeformableAttention:前者提供 eager 的普通自注意力实现(eager_attention_forward),后者是封装好的多尺度可变形注意力模块,供编码器层/解码器层使用。每个层级的采样点数由 encoder_n_pointsdecoder_n_points 控制(默认各 4 个)。

正是因为“只在参考点周围采样少量 key、且跨 num_feature_levels 个尺度同时采样”,可变形注意力大幅削减了注意力矩阵的计算量,同时天然获得多尺度特征聚合能力——这正是其相对原版 DETR 训练收敛更快、精度更高的根源(模型文档中明确表述为 “improves training speed and improves accuracy”)。

编码器与解码器

  • 编码器:DeformableDetrEncoderLayer 由「多尺度可变形自注意力 + FFN」组成,6 层堆叠为 DeformableDetrEncoder。层类继承自 GradientCheckpointingLayer,天然支持梯度检查点;
  • 解码器:DeformableDetrDecoderLayer 交互方式为「可变形自注意力 → 可变形交叉注意力(以编码器特征为 value)→ FFN」,DeformableDetrDecoder 会为每层维护参考点。DeformableDetrDecoderOutput 额外携带 intermediate_hidden_statesintermediate_reference_points,正是文档 docstring 中所述“每层输出过一遍 layernorm 后的中间激活堆叠”,为辅助损失提供了逐层监督信号;
  • 框回归的最后一步:回归头输出的是参考点的增量(残差),代码中先将参考点做 inverse_sigmoid 反变换,累加增量后再 sigmoid 归一化,得到稳定的 (cx, cy, w, h) 预测。

进阶:两阶段、框精修与训练损失

two_stage 与 with_box_refine

这两个开关是官方 checkpoint 家族差异的主要来源,也对应文档模型列表中最常见的几个变体:

  • with_box_refine=True 时,每个解码器层的预测框都以上一层的框为基准继续精修(解码器内共享 bbox_embed);
  • two_stage=True 时(必须同时开启 with_box_refine),编码器输出会先被用于生成 top-k 区域提议(enc_outputs_class 做前景/背景二分类、enc_outputs_coord_logits 出坐标),这些提议再作为解码器 query 的初始化参考点,构成“检测器提议 + Transformer 解码器精修”的两阶段流水线。

对应测试覆盖可见 tests/models/deformable_detr/test_modeling_deformable_detr.py 中的 test_two_stage_trainingtest_inference_object_detection_head_with_box_refine_two_stage,它们验证了这两条训练路径的可执行性。

训练损失与匹配机制

模型前向传入 labels 后即进入训练模式,损失计算由 loss_function 完成,要点如下:

  • 采用二分图匹配(bipartite matching)为每个 GT 框分配唯一的预测 query,匹配代价由 class_costbbox_costgiou_cost 三者的加权和决定;
  • 框损失为 L1 损失 + GIoU 损失的线性组合,对应配置中的 bbox_loss_coefficientgiou_loss_coefficient;分类损失则使用带 focal_alpha=0.25 的 focal 风格损失来缓解正负样本不平衡;
  • 类别 logits 的最后一维是「no-object」槽位,其权重由 eos_coefficient=0.1 控制;
  • auxiliary_loss=True(或解码器输出中间状态)时,每个解码器层都会贡献辅助损失,从而让梯度更好地流经深层堆叠结构。

自定义数据集推理与微调的实践建议

  • 推理调优:框解码阈值由 post_process_object_detectionthreshold 参数控制(默认 0.5,官方示例常取 0.3),分数过滤也可放在后处理阶段完成;target_sizes 必须传原图尺寸([height, width]),后处理才能把归一化框还原为像素坐标。
  • 类别适配num_queries 对应单图最大可检测目标数,若你的场景单图目标密集超过 300,需要相应调大 num_queries。类别标签通过 model.config.id2label / label2id 维护,微调新数据集时需同步更新这两份映射与 num_labels
  • 训练/微调资源:微调通常以官方 COCO 预训练 checkpoint 为起点;在本仓库中做训练态验证时,可以直接参考模型测试(如 test_deformable_detr_modeltest_inference_object_detection_head),它们以小规模输入跑通了完整前向。
  • ONNX/部署:若需导出 ONNX,务必在配置中置 disable_custom_kernels=True(配置 docstring 明确说明自定义 CUDA kernel 不被 PyTorch ONNX 导出支持)。

关键源码与测试索引

想要继续深挖的读者,可以按下面索引直接阅读仓库内的原始材料:

小结

Deformable DETR 在 🤗 Transformers 中的落地体现了“经典论文 → 工程化组件”的完整路径:AutoImageProcessor/Pipeline 让推理在几行代码内完成;DeformableDetrConfig 把两阶段、框精修、多尺度采样点数、各类损失权重等约 30 个超参数全部参数化并内置架构合法性校验;MultiScaleDeformableAttention 提供了可选的 Hub 自定义 kernel 加速路径,同时保留 eager 双线性采样实现供可移植场景使用。无论是拿官方 COCO checkpoint 直接做目标检测,还是在自定义数据集上开启 auxiliary_losswith_box_refinetwo_stage 进行微调,这套实现都能提供从预处理、模型前向到后处理、损失计算的端到端支持。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
858
1.35 K
docsdocs
暂无描述
Markdown
899
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
923
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.83 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
532
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
524
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
393