📌 系统梳理DETR系列5年间12+篇里程碑论文,每篇均包含:背景动机 → 创新点详表 → 技术深度解读 → 代码示意
📋 目录
- 一、前DETR时代:问题与动机
- 二、DETR系列完整演化时间线
- [三、DETR(ECCV 2020)](#三、DETR(ECCV 2020))
- [四、Deformable DETR(ICLR 2021)](#四、Deformable DETR(ICLR 2021))
- [五、Conditional DETR(ICCV 2021)](#五、Conditional DETR(ICCV 2021))
- [六、Anchor DETR(AAAI 2022)](#六、Anchor DETR(AAAI 2022))
- [七、DAB-DETR(ICLR 2022)](#七、DAB-DETR(ICLR 2022))
- [八、DN-DETR(CVPR 2022)](#八、DN-DETR(CVPR 2022))
- [九、Sparse DETR(ICLR 2022)](#九、Sparse DETR(ICLR 2022))
- [十、DINO(ICLR 2023)](#十、DINO(ICLR 2023))
- 十一、RT-DETR(百度,2023)
- [十二、D-FINE(CVPR 2024)](#十二、D-FINE(CVPR 2024))
- [十三、DEIM(CVPR 2025)](#十三、DEIM(CVPR 2025))
- 十四、技术演进脉络与传承关系
- 十五、性能对比总表
- 十六、未来展望
一、前DETR时代:问题与动机
1.1 目标检测的两大范式
2020年之前,目标检测被两大范式统治:
| 范式 | 代表方法 | 核心流程 | 典型速度 |
|---|---|---|---|
| 两阶段 | Faster R-CNN, Cascade R-CNN | RPN生成候选 → ROI Align → 分类回归 | 5-10 FPS |
| 单阶段 | YOLO, SSD, RetinaNet, FCOS | 直接在特征图上预测框和类别 | 30-60 FPS |
1.2 共同痛点
| 痛点 | 具体表现 | 为什么是问题 |
|---|---|---|
| Anchor设计 | 需要手工设定anchor尺寸(32/64/128等)和比例(1:1, 1:2, 2:1) | 不同数据集最优anchor不同,需要反复调参 |
| NMS后处理 | 非极大值抑制(IoU阈值0.5)去除重复框 | 不可微,无法端到端训练;阈值需手工设定 |
| 正负样本分配 | IoU>0.5为正样本,<0.4为负样本 | 阈值选择影响巨大;不同尺度分配不均 |
| 流程碎片化 | Backbone、Neck、Head各自独立 | 无法全局联合优化 |
| 泛化差 | 依赖anchor的统计先验 | 对罕见形状/尺度适应性差 |
1.3 Transformer的启示
2017年Transformer论文("Attention Is All You Need")和2020年ViT(Vision Transformer)的成功表明:
- 自注意力机制天然适合建模全局依赖关系
- 无需手工设计的归纳偏置(如卷积核形状、anchor尺寸)
- 序列到序列的映射天然适合集合预测问题
💡 核心矛盾:检测流程中充满"不可微"的人工设计(anchor、NMS、IoU阈值),无法实现真正的端到端学习。能否用Transformer彻底取代这些手工组件?
二、DETR系列完整演化时间线
2017 ★ Transformer (Vaswani et al., NeurIPS)
│
2020 ★ ViT (Dosovitskiy et al., ICLR 2021)
│
2020.05 ★★★ DETR (Carion et al., ECCV 2020)
│ → 开天辟地:端到端集合预测
│ → 问题:收敛慢(500ep),小目标差,计算量大
│
2021.01 ★★★ Deformable DETR (Zhu et al., ICLR 2021)
│ → 10x训练加速,多尺度特征
│
2021.03 ★★ Efficient DETR (Xiong et al., arXiv)
│ → 密集先验初始化,Decoder层数减少
│
2021.07 ★★★ Conditional DETR (Meng et al., ICCV 2021)
│ → 条件交叉注意力,50ep收敛
│
2022.01 ★★ Anchor DETR (Fang et al., AAAI 2022)
│ → 锚点替代可学习Query
│
2022.01 ★★★ DAB-DETR (Liu et al., ICLR 2022)
│ → 动态锚框即Query
│
2022.01 ★★ Sparse DETR (Kim et al., ICLR 2022)
│ → 稀疏更新Encoder
│
2022.03 ★★★ DN-DETR (Li et al., CVPR 2022)
│ → 去噪训练加速收敛
│
2023.01 ★★★ DINO (Zhang et al., ICLR 2023)
│ → 集大成者:对比去噪+混合查询+LFT
│
2023.04 ★★★ RT-DETR (Lv et al., 百度)
│ → 首个实时DETR,超越YOLO
│
2024.10 ★★★ D-FINE (Peng et al., CVPR 2024)
│ → 分布回归重定义
│
2025.02 ★★★ DEIM (Huang et al., CVPR 2025)
│ → 密集匹配+MAL
│
▼ 未来方向
三、DETR(ECCV 2020)------ 开天辟地
📄 论文信息
| 项目 | 内容 |
|---|---|
| 标题 | End-to-End Object Detection with Transformers |
| 作者 | Nicolas Carion, Francisco Massa, Gabriel Synnaeve, Nicolas Usunier, Alexander Kirillov, Sergey Zagoruyko |
| 机构 | Facebook AI Research (FAIR) |
| 会议 | ECCV 2020 |
| 代码 | github.com/facebookresearch/detr |
3.1 背景与动机
为什么需要DETR?
| 现有方法的问题 | DETR的解决思路 |
|---|---|
| Anchor需要手工设计(尺寸、比例、数量) | 完全去除anchor,用可学习Query替代 |
| NMS后处理不可微,需手工设阈值 | 用二分图匹配实现一对一分配,无需NMS |
| 正负样本分配规则复杂(IoU阈值) | 匈牙利匹配自动完成最优分配 |
| 检测流程碎片化,各组件独立优化 | 统一为Transformer端到端训练 |
| 数据增强依赖(随机裁剪、翻转等) | 全局注意力天然建模上下文,减少增强依赖 |
为什么选择集合预测?
核心洞察 :目标检测的本质是"给定一张图,输出一个无序的目标集合"。这与Transformer的序列到序列映射天然契合------Decoder的每个Query负责预测集合中的一个元素。
3.2 创新点详表
| # | 创新名称 | 具体内容 | 针对的问题 | 作用/效果 |
|---|---|---|---|---|
| 1 | 集合预测框架 | 将检测重新定义为集合预测问题:输入图像→输出固定大小的预测集合 | 传统检测需要anchor+NMS的碎片化流程 | 消除所有手工组件,实现真正端到端 |
| 2 | 二分图匹配损失 | 用匈牙利算法在预测和GT之间做最优一对一匹配 | NMS不可微,无法参与反向传播 | 可微的分配策略,全局最优匹配 |
| 3 | Object Queries | 100个可学习的嵌入向量作为Decoder输入,每个Query负责预测一个目标 | 需要一种方式让模型"主动寻找"目标 | 替代anchor,无需空间先验假设 |
| 4 | Transformer架构用于检测 | 将Encoder-Decoder结构引入检测:Encoder建模全局上下文,Decoder生成目标预测 | CNN感受野有限,难以建模长距离依赖 | 全局注意力捕获图像级上下文 |
| 5 | 辅助损失 | Decoder每层都计算检测损失(共6层×损失) | 深层网络梯度消失,浅层得不到有效监督 | 加速收敛,稳定训练 |
| 6 | 位置编码 | 正弦/余弦位置编码 + 可学习位置编码 | Transformer本身无序,需要空间信息 | 让模型感知特征的空间位置 |
3.3 架构详解
┌─────────────────────────────────────────────────────────────────┐
│ DETR 完整架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 输入图像 [B, 3, H, W] │
│ │ │
│ ▼ │
│ ┌──────────────────────┐ │
│ │ CNN Backbone │ ResNet-50 (去掉最后的FC和GAP) │
│ │ (特征提取) │ 输出: [B, 2048, H/32, W/32] │
│ └──────────┬───────────┘ │
│ │ 1×1卷积降维 │
│ ▼ │
│ ┌──────────────────────┐ │
│ │ 降维到 d_model=256 │ [B, 256, H/32, W/32] │
│ └──────────┬───────────┘ │
│ │ Flatten + 位置编码 │
│ ▼ │
│ ┌──────────────────────────────────────────┐ │
│ │ Transformer Encoder (6层) │ │
│ │ • Multi-Head Self-Attention (8头) │ │
│ │ • FFN (256→1024→256) │ │
│ │ • 对所有HW个token做全局注意力 │ │
│ │ 输出: [B, HW, 256] │ │
│ └──────────────────┬───────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────┐ │
│ │ Transformer Decoder (6层) │ │
│ │ 输入: 100个Object Queries [100, 256] │ │
│ │ • Self-Attention (Query之间) │ │
│ │ • Cross-Attention (Query→Encoder输出) │ │
│ │ • FFN │ │
│ │ 输出: [6, B, 100, 256] (每层都有输出) │ │
│ └──────────────────┬───────────────────────┘ │
│ │ │
│ ┌───────────┴───────────┐ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 分类头 (FFN) │ │ 回归头 (MLP) │ │
│ │ → 类别+背景 │ │ → (cx,cy,w,h)│ │
│ │ [B,100,92] │ │ [B,100,4] │ │
│ └─────────────┘ └─────────────┘ │
│ │
│ 损失计算: │
│ 1. 匈牙利匹配: pred ↔ GT 一对一分配 │
│ 2. 分类损失: Focal Loss / CE │
│ 3. 回归损失: L1 + GIoU │
│ 4. 辅助损失: 每层Decoder都计算 │
│ │
└─────────────────────────────────────────────────────────────────┘
3.4 关键技术深度解读
① 二分图匹配(Hungarian Matching)
为什么需要?
- 预测有100个框,GT可能有10个目标
- 需要决定"哪个预测对应哪个GT"
- 传统方法用IoU阈值,但不可微
- 匈牙利算法找到全局最优的一对一分配
匹配代价 :
L m a t c h = − 1 { c i ≠ ∅ } p i ( c i ) + 1 { c i ≠ ∅ } λ L 1 L L 1 + λ g i o u L g i o u \mathcal{L}{match} = -\mathbb{1}{\{c_i \neq \varnothing\}} p_i(c_i) + \mathbb{1}_{\{c_i \neq \varnothing\}} \\lambda_{L1} \\mathcal{L}_{L1} + \\lambda_{giou} \\mathcal{L}_{giou} Lmatch=−1{ci=∅}pi(ci)+1{ci=∅}λL1LL1+λgiouLgiou
python
# 匈牙利匹配伪代码
def hungarian_matching(pred_class, pred_box, gt_class, gt_box):
N_pred, N_gt = len(pred_class), len(gt_box)
# 构建代价矩阵 [N_pred, N_gt]
cost_matrix = torch.zeros(N_pred, N_gt)
for i in range(N_pred):
for j in range(N_gt):
cost_class = -pred_class[i, gt_class[j]] # 分类代价
cost_l1 = F.l1_loss(pred_box[i], gt_box[j]) # L1代价
cost_giou = 1 - generalized_iou(pred_box[i], gt_box[j]) # GIoU代价
cost_matrix[i, j] = cost_class + 5*cost_l1 + 2*cost_giou
# 匈牙利算法求最优分配
row_ind, col_ind = scipy.optimize.linear_sum_assignment(cost_matrix.numpy())
return row_ind, col_ind
② Object Queries
为什么用100个Query?
- 一张图最多约100个目标(COCO统计)
- 每个Query是一个256维可学习向量
- Query之间通过Self-Attention交互,避免重复预测
Query的语义:
- 训练初期:Query是随机的,无明确含义
- 训练后期:不同Query逐渐"专精"于不同区域/尺度/类别
- 但本质上仍是黑盒(这是后续工作的改进方向)
3.5 核心代码
python
import torch
import torch.nn as nn
import torch.nn.functional as F
from scipy.optimize import linear_sum_assignment
class DETR(nn.Module):
def __init__(self, backbone, num_classes=91, num_queries=100, d_model=256):
super().__init__()
self.backbone = backbone # ResNet-50
self.input_proj = nn.Conv2d(2048, d_model, 1) # 降维
# Transformer
self.encoder = TransformerEncoder(d_model, nhead=8, num_layers=6)
self.decoder = TransformerDecoder(d_model, nhead=8, num_layers=6)
# Object Queries
self.query_embed = nn.Embedding(num_queries, d_model)
# 预测头
self.class_head = nn.Linear(d_model, num_classes + 1) # +1 for 背景
self.bbox_head = MLP(d_model, d_model, 4, num_layers=3)
def forward(self, images):
# 1. Backbone提取特征
features = self.backbone(images) # [B, 2048, H/32, W/32]
features = self.input_proj(features) # [B, 256, H/32, W/32]
# 2. Flatten + 位置编码
B, C, H, W = features.shape
features = features.flatten(2).permute(0, 2, 1) # [B, HW, 256]
pos = positional_encoding(H, W, 256) # [HW, 256]
# 3. Encoder: 全局上下文建模
memory = self.encoder(features + pos) # [B, HW, 256]
# 4. Decoder: Query与特征交互
queries = self.query_embed.weight.unsqueeze(0).expand(B, -1, -1)
hs = self.decoder(queries, memory, pos) # [6, B, 100, 256]
# 5. 预测
outputs_class = self.class_head(hs) # [6, B, 100, 92]
outputs_bbox = self.bbox_head(hs).sigmoid() # [6, B, 100, 4]
return outputs_class, outputs_bbox
class HungarianMatcher(nn.Module):
"""匈牙利匹配器"""
def __init__(self, cost_class=1.0, cost_bbox=5.0, cost_giou=2.0):
super().__init__()
self.cost_class = cost_class
self.cost_bbox = cost_bbox
self.cost_giou = cost_giou
@torch.no_grad()
def forward(self, outputs, targets):
"""
outputs: dict with 'pred_logits' [B, N, C] and 'pred_boxes' [B, N, 4]
targets: list of dict with 'labels' [M] and 'boxes' [M, 4]
"""
B, N = outputs['pred_logits'].shape[:2]
indices = []
for b in range(B):
# 分类代价
out_prob = outputs['pred_logits'][b].softmax(-1) # [N, C]
tgt_ids = targets[b]['labels'] # [M]
cost_class = -out_prob[:, tgt_ids] # [N, M]
# L1代价
out_bbox = outputs['pred_boxes'][b] # [N, 4]
tgt_bbox = targets[b]['boxes'] # [M, 4]
cost_bbox = torch.cdist(out_bbox, tgt_bbox, p=1) # [N, M]
# GIoU代价
cost_giou = -generalized_box_iou(
box_cxcywh_to_xyxy(out_bbox),
box_cxcywh_to_xyxy(tgt_bbox)
) # [N, M]
# 总代价
C = (self.cost_class * cost_class +
self.cost_bbox * cost_bbox +
self.cost_giou * cost_giou)
# 匈牙利算法
row_ind, col_ind = linear_sum_assignment(C.cpu().numpy())
indices.append((torch.tensor(row_ind), torch.tensor(col_ind)))
return indices
3.6 存在的问题(后续工作的出发点)
| 问题 | 具体表现 | 数据支撑 |
|---|---|---|
| 收敛极慢 | 需要500个epoch才能收敛(YOLO只需300) | COCO训练需~10天(8×V100) |
| 小目标差 | AP_small远低于Faster R-CNN | AP_small: 19.6 vs 21.4 |
| 计算量大 | Encoder对所有HW个token做全局注意力 | O((H×W)²)复杂度 |
| Query黑盒 | 100个Query无可解释的几何含义 | 难以调试和优化 |
| 低分辨率 | 只用stride=32的特征 | 小目标信息丢失严重 |
四、Deformable DETR(ICLR 2021)------ 10倍加速
📄 论文信息
| 项目 | 内容 |
|---|---|
| 标题 | Deformable DETR: Deformable Transformers for End-to-End Object Detection |
| 作者 | Xizhou Zhu, Weijie Su, Lewei Lu, Bin Li, Xiaogang Wang, Jifeng Dai |
| 机构 | 商汤科技 + 中科大 + 港中文 |
| 会议 | ICLR 2021 |
| 代码 | github.com/fundamentalvision/Deformable-DETR |
4.1 背景与动机
为什么需要改进DETR?
| DETR的问题 | 根本原因 | 本文解决思路 |
|---|---|---|
| 收敛慢(500ep) | Encoder全局注意力计算量大,梯度传播路径长 | 稀疏注意力:每个Query只关注少量采样点 |
| 小目标差 | 只用stride=32的单尺度特征 | 多尺度特征融合 |
| 计算量O(N²) | 所有token两两交互 | 可变形机制:只采样K=4个点 |
为什么选择"可变形"?
灵感来源:Deformable Convolution (Dai et al., 2017)。可变形卷积通过可学习的偏移量让卷积核自适应感受野形状。同理,让注意力机制的"关注位置"也可学习。
关键洞察:检测任务中,一个Query通常只需要关注目标附近的少量位置,不需要看整张图。将O(N²)的全局注意力降为O(N×K)的稀疏注意力。
4.2 创新点详表
| # | 创新名称 | 具体内容 | 针对的问题 | 作用/效果 |
|---|---|---|---|---|
| 1 | 可变形注意力机制 | 每个Query只在K个可学习采样点上做注意力,而非所有位置 | 全局注意力O(N²)计算量太大 | 复杂度从O(N²)降为O(N×K),K=4 |
| 2 | 多尺度可变形注意力 | 在4个尺度的特征图上分别采样,每个尺度K个点 | 单尺度特征无法同时处理大小目标 | 小目标AP提升3.6 |
| 3 | 参考点机制 | 每个Query有一个2D参考点,采样点围绕参考点分布 | 需要给稀疏采样一个空间锚定 | 提供空间先验,稳定训练 |
| 4 | 迭代框精炼 | 每层Decoder输出框坐标,作为下一层的参考点 | 单层预测精度不够 | 类似Cascade,逐层精炼 |
| 5 | Encoder移除Self-Attention | Encoder只保留FFN,去掉Self-Attention | Encoder计算量大但收益有限 | 进一步减少计算量 |
4.3 关键技术深度解读
① 可变形注意力公式
标准注意力:
Attn ( q ) = ∑ i = 1 N A i ⋅ W x i , A i = exp ( q ⋅ W x i ) ∑ j exp ( q ⋅ W x j ) \text{Attn}(q) = \sum_{i=1}^{N} A_i \cdot W x_i, \quad A_i = \frac{\exp(q \cdot W x_i)}{\sum_j \exp(q \cdot W x_j)} Attn(q)=i=1∑NAi⋅Wxi,Ai=∑jexp(q⋅Wxj)exp(q⋅Wxi)
可变形注意力:
DeformAttn ( q , p , x ) = ∑ m = 1 M W m ∑ k = 1 K A m k ⋅ W m ′ x ( p + Δ p m k ) \text{DeformAttn}(q, p, x) = \sum_{m=1}^{M} W_m \sum_{k=1}^{K} A_{mk} \cdot W'm x(p + \Delta p{mk}) DeformAttn(q,p,x)=m=1∑MWmk=1∑KAmk⋅Wm′x(p+Δpmk)
其中:
- q q q:Query向量
- p p p:参考点坐标(归一化到0,1)
- Δ p m k \Delta p_{mk} Δpmk:第m个head第k个采样点的可学习偏移
- A m k A_{mk} Amk:注意力权重(Softmax归一化)
- K = 4 K=4 K=4:每个head的采样点数
- M M M:注意力头数
复杂度对比:
- 标准注意力: O ( N 2 ⋅ C ) O(N^2 \cdot C) O(N2⋅C),N=HW
- 可变形注意力: O ( N ⋅ K ⋅ C ) O(N \cdot K \cdot C) O(N⋅K⋅C),K=4 << N
② 多尺度机制
特征金字塔:
Level 0: stride 8, 尺寸 100×133 (小目标)
Level 1: stride 16, 尺寸 50×67 (中目标)
Level 2: stride 32, 尺寸 25×34 (大目标)
Level 3: stride 64, 尺寸 13×17 (超大目标)
每个Query的采样:
4个尺度 × 每个尺度4个采样点 = 16个采样点
(vs 标准注意力的 100×133=13300个位置)
③ 参考点与迭代精炼
python
# 初始参考点:由Query通过线性层预测
reference_points = linear(query_embed).sigmoid() # [B, N_q, 2]
# 每层Decoder后更新参考点
for layer in decoder_layers:
output = layer(query, reference_points, features)
# 预测框偏移
delta_bbox = bbox_head(output)
# 更新参考点(逆sigmoid变换)
reference_points = inverse_sigmoid(sigmoid(reference_points) + delta_bbox)
4.4 核心代码
python
class DeformableAttention(nn.Module):
"""多尺度可变形注意力"""
def __init__(self, d_model=256, n_heads=8, n_levels=4, n_points=4):
super().__init__()
self.n_heads = n_heads
self.n_levels = n_levels
self.n_points = n_points
# 采样偏移预测: 每个head每个level每个point有2D偏移
self.sampling_offsets = nn.Linear(
d_model, n_heads * n_levels * n_points * 2)
# 注意力权重预测
self.attention_weights = nn.Linear(
d_model, n_heads * n_levels * n_points)
# 值投影
self.value_proj = nn.Linear(d_model, d_model)
self.output_proj = nn.Linear(d_model, d_model)
# 初始化:偏移为零(初始等价于标准注意力在参考点处)
nn.init.constant_(self.sampling_offsets.weight, 0)
nn.init.constant_(self.sampling_offsets.bias, 0)
def forward(self, query, reference_points, value, spatial_shapes, level_start_index):
"""
query: [B, N_q, C]
reference_points: [B, N_q, n_levels, 2] 归一化坐标
value: [B, sum(H_l*W_l), C] 多尺度特征拼接
spatial_shapes: [(H_0,W_0), (H_1,W_1), ...] 各尺度尺寸
"""
B, N_q, _ = query.shape
# 1. 预测采样偏移
offsets = self.sampling_offsets(query)
offsets = offsets.view(B, N_q, self.n_heads, self.n_levels, self.n_points, 2)
# 2. 计算采样位置 = 参考点 + 偏移
# 偏移需要按特征图尺寸归一化
sampling_locations = reference_points[:, :, None, :, None, :] # [B,Nq,1,L,1,2]
sampling_locations = sampling_locations + offsets / spatial_shapes # 归一化偏移
# 3. 注意力权重
weights = self.attention_weights(query)
weights = weights.view(B, N_q, self.n_heads, self.n_levels * self.n_points)
weights = F.softmax(weights, dim=-1)
weights = weights.view(B, N_q, self.n_heads, self.n_levels, self.n_points)
# 4. 双线性插值采样(CUDA实现)
# 对每个采样位置,在value中做双线性插值
output = multi_scale_deformable_attn_core(
value, spatial_shapes, sampling_locations, weights)
return self.output_proj(output)
class DeformableDETR(nn.Module):
def __init__(self, num_classes=91, num_queries=300):
super().__init__()
self.backbone = ResNet50()
self.neck = nn.ModuleList([
nn.Sequential(nn.Conv2d(512, 256, 1), nn.GroupNorm(32, 256)),
nn.Sequential(nn.Conv2d(1024, 256, 1), nn.GroupNorm(32, 256)),
nn.Sequential(nn.Conv2d(2048, 256, 1), nn.GroupNorm(32, 256)),
])
# 添加第四尺度
self.extra_level = nn.Sequential(
nn.Conv2d(256, 256, 3, stride=2, padding=1), nn.GroupNorm(32, 256))
self.encoder = DeformableTransformerEncoder(256, n_levels=4)
self.decoder = DeformableTransformerDecoder(256, n_levels=4)
self.query_embed = nn.Embedding(num_queries, 256)
self.reference_points = nn.Linear(256, 2)
self.class_head = nn.Linear(256, num_classes + 1)
self.bbox_head = MLP(256, 256, 4, 3)
def forward(self, images):
# 多尺度特征
features = self.backbone(images) # 3个尺度
features = [neck(f) for neck, f in zip(self.neck, features)]
features.append(self.extra_level(features[-1])) # 第4尺度
# Encoder(可变形自注意力)
memory = self.encoder(features)
# 参考点初始化
ref_points = self.reference_points(self.query_embed.weight).sigmoid()
# Decoder(可变形交叉注意力)
hs = self.decoder(self.query_embed.weight, ref_points, memory)
# 预测
out_class = self.class_head(hs)
out_bbox = self.bbox_head(hs).sigmoid()
return out_class, out_bbox
4.5 性能对比
| 模型 | Backbone | Epochs | AP | AP_small | 训练时间 |
|---|---|---|---|---|---|
| DETR | R50 | 500 | 42.0 | 19.6 | ~10天 |
| Deformable DETR | R50 | 50 | 43.8 | 27.1 | ~1天 |
| Deformable DETR (多尺度) | R50 | 50 | 46.2 | 28.8 | ~1.5天 |
| Deformable DETR (多尺度) | R50 | 12 | 41.7 | 23.4 | ~4小时 |
五、Conditional DETR(ICCV 2021)
📄 论文信息
| 项目 | 内容 |
|---|---|
| 标题 | Conditional DETR for Fast Training Convergence |
| 作者 | Depu Meng, Xiaokang Chen, Zejia Fan, Gang Zeng, Houqiang Li, Yuhui Yuan, Lei Sun, Jingdong Wang |
| 机构 | 中科大 + 微软亚洲研究院 |
| 会议 | ICCV 2021 |
5.1 背景与动机
为什么DETR收敛慢?
本文的核心分析 :DETR的交叉注意力需要同时学习两件事:
- 内容匹配:Query的语义和特征的内容是否匹配("这是不是一个目标")
- 空间定位:Query关注的位置是否包含目标("目标在哪里")
这两个任务耦合在一起,导致学习困难,收敛缓慢。
为什么用"条件"?
灵感 :条件生成(Conditional Generation)。如果Query的内容信息能条件化地生成空间查询,就能将两个任务解耦。
5.2 创新点详表
| # | 创新名称 | 具体内容 | 针对的问题 | 作用/效果 |
|---|---|---|---|---|
| 1 | 条件交叉注意力 | 将交叉注意力分解为内容部分和空间部分的乘积 | 内容和空间耦合导致收敛慢 | 50ep达到DETR 500ep精度 |
| 2 | 空间条件查询生成 | 从Query内容向量通过MLP生成空间查询向量 | Query缺乏明确的空间定位信号 | 空间定位更精准 |
| 3 | 解耦设计 | 内容注意力用Query内容,空间注意力用条件生成的向量 | 单一注意力难以同时优化两个目标 | 各部分独立优化,互不干扰 |
5.3 关键技术深度解读
标准DETR交叉注意力:
CrossAttn ( q , k , v ) = softmax ( q ⋅ k T d ) ⋅ v \text{CrossAttn}(q, k, v) = \text{softmax}\left(\frac{q \cdot k^T}{\sqrt{d}}\right) \cdot v CrossAttn(q,k,v)=softmax(d q⋅kT)⋅v
这里 q q q 同时承担了"找什么"和"在哪找"的角色。
Conditional DETR分解:
CondCrossAttn = ( W q c q ) ⋅ ( W k c k ) T ⏟ 内容匹配 ⊙ ( W q s q s p a t i a l ) ⋅ ( W k s k p o s ) T ⏟ 空间定位 \text{CondCrossAttn} = \underbrace{(W_q^c q) \cdot (W_k^c k)^T}{\text{内容匹配}} \odot \underbrace{(W_q^s q{spatial}) \cdot (W_k^s k_{pos})^T}_{\text{空间定位}} CondCrossAttn=内容匹配 (Wqcq)⋅(Wkck)T⊙空间定位 (Wqsqspatial)⋅(Wkskpos)T
其中 q s p a t i a l = MLP ( q c o n t e n t ) q_{spatial} = \text{MLP}(q_{content}) qspatial=MLP(qcontent) 是从内容条件生成的空间查询。
python
class ConditionalCrossAttention(nn.Module):
def __init__(self, d_model=256, n_heads=8):
super().__init__()
# 内容部分
self.q_content = nn.Linear(d_model, d_model)
self.k_content = nn.Linear(d_model, d_model)
# 空间部分
self.spatial_query_gen = MLP(d_model, d_model, d_model, 2) # 条件生成
self.q_spatial = nn.Linear(d_model, d_model)
self.k_spatial = nn.Linear(d_model, d_model) # 位置编码投影
self.v_proj = nn.Linear(d_model, d_model)
self.out_proj = nn.Linear(d_model, d_model)
def forward(self, query, key, value, pos_embed):
"""
query: [B, N_q, C] Object Query
key: [B, HW, C] Encoder输出
value: [B, HW, C] Encoder输出
pos_embed: [B, HW, C] 位置编码
"""
# 内容注意力
q_c = self.q_content(query) # [B, N_q, C]
k_c = self.k_content(key) # [B, HW, C]
attn_content = q_c @ k_c.transpose(-1, -2) # [B, N_q, HW]
# 空间条件查询
q_spatial = self.spatial_query_gen(query) # [B, N_q, C]
q_s = self.q_spatial(q_spatial) # [B, N_q, C]
k_s = self.k_spatial(pos_embed) # [B, HW, C]
attn_spatial = q_s @ k_s.transpose(-1, -2) # [B, N_q, HW]
# 逐元素相乘 → 联合注意力
attn = attn_content * attn_spatial
attn = attn.softmax(dim=-1)
# 加权求和
output = attn @ self.v_proj(value)
return self.out_proj(output)
5.4 效果
| 模型 | Epochs | AP |
|---|---|---|
| DETR | 500 | 42.0 |
| Conditional DETR | 50 | 43.0 |
| Conditional DETR | 108 | 44.0 |
六、Anchor DETR(AAAI 2022)
📄 论文信息
| 项目 | 内容 |
|---|---|
| 标题 | Anchor DETR: Query Design for Transformer-Based Object Detection |
| 作者 | Yingming Zheng, Xiangyu Zhang, Jian Sun |
| 机构 | 旷视科技 |
| 会议 | AAAI 2022 |
6.1 背景与动机
为什么需要改进Query设计?
| DETR Query的问题 | 具体表现 |
|---|---|
| 完全可学习,无空间先验 | 训练初期Query"不知道看哪里" |
| 黑盒,不可解释 | 无法知道每个Query负责什么区域 |
| 收敛慢 | 需要大量epoch才能学到有意义的空间分布 |
为什么用"锚点"?
核心思想 :与其让Query从零学习"看哪里",不如直接给它一个空间锚点作为先验。类似于Faster R-CNN的anchor,但更灵活。
6.2 创新点详表
| # | 创新名称 | 具体内容 | 针对的问题 | 作用/效果 |
|---|---|---|---|---|
| 1 | 锚点查询 | 在特征图上均匀放置锚点(如7×7=49个),每个锚点生成一个Query | Query缺乏空间先验 | 提供明确的空间位置信息 |
| 2 | 区域注意力 | 每个锚点Query只关注其附近区域(非全局) | 全局注意力计算量大 | 减少计算量,聚焦局部 |
| 3 | 多尺度锚点 | 不同尺度的特征图使用不同密度的锚点 | 单一密度无法适配多尺度目标 | 大目标用稀疏锚点,小目标用密集锚点 |
| 4 | 锚点偏移学习 | 锚点位置可微调(小范围偏移) | 固定网格可能错过目标中心 | 提高定位精度 |
6.3 核心代码
python
class AnchorQueryGenerator(nn.Module):
def __init__(self, num_anchors_per_level=[49, 25, 9], d_model=256):
super().__init__()
# 每个锚点生成Query向量
self.anchor_to_query = nn.Sequential(
nn.Linear(2, d_model), # (x, y) → Query
nn.ReLU(),
nn.Linear(d_model, d_model),
)
def generate_anchors(self, H, W, num_anchors):
"""在H×W特征图上均匀放置锚点"""
grid_h = torch.linspace(0.5/H, 1-0.5/H, int(num_anchors**0.5))
grid_w = torch.linspace(0.5/W, 1-0.5/W, int(num_anchors**0.5))
gy, gx = torch.meshgrid(grid_h, grid_w)
anchors = torch.stack([gx.flatten(), gy.flatten()], -1) # [N, 2]
return anchors
def forward(self, feature_shapes):
all_queries = []
for (H, W), num_a in zip(feature_shapes, self.num_anchors_per_level):
anchors = self.generate_anchors(H, W, num_a) # [N, 2]
queries = self.anchor_to_query(anchors) # [N, C]
all_queries.append(queries)
return torch.cat(all_queries, dim=0)
七、DAB-DETR(ICLR 2022)
📄 论文信息
| 项目 | 内容 |
|---|---|
| 标题 | DAB-DETR: Dynamic Anchor Boxes are Better Queries for DETR |
| 作者 | Shilong Liu, Feng Li, Hao Zhang, Xiao Yang, Xianbiao Qi, Hang Su, Jun Zhu, Lei Zhang |
| 机构 | 清华 + IDEA + 华为 |
| 会议 | ICLR 2022 |
7.1 背景与动机
为什么重新定义Query?
核心洞察 :DETR的Object Query本质上就是一个锚框(anchor box)!
- Anchor DETR用2D锚点 (x, y)
- 但检测需要4D信息 (x, y, w, h)
- 因此Query应该直接是4D动态锚框
为什么"动态"?
传统anchor是固定的,但DAB-DETR的锚框在每层Decoder后迭代更新,越来越精确。
7.2 创新点详表
| # | 创新名称 | 具体内容 | 针对的问题 | 作用/效果 |
|---|---|---|---|---|
| 1 | 4D锚框即Query | Query = (cx, cy, w, h),通过MLP投影为向量 | 2D锚点缺乏尺度信息 | 提供完整的几何先验 |
| 2 | 迭代框更新 | 每层Decoder输出框偏移,更新锚框坐标 | 单层预测精度不够 | 逐层精炼,类似Cascade R-CNN |
| 3 | 温度调制注意力 | 用锚框的w,h调制交叉注意力的温度 | 大目标和小目标需要不同的注意力范围 | 大目标关注更大区域 |
| 4 | 可解释性 | 每个Query有明确的几何含义 | DETR Query是黑盒 | 可可视化、可调试 |
7.3 核心代码
python
class DABQuery(nn.Module):
"""DAB-DETR: 动态锚框查询"""
def __init__(self, num_queries=300, d_model=256):
super().__init__()
# 可学习的4D锚框 (cx, cy, w, h)
self.anchor_boxes = nn.Parameter(torch.randn(num_queries, 4))
# 4D → Query向量的投影
self.box_proj = MLP(4, d_model, d_model, 3)
def forward(self):
boxes = self.anchor_boxes.sigmoid() # 归一化到[0,1]
queries = self.box_proj(boxes) # [N_q, C]
return queries, boxes
class DABDecoderLayer(nn.Module):
def __init__(self, d_model=256, n_heads=8):
super().__init__()
self.self_attn = nn.MultiheadAttention(d_model, n_heads)
self.cross_attn = nn.MultiheadAttention(d_model, n_heads)
self.ffn = nn.Sequential(nn.Linear(d_model, d_model*4), nn.ReLU(),
nn.Linear(d_model*4, d_model))
self.bbox_head = MLP(d_model, d_model, 4, 3)
def forward(self, query, anchor_boxes, memory, pos):
"""
query: [N_q, B, C]
anchor_boxes: [N_q, B, 4] 当前锚框
memory: [HW, B, C]
"""
# Self-Attention
query = self.self_attn(query, query, query)[0] + query
# Cross-Attention (用锚框位置调制)
# 温度调制: 大框→低温度→关注范围大
temperature = 1.0 / (anchor_boxes[:, :, 2:4].mean(-1, keepdim=True) + 1e-6)
query = self.cross_attn(query, memory + pos, memory)[0] + query
# FFN
query = self.ffn(query) + query
# 预测框偏移 → 更新锚框
delta_box = self.bbox_head(query) # [N_q, B, 4]
new_boxes = anchor_boxes + delta_box
new_boxes = new_boxes.sigmoid()
return query, new_boxes
八、DN-DETR(CVPR 2022)
📄 论文信息
| 项目 | 内容 |
|---|---|
| 标题 | DN-DETR: Accelerate DETR Training by Introducing Query DeNoising |
| 作者 | Feng Li, Hao Zhang, Shilong Liu, Jian Guo, Lionel M. Ni, Lei Zhang |
| 机构 | IDEA + 清华 + 港科大 |
| 会议 | CVPR 2022 |
8.1 背景与动机
为什么收敛仍然慢?
即使有了Deformable DETR,收敛仍需50 epochs。
本文分析 :根本原因是Decoder的二部图匹配不稳定。
- 训练初期,预测框和GT的匹配关系频繁变化
- Query不知道"该往哪个方向优化"
- 导致梯度信号噪声大,收敛慢
为什么用"去噪"?
灵感来源 :扩散模型(Diffusion Model)和去噪自编码器(DAE)。
如果给模型一个"带噪声的GT框"让它恢复,模型就能快速学会"目标长什么样、在哪里"。
这比从随机Query开始学习要容易得多。
8.2 创新点详表
| # | 创新名称 | 具体内容 | 针对的问题 | 作用/效果 |
|---|---|---|---|---|
| 1 | 去噪训练(DeNoising Training) | 训练时向Decoder输入带噪声的GT框作为额外Query | 匹配不稳定导致收敛慢 | 收敛速度提升4x (500→125ep) |
| 2 | 噪声框构造 | 对GT的类别和坐标分别加噪声:类别用随机替换,坐标用高斯扰动 | 需要构造有意义的"退化"样本 | 模型学会从退化状态恢复 |
| 3 | 去噪分支与检测分支并行 | 去噪Query和正常Object Query同时输入Decoder,但去噪Query不参与匹配 | 去噪不应干扰正常检测 | 推理时零开销 |
| 4 | 对比去噪(后续DINO扩展) | 同时加正噪声和负噪声形成对比 | 单一去噪信号不够丰富 | 减少重复预测 |
8.3 关键技术解读
python
class DNTraining:
"""DN-DETR去噪训练"""
def __init__(self, num_queries=100, noise_scale=0.2, num_dn_queries=100):
self.noise_scale = noise_scale
self.num_dn_queries = num_dn_queries
def create_noisy_queries(self, gt_boxes, gt_labels, num_gt):
"""
对GT加噪声,构造去噪Query
"""
# 重复GT多次,增加去噪样本
num_groups = self.num_dn_queries // num_gt
noisy_boxes = gt_boxes.repeat(num_groups, 1) # [num_dn, 4]
noisy_labels = gt_labels.repeat(num_groups) # [num_dn]
# 坐标噪声: 加高斯扰动
box_noise = torch.randn_like(noisy_boxes) * self.noise_scale
noisy_boxes = (noisy_boxes + box_noise).clamp(0, 1)
# 类别噪声: 随机替换为其他类别 (概率10%)
mask = torch.rand(len(noisy_labels)) < 0.1
noisy_labels[mask] = torch.randint(0, 91, (mask.sum(),))
return noisy_boxes, noisy_labels
def forward(self, decoder, object_queries, noisy_queries, memory):
"""
并行处理检测Query和去噪Query
"""
# 拼接: [N_obj + N_dn, B, C]
all_queries = torch.cat([object_queries, noisy_queries], dim=0)
# 共享Decoder
output = decoder(all_queries, memory)
# 分离
det_output = output[:len(object_queries)]
dn_output = output[len(object_queries):]
# 检测分支: 正常匈牙利匹配
# 去噪分支: 直接和对应GT计算损失(无需匹配)
return det_output, dn_output
8.4 效果
| 模型 | Epochs | AP | 训练加速 |
|---|---|---|---|
| DETR | 500 | 42.0 | 1x |
| Deformable DETR | 50 | 46.2 | 10x |
| DN-DETR | 50 | 46.0 | 10x |
| DN-DETR | 12 | 43.4 | 40x |
九、Sparse DETR(ICLR 2022)
📄 论文信息
| 项目 | 内容 |
|---|---|
| 标题 | Sparse DETR: Efficient End-to-End Object Detection with Learnable Sparsity |
| 作者 | Byeonghyun Kim, Byeongho Heo, Sangdoo Yun, Dongyoon Han, Jinsoo Choi, Sung Ju Hwang |
| 机构 | KAIST + NAVER AI Lab |
| 会议 | ICLR 2022 |
9.1 背景与动机
为什么Encoder计算量大?
DETR/Deformable DETR的Encoder对所有HW个token做Self-Attention。
但一张图中,真正包含目标的区域可能只占10-20% ,其余是背景。
对背景token做注意力是浪费算力。
为什么用"稀疏"?
核心思想:让模型自己学习"哪些token重要",只对重要token做更新。
9.2 创新点详表
| # | 创新名称 | 具体内容 | 针对的问题 | 作用/效果 |
|---|---|---|---|---|
| 1 | 可学习稀疏性 | 每个token学习一个显著性分数,只有Top-K个重要token被更新 | Encoder对所有token做注意力,浪费算力 | 计算量减少60% |
| 2 | 稀疏更新策略 | 重要token做Self-Attention更新,不重要token保持原样 | 全部更新不必要 | 精度不降,速度提升 |
| 3 | 显著性监督 | 用GT框生成显著性标签,监督稀疏预测 | 无监督的稀疏选择可能不准 | 稀疏选择更准确 |
9.3 核心代码
python
class SparseEncoder(nn.Module):
def __init__(self, d_model=256, n_heads=8, num_layers=6, keep_ratio=0.25):
super().__init__()
self.keep_ratio = keep_ratio # 保留25%的token
# 显著性预测头
self.importance_head = nn.Linear(d_model, 1)
# Encoder层
self.layers = nn.ModuleList([
EncoderLayer(d_model, n_heads) for _ in range(num_layers)
])
def forward(self, src, pos):
"""src: [B, HW, C]"""
B, N, C = src.shape
# 预测每个token的显著性
importance = self.importance_head(src).squeeze(-1) # [B, N]
# 选择Top-K重要token
K = int(N * self.keep_ratio)
_, top_indices = importance.topk(K, dim=-1) # [B, K]
# 只对重要token做Self-Attention
for layer in self.layers:
# 提取重要token
selected = torch.gather(src, 1, top_indices.unsqueeze(-1).expand(-1,-1,C))
# Self-Attention更新
updated = layer(selected, selected, selected)
# 写回
src.scatter_(1, top_indices.unsqueeze(-1).expand(-1,-1,C), updated)
return src
十、DINO(ICLR 2023)------ 集大成者
📄 论文信息
| 项目 | 内容 |
|---|---|
| 标题 | DINO: DETR with Improved DeNoising Anchor Boxes for End-to-End Object Detection |
| 作者 | Hao Zhang, Feng Li, Shilong Liu, Lei Zhang, Hang Su, Jun Zhu, Lionel M. Ni, Heung-Yeung Shum |
| 机构 | IDEA + 清华 + 微软 |
| 会议 | ICLR 2023 |
| 性能 | 12ep: 49.4 AP; 36ep(Swin-L): 63.2 AP |
10.1 背景与动机
为什么需要DINO?
到2022年底,DETR系列已有多个改进方向:
- 去噪训练(DN-DETR)→ 加速收敛
- 可变形注意力(Deformable DETR)→ 减少计算
- 锚框Query(DAB-DETR)→ 提供几何先验
- 条件注意力(Conditional DETR)→ 解耦内容和空间
DINO的目标 :将这些优点统一整合,并进一步创新。
三个核心问题:
- DN-DETR的去噪只用正样本,能否加入负样本形成对比?
- Query的内容和空间能否来自不同源?
- 能否用更好的层间监督信号?
10.2 创新点详表
| # | 创新名称 | 具体内容 | 针对的问题 | 作用/效果 |
|---|---|---|---|---|
| 1 | 对比去噪训练(CDN) | 对同一GT加两种不同程度的噪声:小噪声(正)和大噪声(负),形成对比学习 | DN-DETR只有正样本去噪,缺乏"什么是错误"的信号 | 减少重复预测,AP+1.2 |
| 2 | 混合查询选择(MQS) | Query的内容部分用可学习嵌入,空间部分从Encoder特征Top-K选取 | DAB-DETR的空间和内容耦合 | 内容灵活+空间精准,AP+0.8 |
| 3 | Look Forward Twice(LFT) | 用第l+1层的精炼框作为第l层的监督目标(停止梯度) | 每层独立用GT监督,浅层目标太难 | 提供更准确的梯度,AP+0.5 |
| 4 | 多尺度可变形注意力 | 继承Deformable DETR的多尺度稀疏注意力 | 计算效率 | 保持实时性 |
| 5 | 去噪框作为锚框初始化 | 去噪Query的框坐标用GT加噪生成,而非随机初始化 | 去噪Query需要合理的初始位置 | 去噪效果更好 |
10.3 关键技术深度解读
① 对比去噪训练(CDN)
python
class ContrastiveDeNoising:
def __init__(self, num_gt_max=100, num_dn_groups=5):
self.num_dn_groups = num_dn_groups
def create_contrastive_queries(self, gt_boxes, gt_labels):
"""
对每个GT创建正负两类去噪Query
"""
queries_positive = []
queries_negative = []
for _ in range(self.num_dn_groups):
# 正样本: 小噪声 → 接近GT
noise_pos = torch.randn_like(gt_boxes) * 0.05
boxes_pos = (gt_boxes + noise_pos).clamp(0, 1)
queries_positive.append((boxes_pos, gt_labels))
# 负样本: 大噪声 → 远离GT
noise_neg = torch.randn_like(gt_boxes) * 0.3
boxes_neg = (gt_boxes + noise_neg).clamp(0, 1)
# 类别也随机替换
labels_neg = torch.randint(0, 91, gt_labels.shape)
queries_negative.append((boxes_neg, labels_neg))
return queries_positive, queries_negative
def compute_dn_loss(self, pred_pos, pred_neg, gt_boxes, gt_labels):
"""
正样本: 恢复到GT → L1 + GIoU损失
负样本: 远离GT → 分类为"无目标"
"""
loss_pos = F.l1_loss(pred_pos['boxes'], gt_boxes) + \
(1 - generalized_iou(pred_pos['boxes'], gt_boxes)).mean()
loss_neg = F.cross_entropy(pred_neg['logits'],
torch.full_like(gt_labels, 91)) # 背景类
return loss_pos + loss_neg
② 混合查询选择(MQS)
python
class MixedQuerySelection(nn.Module):
def __init__(self, d_model=256, num_queries=900):
super().__init__()
# 内容部分: 可学习嵌入(学习"找什么")
self.content_embed = nn.Embedding(num_queries, d_model)
# 空间部分: 从Encoder特征中选Top-K位置
self.spatial_score = nn.Linear(d_model, 1)
def forward(self, encoder_output):
"""
encoder_output: [B, HW, C]
"""
B = encoder_output.shape[0]
# 内容Query: 可学习
content = self.content_embed.weight # [N_q, C]
content = content.unsqueeze(0).expand(B, -1, -1) # [B, N_q, C]
# 空间Query: 从Encoder选Top-K
scores = self.spatial_score(encoder_output).squeeze(-1) # [B, HW]
_, top_indices = scores.topk(self.num_queries, dim=-1) # [B, N_q]
# 取出对应位置作为空间参考点
spatial = torch.gather(encoder_output, 1,
top_indices.unsqueeze(-1).expand(-1,-1,encoder_output.shape[-1]))
# 混合: 内容可学习 + 空间数据驱动
query = content + spatial # [B, N_q, C]
return query, top_indices
③ Look Forward Twice(LFT)
python
class LookForwardTwice:
"""
标准DETR: 每层独立用GT计算损失
DINO LFT: 用第l+1层的框作为第l层的"更准目标"
"""
def compute_loss_with_lft(self, layer_outputs, gt_boxes):
"""
layer_outputs: list of [B, N_q, 4], 共L层
"""
total_loss = 0
for l in range(len(layer_outputs)):
if l == len(layer_outputs) - 1:
# 最后一层: 直接用GT
target = gt_boxes
else:
# 非最后层: 用下一层的预测作为target
target = layer_outputs[l + 1].detach() # 停止梯度!
loss_l = F.l1_loss(layer_outputs[l], target) + \
(1 - generalized_iou(layer_outputs[l], target)).mean()
total_loss += loss_l
return total_loss
10.4 性能
| 配置 | Backbone | Epochs | AP | AP_small |
|---|---|---|---|---|
| DINO | R50 | 12 | 49.4 | 32.3 |
| DINO | R50 | 24 | 50.4 | 33.4 |
| DINO | R50 | 36 | 50.9 | 33.7 |
| DINO | Swin-L | 36 | 63.2 | 46.0 |
十一、RT-DETR(百度,2023)------ 实时化落地
📄 论文信息
| 项目 | 内容 |
|---|---|
| 标题 | DETRs Beat YOLOs on Real-time Object Detection |
| 作者 | Wenyu Lv, Shangliang Xu, Yian Zhao, Guanzhong Wang, Junjun Wei, Cheng Cui, Yuning Du, Qingqing Dang, Yi Liu |
| 机构 | 百度PaddlePaddle |
| 时间 | 2023年4月 |
| 意义 | 首个在实时速度下超越YOLO的DETR |
11.1 背景与动机
为什么DETR之前不能实时?
| 瓶颈 | 原因 | 影响 |
|---|---|---|
| Encoder计算量大 | 多尺度特征间的注意力交互 | 占总计算量60%+ |
| Decoder层数多 | 需要6层迭代精炼 | 增加延迟 |
| 高分辨率输入 | 小目标需要高分辨率 | 计算量平方增长 |
为什么YOLO一直是实时代名词?
YOLO用纯CNN + 无注意力机制,计算效率高。但精度天花板受限于感受野和手工设计。
RT-DETR的目标:保留DETR的端到端优势,同时达到YOLO的速度。
11.2 创新点详表
| # | 创新名称 | 具体内容 | 针对的问题 | 作用/效果 |
|---|---|---|---|---|
| 1 | AIFI(Attention-based Intra-scale Feature Interaction) | 只在最高层(P5)做Self-Attention,低层不做 | Encoder计算量大 | 计算量减少70% |
| 2 | CCFF(CNN-based Cross-scale Feature Fusion) | 用卷积(非注意力)做跨尺度特征融合 | 跨尺度注意力太慢 | 速度提升3x,精度持平 |
| 3 | 灵活Decoder层数 | 推理时可调整Decoder层数(1-6层),无需重训练 | 不同硬件需要不同速度 | 速度-精度灵活权衡 |
| 4 | 辅助损失 | 每层Decoder都计算损失 | 加速训练收敛 | 训练更稳定 |
11.3 关键技术解读
AIFI:为什么只在P5做注意力?
实验发现:
- P5(20×20=400 token)做Self-Attention:效果好,计算量可接受
- P3(80×80=6400 token)做Self-Attention:计算量爆炸,收益微小
- P4(40×40=1600 token)做Self-Attention:性价比不高
结论:高层特征语义丰富,做注意力收益大;低层特征纹理为主,用卷积足够。
python
class AIFI(nn.Module):
"""只在最高层做Self-Attention"""
def __init__(self, d_model=256, n_heads=8):
super().__init__()
self.self_attn = nn.MultiheadAttention(d_model, n_heads)
self.ffn = nn.Sequential(
nn.Linear(d_model, d_model * 4), nn.GELU(),
nn.Linear(d_model * 4, d_model))
self.norm = nn.LayerNorm(d_model)
def forward(self, feat_p5):
"""feat_p5: [B, C, H, W], H=W=20"""
B, C, H, W = feat_p5.shape
x = feat_p5.flatten(2).permute(0, 2, 1) # [B, 400, C]
# Self-Attention
x = self.self_attn(x, x, x)[0] + x
x = self.ffn(x) + x
x = self.norm(x)
return x.permute(0, 2, 1).reshape(B, C, H, W)
class CCFF(nn.Module):
"""CNN跨尺度融合(替代注意力)"""
def __init__(self, d_model=256):
super().__init__()
self.fuse = nn.Sequential(
nn.Conv2d(d_model * 2, d_model, 3, padding=1),
nn.BatchNorm2d(d_model),
nn.SiLU(),
nn.Conv2d(d_model, d_model, 3, padding=1),
nn.BatchNorm2d(d_model),
nn.SiLU(),
)
def forward(self, feat_high, feat_low):
"""
feat_high: [B, C, H, W] 高层(语义)
feat_low: [B, C, 2H, 2W] 低层(细节)
"""
# 上采样高层
feat_up = F.interpolate(feat_high, size=feat_low.shape[2:], mode='bilinear')
# 拼接 + 卷积融合
fused = torch.cat([feat_up, feat_low], dim=1)
return self.fuse(fused)
11.4 性能
| 模型 | AP(COCO) | FPS(T4) | 参数量 | GFLOPs |
|---|---|---|---|---|
| YOLOv5-X | 50.7 | 136 | 87M | 206 |
| YOLOv8-X | 53.9 | 142 | 68M | 258 |
| RT-DETR-R50 | 53.1 | 108 | 42M | 136 |
| RT-DETR-X | 54.8 | 74 | 67M | 259 |
| RT-DETR-L | 53.0 | 145 | 32M | 110 |
关键结论:RT-DETR-L在速度(145 FPS)和精度(53.0 AP)上同时超越YOLOv8-X!
十二、D-FINE(CVPR 2024)------ 回归任务重定义
📄 论文信息
| 项目 | 内容 |
|---|---|
| 标题 | D-FINE: Redefine Regression Task in DETRs as Fine-grained Distribution Refinement |
| 作者 | Yansheng Peng, Jiawei Zhao, Haohang Lu, Zhan Wu, Shenghai Yuan, Yongjun Zhang, Shuicheng Yan |
| 机构 | 中科大 + 武汉大学 + Skywork AI |
| 会议 | CVPR 2024 |
12.1 背景与动机
为什么重新定义回归?
| 传统DETR回归 | 问题 |
|---|---|
| 直接预测4个坐标值 (cx, cy, w, h) | 单点预测无法表达不确定性 |
| L1 + GIoU损失 | 对离群值敏感,梯度不稳定 |
| 一次性预测 | 无法迭代精炼 |
灵感来源:DFL(Distribution Focal Loss)
GFL(Generalized Focal Loss, 2020)提出用离散分布 替代单点回归。
D-FINE将此思想引入DETR,并设计逐层迭代精炼机制。
12.2 创新点详表
| # | 创新名称 | 具体内容 | 针对的问题 | 作用/效果 |
|---|---|---|---|---|
| 1 | FDR(Fine-grained Distribution Refinement) | 将框回归定义为4条边距离的概率分布,逐层精炼 | 单点回归无法表达不确定性 | AP+1.0,回归更稳定 |
| 2 | GO-LSD(Global Optimal Localization Self-Distillation) | 用最后一层的最优分布蒸馏所有层 | 浅层缺乏准确监督 | 加速收敛,AP+0.5 |
| 3 | 迭代精炼机制 | 每层Decoder输出分布偏移,叠加到上一层 | 单层预测精度有限 | 逐层提升定位精度 |
| 4 | 轻量设计 | 保持RT-DETR的轻量架构,不增加推理开销 | 分布回归可能增加计算量 | 速度不降 |
12.3 关键技术解读
分布回归 vs 点回归
python
# 传统点回归
bbox = MLP(query) # → (cx, cy, w, h), 4个标量
# D-FINE分布回归
# 将框表示为4条边到中心点的距离: (left, top, right, bottom)
# 每条边用N个bin的概率分布表示
N_bins = 32 # 离散化bin数
dist_left = MLP(query) # → [N_bins] 概率分布, sum=1
dist_top = MLP(query) # → [N_bins]
dist_right = MLP(query) # → [N_bins]
dist_bottom = MLP(query) # → [N_bins]
# 期望值作为最终距离
left = (dist_left * torch.arange(N_bins)).sum()
top = (dist_top * torch.arange(N_bins)).sum()
# ... 类似得到right, bottom
# 转换为框
bbox = ltrb_to_cxcywh(left, top, right, bottom)
逐层精炼
python
class DFineDecoder(nn.Module):
def __init__(self, num_layers=6, n_bins=32):
super().__init__()
self.layers = nn.ModuleList([DecoderLayer() for _ in range(num_layers)])
self.dist_heads = nn.ModuleList([
nn.Linear(256, 4 * n_bins) for _ in range(num_layers)
])
def forward(self, query, memory):
# 初始分布: 均匀分布
dist = torch.ones(B, N_q, 4, N_bins) / N_bins
for l, (layer, head) in enumerate(zip(self.layers, self.dist_heads)):
query = layer(query, memory)
# 预测分布偏移
delta_dist = head(query).view(B, N_q, 4, N_bins)
# 叠加到当前分布 → 精炼
dist = F.softmax(dist + delta_dist, dim=-1)
return dist # 最终精炼后的分布
GO-LSD自蒸馏
python
class GOLSD:
"""全局最优定位自蒸馏"""
def compute_loss(self, layer_dists, gt_dist):
"""
layer_dists: list of [B, N_q, 4, N_bins], 共L层
gt_dist: [B, N_gt, 4, N_bins] GT的分布表示
"""
# 最后一层作为"全局最优"
best_dist = layer_dists[-1].detach() # 停止梯度
total_loss = 0
for l, dist_l in enumerate(layer_dists):
# 标准分布损失
loss_reg = F.cross_entropy(dist_l.view(-1, N_bins), gt_dist.view(-1))
# 自蒸馏损失: 向最优分布靠拢
loss_distill = F.kl_div(
dist_l.log(), best_dist, reduction='batchmean')
total_loss += loss_reg + 0.5 * loss_distill
return total_loss
12.4 性能
| 模型 | AP | FPS(T4) | 参数量 |
|---|---|---|---|
| RT-DETR-R50 | 53.1 | 108 | 42M |
| D-FINE-R50 | 54.1 | 112 | 42M |
| YOLOv8-X | 53.9 | 142 | 68M |
| D-FINE-X | 55.8 | 95 | 65M |
十三、DEIM(CVPR 2025)------ 匹配机制终极优化
📄 论文信息
| 项目 | 内容 |
|---|---|
| 标题 | DEIM: DETR with Improved Matching for Fast Convergence |
| 作者 | Tianhao Huang, Yuchen Yang, Xiangwen Deng, et al. |
| 会议 | CVPR 2025 |
13.1 背景与动机
为什么匹配是瓶颈?
| 问题 | 具体表现 | 影响 |
|---|---|---|
| O2O匹配太稀疏 | 10个目标 → 只有10个正样本Query获得有效梯度 | 290个Query全是负样本,学习信号弱 |
| 对比YOLO的O2M | YOLO每个目标有多个正样本anchor | YOLO监督信号密度是DETR的3-5倍 |
| 训练慢 | 稀疏监督导致收敛慢 | 需要更多epoch |
为什么不用O2M?
O2M(一对多匹配)会引入重复预测 问题,需要NMS后处理,违背DETR"无NMS"的设计哲学。
DEIM的思路 :保持O2O,但通过数据增强增加目标数量 + 匹配质量感知来解决稀疏问题。
13.2 创新点详表
| # | 创新名称 | 具体内容 | 针对的问题 | 作用/效果 |
|---|---|---|---|---|
| 1 | 密集O2O匹配 | 通过Mosaic/Mixup增加每张图的目标数量,从而增加正样本Query数 | O2O匹配监督信号太稀疏 | 正样本数量提升3-4倍 |
| 2 | MAL(Matchability-Aware Loss) | 根据匹配质量(IoU)动态调整损失权重 | 密集匹配引入低质量匹配,产生错误梯度 | 低质量匹配影响减小,AP+0.3 |
| 3 | 动态Query数量 | 根据目标数量动态调整活跃Query数 | 固定300个Query对少目标图浪费 | 计算效率提升 |
| 4 | 训练加速策略 | 结合去噪训练 + 密集匹配 | 综合加速 | 36ep达到72ep精度 |
13.3 关键技术解读
MAL:匹配质量感知损失
python
class MatchabilityAwareLoss(nn.Module):
"""
根据匹配质量动态加权损失
高质量匹配(IoU高) → 正常学习
低质量匹配(IoU低) → 降低权重
"""
def __init__(self, alpha=2.0):
super().__init__()
self.alpha = alpha
def forward(self, pred_boxes, gt_boxes, matched_indices):
# 计算匹配质量(IoU)
matched_pred = pred_boxes[matched_indices[0]]
matched_gt = gt_boxes[matched_indices[1]]
match_quality = box_iou(matched_pred, matched_gt) # [N_matched]
# 动态权重: 质量越高权重越大
weights = match_quality.pow(self.alpha) # IoU^α
weights = weights / weights.sum() * len(weights) # 归一化
# 加权损失
loss_l1 = F.l1_loss(matched_pred, matched_gt, reduction='none')
loss_giou = 1 - generalized_iou(matched_pred, matched_gt)
weighted_loss = (weights * (loss_l1.sum(-1) + loss_giou)).mean()
return weighted_loss
密集O2O:通过数据增强增加正样本
python
class DenseO2OTraining:
"""
核心思想: 通过Mosaic将4张图拼成1张
原来1张图10个目标 → 现在40个目标
正样本Query从10个增加到40个
"""
def __init__(self, num_queries=300):
self.num_queries = num_queries
def mosaic_augment(self, images, targets):
"""4图拼接"""
# 随机选择4张图
# 拼接为1张大图
# 目标数量变为4倍
# 正样本Query数量相应增加
pass
def compute_matching(self, pred_boxes, gt_boxes):
"""
目标多了 → 正样本多了 → 监督信号密集了
但仍保持O2O: 每个GT只匹配1个Query
"""
cost_matrix = compute_cost(pred_boxes, gt_boxes)
indices = linear_sum_assignment(cost_matrix)
return indices # 一对一,但正样本总数增加了
13.4 性能
| 模型 | Epochs | AP | 训练时间 |
|---|---|---|---|
| RT-DETR-R50 | 72 | 53.1 | ~2天 |
| DEIM-R50 | 36 | 53.4 | ~1天 |
| DEIM-R50 | 72 | 54.2 | ~2天 |
| DEIM-R18 | 36 | 47.2 | ~0.5天 |
十四、技术演进脉络与传承关系
14.1 按问题维度
┌─────────────────────────────────────────────────────────────────────────┐
│ DETR系列解决的问题演化 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 问题1: 端到端化(去除Anchor和NMS) │
│ └─ DETR (2020): 集合预测 + 匈牙利匹配 │
│ │
│ 问题2: 收敛太慢 (500 epochs) │
│ ├─ Deformable DETR (2021): 稀疏注意力 → 50 ep │
│ ├─ Conditional DETR (2021): 解耦注意力 → 50 ep │
│ ├─ DN-DETR (2022): 去噪训练 → 125 ep │
│ ├─ DINO (2023): 对比去噪+混合查询 → 12 ep │
│ └─ DEIM (2025): 密集匹配 → 36 ep (精度更高) │
│ │
│ 问题3: 计算量太大 │
│ ├─ Deformable DETR: 只采样K=4个点,O(N²)→O(NK) │
│ ├─ Sparse DETR: 只更新重要token │
│ └─ RT-DETR: AIFI(只在P5做注意力) + CCFF(卷积替代注意力) │
│ │
│ 问题4: Query设计不合理(黑盒) │
│ ├─ Conditional DETR: 分解内容/空间 │
│ ├─ Anchor DETR: 2D锚点提供空间先验 │
│ ├─ DAB-DETR: 4D动态锚框即Query │
│ └─ DINO: 混合查询(内容可学习+空间数据驱动) │
│ │
│ 问题5: 小目标性能差 │
│ ├─ Deformable DETR: 多尺度特征 │
│ ├─ DINO: 混合查询 + LFT │
│ └─ D-FINE: 细粒度分布回归 │
│ │
│ 问题6: 实时性不足 │
│ ├─ RT-DETR (2023): 首个实时DETR,超越YOLO │
│ ├─ D-FINE (2024): 更高效的回归,不增加推理开销 │
│ └─ DEIM (2025): 训练加速不增加推理开销 │
│ │
│ 问题7: 回归精度 │
│ ├─ DINO: LFT提供更准的层间监督 │
│ ├─ D-FINE: 分布回归 + 自蒸馏 │
│ └─ DEIM: MAL避免低质量匹配干扰 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
14.2 技术传承图
DETR (2020) ─── 开山之作
│
├─→ Deformable DETR (2021) ─── 稀疏注意力+多尺度
│ │
│ ├─→ DAB-DETR (2022) ─── 4D锚框Query
│ │ │
│ │ └─→ DINO (2023) ─── 对比去噪+混合查询+LFT
│ │ │
│ │ ├─→ RT-DETR (2023) ─── 实时化
│ │ │ │
│ │ │ ├─→ D-FINE (2024) ─── 分布回归
│ │ │ │
│ │ │ └─→ DEIM (2025) ─── 密集匹配+MAL
│ │ │
│ │ └─→ Grounding DINO ─── 开放词汇
│ │
│ └─→ Sparse DETR (2022) ─── 稀疏Encoder
│
├─→ Conditional DETR (2021) ─── 条件注意力
│ │
│ └─→ DINO (2023)
│
├─→ Anchor DETR (2022) ─── 锚点Query
│ │
│ └─→ DAB-DETR (2022)
│
└─→ DN-DETR (2022) ─── 去噪训练
│
└─→ DINO (2023) ─── 对比去噪
十五、性能对比总表
| 模型 | 年份 | 会议 | Backbone | Epochs | COCO AP | AP_small | FPS(T4) | 关键创新 |
|---|---|---|---|---|---|---|---|---|
| Faster R-CNN | 2015 | NeurIPS | R50+FPN | - | 40.2 | 21.4 | 8 | Anchor+RPN+NMS |
| YOLOv3 | 2018 | arXiv | Darknet53 | - | 33.0 | 18.3 | 45 | 单阶段 |
| DETR | 2020 | ECCV | R50 | 500 | 42.0 | 19.6 | 5 | 集合预测+二分匹配 |
| Deformable DETR | 2021 | ICLR | R50 | 50 | 46.2 | 28.8 | 8 | 可变形注意力+多尺度 |
| Conditional DETR | 2021 | ICCV | R50 | 50 | 43.0 | 23.5 | 7 | 条件交叉注意力 |
| Anchor DETR | 2022 | AAAI | R50 | 50 | 44.2 | 24.6 | 8 | 锚点查询 |
| DAB-DETR | 2022 | ICLR | R50 | 50 | 45.7 | 26.3 | 8 | 4D动态锚框 |
| DN-DETR | 2022 | CVPR | R50 | 50 | 46.0 | 27.4 | 8 | 去噪训练 |
| Sparse DETR | 2022 | ICLR | R50 | 50 | 46.0 | 27.0 | 12 | 稀疏更新 |
| DINO | 2023 | ICLR | R50 | 12 | 49.4 | 32.3 | 5 | 对比去噪+混合查询 |
| DINO | 2023 | ICLR | Swin-L | 36 | 63.2 | 46.0 | 2 | (大模型极限) |
| YOLOv8-X | 2023 | - | CSP | 500 | 53.9 | 35.5 | 142 | 纯CNN |
| RT-DETR-R50 | 2023 | - | R50 | 72 | 53.1 | 34.8 | 108 | 实时DETR |
| RT-DETR-X | 2023 | - | HGNetv2 | 72 | 54.8 | 37.2 | 74 | 实时DETR |
| D-FINE-R50 | 2024 | CVPR | R50 | 72 | 54.1 | 35.8 | 112 | 分布回归+自蒸馏 |
| D-FINE-X | 2024 | CVPR | HGNetv2 | 72 | 55.8 | 38.1 | 95 | 分布回归 |
| DEIM-R50 | 2025 | CVPR | R50 | 36 | 53.4 | 35.2 | 105 | 密集O2O+MAL |
| DEIM-R50 | 2025 | CVPR | R50 | 72 | 54.2 | 36.1 | 105 | 密集O2O+MAL |
十六、一句话总结每个里程碑
| 模型 | 一句话 |
|---|---|
| DETR | "检测就是集合预测,不需要Anchor和NMS" |
| Deformable DETR | "不要看所有地方,只看几个关键点" |
| Conditional DETR | "把'找什么'和'在哪找'分开学" |
| Anchor DETR | "给Query一个明确的出生地" |
| DAB-DETR | "Query就是一个会动的锚框" |
| DN-DETR | "先学会从噪声中恢复,再学真正的检测" |
| Sparse DETR | "背景不重要,别浪费算力" |
| DINO | "正负对比去噪 + 混合查询 = 12 epoch收敛" |
| RT-DETR | "DETR也能实时,比YOLO还准" |
| D-FINE | "回归不是猜坐标,是精炼分布" |
| DEIM | "给更多Query正样本身份,但要学会区分好坏" |
参考文献
- Carion et al., "End-to-End Object Detection with Transformers", ECCV 2020
- Zhu et al., "Deformable DETR: Deformable Transformers for End-to-End Object Detection", ICLR 2021
- Meng et al., "Conditional DETR for Fast Training Convergence", ICCV 2021
- Fang et al., "Anchor DETR: Query Design for Transformer-Based Object Detection", AAAI 2022
- Liu et al., "DAB-DETR: Dynamic Anchor Boxes are Better Queries for DETR", ICLR 2022
- Li et al., "DN-DETR: Accelerate DETR Training by Introducing Query DeNoising", CVPR 2022
- Kim et al., "Sparse DETR: Efficient End-to-End Object Detection with Learnable Sparsity", ICLR 2022
- Zhang et al., "DINO: DETR with Improved DeNoising Anchor Boxes", ICLR 2023
- Lv et al., "DETRs Beat YOLOs on Real-time Object Detection", arXiv 2023
- Peng et al., "D-FINE: Redefine Regression Task in DETRs", CVPR 2024
- Huang et al., "DEIM: DETR with Improved Matching for Fast Convergence", CVPR 2025
- Dai et al., "Deformable Convolutional Networks", ICCV 2017
- Li et al., "Generalized Focal Loss", NeurIPS 2020
- Vaswani et al., "Attention Is All You Need", NeurIPS 2017
本文基于大量公开文献搜索整理,代码为原理示意,非官方实现。