Deformable DETR 完全指南:基于可变形注意力的高效目标检测与 Transformer 实现解析
本指南以 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}")
上述代码的每一步都对应一条关键调用链,下面逐一拆解其内部机制:
image_processor(images=image, return_tensors="pt")会执行 resize → rescale → normalize → pad(并生成pixel_mask),返回的 dict 包含pixel_values与pixel_mask两个键(见 image_processing_deformable_detr.py 中model_input_names = ["pixel_values", "pixel_mask"])。model(**inputs)走DeformableDetrForObjectDetection.forward,内部输出 logits 与归一化的预测框pred_boxes(格式为(center_x, center_y, width, height),值域 [0,1],相对于单张原图而非 batch 内 padding)。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=True且two_stage=True时才返回的enc_outputs_class、enc_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=True时model.decoder.bbox_embed会直接绑定到检测头,当two_stage=True时model.decoder.class_embed也会被绑定(见_tied_weights_keys与__init__中的赋值逻辑),这是权重能紧凑保存的原因。
其 forward 主流程为:
- 调用
DeformableDetrModel获得每层隐状态与参考点; - 对参考点做
inverse_sigmoid反变换,将每层隐状态经对应检测头产出「框修正量delta_bbox+ 参考点」的 logits,再经sigmoid得到归一化坐标; - 取最后一层结果作为
logits与pred_boxes; - 若提供了
labels,则计算二分图匹配损失并返回loss、loss_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=3、max_position_embeddings=1024、encoder_layers=6、encoder_ffn_dim=1024、encoder_attention_heads=8、decoder_layers=6、decoder_ffn_dim=1024、decoder_attention_heads=8、d_model=256、dropout=0.1、attention_dropout=0.0、activation_dropout=0.0、encoder_layerdrop=0.0、activation_function="relu"、init_std=0.02、init_xavier_std=1.0; - 损失与匹配类:二分图匹配代价权重
class_cost=1、bbox_cost=5、giou_cost=2;损失系数bbox_loss_coefficient=5、giou_loss_coefficient=2、mask_loss_coefficient=1、dice_loss_coefficient=1(用于分割/全景扩展场景)、无目标类别权重eos_coefficient=0.1、focal 损失focal_alpha=0.25; - 其他:
is_encoder_decoder=True、auxiliary_loss=False、tie_word_embeddings=True。
为兼容下游框架,配置类还维护了属性映射:hidden_size → d_model、num_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 两种后端
文档中将 DeformableDetrImageProcessor 与 DeformableDetrImageProcessorPil 并列列出,二者提供同一套 preprocess 与 post_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 = True、do_rescale = True、do_normalize = True、do_pad = True:默认四步全开;format = AnnotationFormat.COCO_DETECTION:默认按 COCO Detection 注释格式处理;default_to_square = False:不做正方形填充。
其中值得重点说明的两点是:
- resize 的
size参数支持三种形态:{"height", "width"}(精确缩放)、{"shortest_edge", "longest_edge"}(保比例缩放)、{"max_height", "max_width"}(限高限宽),可据任务自行选择; - pad 与 pixel_mask:
DeformableDetrImageProcessor默认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_annotations、test_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"。
可变形注意力的两种落地形态
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")在每个参考点周围的双线性采样点位置取值,再按注意力权重加权求和;DeformableDetrSelfAttention/DeformableDetrMultiscaleDeformableAttention:前者提供 eager 的普通自注意力实现(eager_attention_forward),后者是封装好的多尺度可变形注意力模块,供编码器层/解码器层使用。每个层级的采样点数由encoder_n_points与decoder_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_states与intermediate_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_training 与 test_inference_object_detection_head_with_box_refine_two_stage,它们验证了这两条训练路径的可执行性。
训练损失与匹配机制
模型前向传入 labels 后即进入训练模式,损失计算由 loss_function 完成,要点如下:
- 采用二分图匹配(bipartite matching)为每个 GT 框分配唯一的预测 query,匹配代价由
class_cost、bbox_cost、giou_cost三者的加权和决定; - 框损失为 L1 损失 + GIoU 损失的线性组合,对应配置中的
bbox_loss_coefficient与giou_loss_coefficient;分类损失则使用带focal_alpha=0.25的 focal 风格损失来缓解正负样本不平衡; - 类别 logits 的最后一维是「no-object」槽位,其权重由
eos_coefficient=0.1控制; - 当
auxiliary_loss=True(或解码器输出中间状态)时,每个解码器层都会贡献辅助损失,从而让梯度更好地流经深层堆叠结构。
自定义数据集推理与微调的实践建议
- 推理调优:框解码阈值由
post_process_object_detection的threshold参数控制(默认0.5,官方示例常取0.3),分数过滤也可放在后处理阶段完成;target_sizes必须传原图尺寸([height, width]),后处理才能把归一化框还原为像素坐标。 - 类别适配:
num_queries对应单图最大可检测目标数,若你的场景单图目标密集超过 300,需要相应调大num_queries。类别标签通过model.config.id2label/label2id维护,微调新数据集时需同步更新这两份映射与num_labels。 - 训练/微调资源:微调通常以官方 COCO 预训练 checkpoint 为起点;在本仓库中做训练态验证时,可以直接参考模型测试(如
test_deformable_detr_model、test_inference_object_detection_head),它们以小规模输入跑通了完整前向。 - ONNX/部署:若需导出 ONNX,务必在配置中置
disable_custom_kernels=True(配置 docstring 明确说明自定义 CUDA kernel 不被 PyTorch ONNX 导出支持)。
关键源码与测试索引
想要继续深挖的读者,可以按下面索引直接阅读仓库内的原始材料:
- 模型文档: docs/source/en/model_doc/deformable_detr.md(可与姊妹模型文档 DETR 对照阅读,理解“全局注意力 vs 可变形采样”的差异)
- 模型实现: src/transformers/models/deformable_detr/modeling_deformable_detr.py
- 配置实现: src/transformers/models/deformable_detr/configuration_deformable_detr.py
- 图像预处理: image_processing_deformable_detr.py 与 image_processing_pil_deformable_detr.py
- 权重转换脚本: src/transformers/models/deformable_detr/convert_deformable_detr_to_pytorch.py(面向希望从 SenseTime 官方权重自行转换的开发者)
- 模型测试: tests/models/deformable_detr/test_modeling_deformable_detr.py
- 图像处理器测试: tests/models/deformable_detr/test_image_processing_deformable_detr.py
小结
Deformable DETR 在 🤗 Transformers 中的落地体现了“经典论文 → 工程化组件”的完整路径:AutoImageProcessor/Pipeline 让推理在几行代码内完成;DeformableDetrConfig 把两阶段、框精修、多尺度采样点数、各类损失权重等约 30 个超参数全部参数化并内置架构合法性校验;MultiScaleDeformableAttention 提供了可选的 Hub 自定义 kernel 加速路径,同时保留 eager 双线性采样实现供可移植场景使用。无论是拿官方 COCO checkpoint 直接做目标检测,还是在自定义数据集上开启 auxiliary_loss、with_box_refine 与 two_stage 进行微调,这套实现都能提供从预处理、模型前向到后处理、损失计算的端到端支持。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00