DETR系列发展演化全史(深度完整版)

📌 系统梳理DETR系列5年间12+篇里程碑论文,每篇均包含:背景动机 → 创新点详表 → 技术深度解读 → 代码示意


📋 目录


一、前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的交叉注意力需要同时学习两件事

  1. 内容匹配:Query的语义和特征的内容是否匹配("这是不是一个目标")
  2. 空间定位: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的目标 :将这些优点统一整合,并进一步创新。

三个核心问题:
  1. DN-DETR的去噪只用正样本,能否加入负样本形成对比?
  2. Query的内容和空间能否来自不同源?
  3. 能否用更好的层间监督信号?

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正样本身份,但要学会区分好坏"

参考文献

  1. Carion et al., "End-to-End Object Detection with Transformers", ECCV 2020
  2. Zhu et al., "Deformable DETR: Deformable Transformers for End-to-End Object Detection", ICLR 2021
  3. Meng et al., "Conditional DETR for Fast Training Convergence", ICCV 2021
  4. Fang et al., "Anchor DETR: Query Design for Transformer-Based Object Detection", AAAI 2022
  5. Liu et al., "DAB-DETR: Dynamic Anchor Boxes are Better Queries for DETR", ICLR 2022
  6. Li et al., "DN-DETR: Accelerate DETR Training by Introducing Query DeNoising", CVPR 2022
  7. Kim et al., "Sparse DETR: Efficient End-to-End Object Detection with Learnable Sparsity", ICLR 2022
  8. Zhang et al., "DINO: DETR with Improved DeNoising Anchor Boxes", ICLR 2023
  9. Lv et al., "DETRs Beat YOLOs on Real-time Object Detection", arXiv 2023
  10. Peng et al., "D-FINE: Redefine Regression Task in DETRs", CVPR 2024
  11. Huang et al., "DEIM: DETR with Improved Matching for Fast Convergence", CVPR 2025
  12. Dai et al., "Deformable Convolutional Networks", ICCV 2017
  13. Li et al., "Generalized Focal Loss", NeurIPS 2020
  14. Vaswani et al., "Attention Is All You Need", NeurIPS 2017

本文基于大量公开文献搜索整理,代码为原理示意,非官方实现。

相关推荐
guo_xiao_xiao_17 小时前
YOLO三相电能表数字与单位符号目标检测数据集
人工智能·yolo·目标检测
青春不败 177-3266-05201 天前
CNN-Transformer:PyTorch遥感【含无人机】影像的分类、检测、语义分割和点云分类
pytorch·目标检测·cnn·transformer·生态学·遥感·地物分类
陈嘿萌1 天前
ECCV 2026|相机 × 激光雷达 × 4D 雷达:RAF 如何实现恶劣天气下的鲁棒 3D 检测?
人工智能·目标检测·计算机视觉·激光雷达·eccv
具身新纪元2 天前
CVPR 2026|新缺陷不断上线,如何让工业视觉检测模型不忘旧账?
人工智能·深度学习·目标检测·机器学习·计算机视觉·目标跟踪·视觉检测
一碗白开水一3 天前
入门实践工程二:基于 YOLOv8 的日常物品目标检测|附:环境依赖环境及工程源码
yolo·目标检测·目标跟踪
指尖的爷3 天前
RKNN转化环境搭建(rknn_toolkit2新版本)
嵌入式硬件·深度学习·物联网·目标检测
guo_xiao_xiao_3 天前
YOLO[室内与室外多场景混凝土块目标检测]目标检测数据集
yolo·目标检测·目标跟踪
江畔柳前堤3 天前
YOLO 目标检测全流程深度剖析
人工智能·yolo·目标检测·计算机视觉·unity·面试·vllm