论文信息

  • 标题:End-to-End Object Detection with Transformers
  • 会议:ECCV 2020
  • 单位:Facebook AI
  • 代码:github.com/facebookresearch/detr
  • 论文:https://arxiv.org/pdf/2005.12872.pdf

一、引言:目标检测终于不用"猜谜语"了

如果你接触过目标检测,一定对这些词不陌生:anchor锚点NMS非极大值抑制RPN区域建议网络。这些都是传统目标检测算法(比如Faster R-CNN、YOLO)的核心组件,但它们本质上都是手工设计的"猜谜语"游戏

  • anchor:先在图片上画几千个不同大小的框,猜哪个框里有物体
  • NMS:模型会对同一个物体输出多个重叠的框,再用启发式规则删掉重复的
  • RPN:专门用来筛选可能有物体的区域,再做精细检测

这些组件不仅让检测流程变得复杂,还引入了大量需要调参的超参数。那有没有可能让目标检测变得像图像分类一样简单?输入一张图片,直接输出所有物体的类别和坐标,不需要任何后处理

这就是DETR(DEtection TRansformer)要解决的问题。DETR第一次把Transformer完整地引入目标检测领域,用集合预测的思路彻底抛弃了anchor和NMS,实现了真正的端到端检测。

二、DETR整体架构:简单到难以置信

DETR的架构简单到令人发指,整个流程只需要三个步骤:

  1. 用CNN提取图像特征
  2. 用Transformer编码器-解码器处理特征
  3. 用两个全连接层直接输出类别和 bounding box

在这里插入图片描述
图1:DETR整体架构概览(来源:论文Figure 1)

通俗易懂的解释:你可以把DETR想象成一个"全能侦探"。它先用CNN"扫描"整个图片,提取出所有重要的视觉特征;然后用Transformer的自注意力机制"全局思考",理解图片中各个物体之间的关系;最后直接"说出"它看到的所有物体,每个物体只说一次,不会重复。

最神奇的是,整个模型不需要任何专门的检测层,只用标准的CNN和Transformer就能实现,推理代码不到50行!

三、核心技术细节

3.1 最关键的创新:二分匹配损失

DETR最大的挑战是:模型输出的是一个固定大小的集合(比如100个预测),而真实标签的数量是不固定的(每张图有几个到几十个物体),怎么把预测和真实标签对应起来?

传统方法是用anchor匹配:每个真实标签和离它最近的anchor对应。但DETR没有anchor,所以它用了一个更优雅的方法:匈牙利算法(二分匹配)
在这里插入图片描述

第一步:找到最优匹配

我们定义一个匹配成本函数,然后用匈牙利算法找到预测和真实标签之间的最优一一对应:
σ^=argminσ∈SN∑iNLmatch(yi,y^σ(i))\hat{\sigma}=\underset{\sigma \in \mathfrak{S}_{N}}{arg min } \sum_{i}^{N} \mathcal{L}_{match }\left(y_{i}, \hat{y}_{\sigma(i)}\right)σ^=σSNargminiNLmatch(yi,y^σ(i))

其中:

  • SN\mathfrak{S}_{N}SN:所有可能的排列组合(N是预测数量,固定为100)
  • yi=(ci,bi)y_i=(c_i, b_i)yi=(ci,bi):第i个真实标签,cic_ici是类别,bib_ibi是归一化的box坐标
  • y^σ(i)\hat{y}_{\sigma(i)}y^σ(i):第σ(i)\sigma(i)σ(i)个预测
  • Lmatch\mathcal{L}_{match}Lmatch:匹配成本函数,定义为:
    Lmatch(yi,y^σ(i))=−1{ci≠∅}p^σ(i)(ci)+1{ci≠∅}Lbox(bi,b^σ(i))\mathcal{L}_{match}(y_i, \hat{y}_{\sigma(i)}) = -\mathbb{1}_{\{c_i \neq \emptyset\}} \hat{p}_{\sigma(i)}(c_i) + \mathbb{1}_{\{c_i \neq \emptyset\}} \mathcal{L}_{box}(b_i, \hat{b}_{\sigma(i)})Lmatch(yi,y^σ(i))=1{ci=}p^σ(i)(ci)+1{ci=}Lbox(bi,b^σ(i))
    • 1{ci≠∅}\mathbb{1}_{\{c_i \neq \emptyset\}}1{ci=}:指示函数,当cic_ici不是背景类时为1
    • p^σ(i)(ci)\hat{p}_{\sigma(i)}(c_i)p^σ(i)(ci):预测为类别cic_ici的概率
    • Lbox\mathcal{L}_{box}Lbox:box损失函数

通俗易懂的解释:这就像一场"相亲配对"。每个真实物体是"女生",每个预测是"男生"。匹配成本就是"男生和女生的合适程度":预测类别越准、box越准,成本越低。匈牙利算法会找到一个全局最优的配对方案,让每个女生都找到最合适的男生,而且每个男生只能配一个女生。

第二步:计算匈牙利损失

找到最优匹配后,我们就可以计算最终的损失函数了:
LHungarian(y,y^)=∑i=1N[−logp^σ^(i)(ci)+1{ci≠ø}Lbox(bi,b^σ^(i))]\mathcal{L}_{Hungarian}(y, \hat{y})=\sum_{i=1}^{N}\left[-log \hat{p}_{\hat{\sigma}(i)}\left(c_{i}\right)+\mathbb{1}_{\left\{c_{i} \neq ø\right\}} \mathcal{L}_{box}\left(b_{i}, \hat{b}_{\hat{\sigma}}(i)\right)\right]LHungarian(y,y^)=i=1N[logp^σ^(i)(ci)+1{ci=ø}Lbox(bi,b^σ^(i))]

其中:

  • σ^\hat{\sigma}σ^:第一步找到的最优匹配
  • 第一项是分类损失(负对数似然)
  • 第二项是box损失,只有当cic_ici不是背景类时才计算
第三步:box损失函数

DETR没有用传统的L1损失,而是用了L1损失+广义IoU(GIoU)损失的组合:
Lbox(bi,b^σ(i))=λiouLiou(bi,b^σ(i))+λL1∥bi−b^σ(i)∥1\mathcal{L}_{box}(b_i, \hat{b}_{\sigma(i)}) = \lambda_{iou} \mathcal{L}_{iou}(b_i, \hat{b}_{\sigma(i)}) + \lambda_{L1} \left\| b_i - \hat{b}_{\sigma(i)} \right\|_1Lbox(bi,b^σ(i))=λiouLiou(bi,b^σ(i))+λL1 bib^σ(i) 1

其中:

  • λiou=2\lambda_{iou}=2λiou=2λL1=5\lambda_{L1}=5λL1=5:两个损失的权重
  • Liou\mathcal{L}_{iou}Liou:GIoU损失,定义为:
    Liou(bi,b^σ(i))=1−(∣bi∩b^σ(i)∣∣bi∪b^σ(i)∣−∣B(bi,b^σ(i))∖(bi∪b^σ(i))∣∣B(bi,b^σ(i))∣)\mathcal{L}_{iou}(b_i, \hat{b}_{\sigma(i)}) = 1 - \left( \frac{|b_i \cap \hat{b}_{\sigma(i)}|}{|b_i \cup \hat{b}_{\sigma(i)}|} - \frac{|B(b_i, \hat{b}_{\sigma(i)}) \setminus (b_i \cup \hat{b}_{\sigma(i)})|}{|B(b_i, \hat{b}_{\sigma(i)})|} \right)Liou(bi,b^σ(i))=1(bib^σ(i)bib^σ(i)B(bi,b^σ(i))B(bi,b^σ(i))(bib^σ(i)))
    • ∣bi∩b^σ(i)∣|b_i \cap \hat{b}_{\sigma(i)}|bib^σ(i):两个box的交集面积
    • ∣bi∪b^σ(i)∣|b_i \cup \hat{b}_{\sigma(i)}|bib^σ(i):两个box的并集面积
    • B(bi,b^σ(i))B(b_i, \hat{b}_{\sigma(i)})B(bi,b^σ(i)):能包含两个box的最小矩形面积

通俗易懂的解释:L1损失对大box和小box的惩罚是一样的,而GIoU损失是尺度不变的,对不同大小的box都能很好地优化。两者结合可以让box预测更准确。

3.2 Transformer编码器-解码器

DETR使用了标准的Transformer编码器-解码器架构,只做了一些小的修改。

编码器
  1. 输入:CNN提取的特征图f∈RC×H×Wf \in \mathbb{R}^{C \times H \times W}fRC×H×W(C=2048,H=W=原图尺寸/32)
  2. 用1x1卷积把通道数降到d=256,得到z0∈Rd×H×Wz_0 \in \mathbb{R}^{d \times H \times W}z0Rd×H×W
  3. 把空间维度展平,得到d×HWd \times HWd×HW的序列
  4. 加上固定的正弦位置编码,输入到Transformer编码器
  5. 编码器由6层多头自注意力和前馈网络组成

通俗易懂的解释:编码器的作用是"全局理解图片"。自注意力机制让每个位置的特征都能和图片中所有其他位置的特征交互,这样模型就能理解物体之间的空间关系和语义关系。

解码器
  1. 输入:N=100个可学习的对象查询(object queries)和编码器的输出
  2. 每个对象查询是一个d=256维的向量,代表模型"要找的物体"
  3. 解码器由6层多头自注意力和编码器-解码器注意力组成
  4. 每个解码器层输出N个d维的向量,分别对应N个预测

通俗易懂的解释:对象查询就像100个"侦探",每个侦探负责找一个物体。解码器让这些侦探之间互相交流(自注意力),同时查看编码器提取的图片特征(编码器-解码器注意力),最后每个侦探输出一个物体的类别和坐标。

3.3 预测头

解码器的每个输出向量会被输入到两个共享的全连接层:

  • 分类头:输出类别概率(包括背景类)
  • 回归头:输出归一化的box坐标(中心x、y,宽w,高h)

四、实验结果与分析

DETR在COCO 2017数据集上进行了全面的评估,和当时最先进的Faster R-CNN进行了对比。

4.1 整体性能对比

表1:DETR与Faster R-CNN的性能对比(来源:论文Table 1)

Model GFLOPS/FPS #params AP AP50 AP75 APS APM APL
Faster RCNN-FPN 180/26 42M 40.2 61.0 43.8 24.2 43.5 52.0
Faster RCNN-R101-FPN 246/20 60M 42.0 62.5 45.9 25.2 45.6 54.6
Faster RCNN-FPN+ 180/26 42M 42.0 62.1 45.5 26.6 45.4 53.4
Faster RCNN-R101-FPN+ 246/20 60M 44.0 63.9 47.8 27.2 48.1 56.0
DETR 86/28 41M 42.0 62.4 44.2 20.5 45.8 61.1
DETR-DC5 187/12 41M 43.3 63.1 45.9 22.5 47.3 61.1
DETR-R101 152/20 60M 43.5 63.8 46.4 21.9 48.0 61.8
DETR-DC5-R101 253/10 60M 44.9 64.7 47.7 23.7 49.5 62.3

结果分析

  • 整体性能相当:DETR和同等参数量的Faster R-CNN性能相当(42.0 AP vs 42.0 AP)
  • 大物体碾压:DETR在大物体上的性能比Faster R-CNN高7.8 AP(61.1 vs 53.4),这得益于Transformer的全局注意力机制
  • 小物体不足:DETR在小物体上的性能比Faster R-CNN低5.5 AP(20.5 vs 26.6),这是因为CNN下采样太多,小物体的特征丢失了
  • 速度更快:DETR的推理速度比Faster R-CNN快(28 FPS vs 26 FPS)

4.2 消融实验

研究人员做了大量的消融实验,来验证各个组件的重要性。

编码器层数的影响

表2:编码器层数对性能的影响(来源:论文Table 2)

#layers GFLOPS/FPS #params AP AP50 APS APM APL
0 76/28 33.4M 36.7 57.4 16.8 39.6 54.2
3 81/25 37.4M 40.1 60.6 18.5 43.8 58.6
6 86/23 41.3M 40.6 61.6 19.9 44.3 60.2
12 95/20 49.2M 41.6 62.1 19.8 44.9 61.9

结果分析:没有编码器的话,AP会下降3.9点,大物体AP下降6.0点。这说明编码器的全局推理能力对检测非常重要。

解码器层数的影响

在这里插入图片描述

图2:解码器层数对性能的影响(来源:论文Figure 4)

结果分析

  • 随着解码器层数的增加,AP和AP50持续提升
  • 第一层解码器的输出需要NMS来去除重复预测,因为第一层没有自注意力,模型不知道其他预测的存在
  • 从第二层开始,自注意力机制让模型能够抑制重复预测,NMS反而会降低性能
  • 这证明了DETR确实不需要NMS!

4.3 最有趣的实验:泛化到未见数量的物体

COCO数据集中最多只有13只长颈鹿的图片,但DETR能检测出24只长颈鹿!

在这里插入图片描述

图3:DETR泛化到24只长颈鹿(来源:论文Figure 5)

这个实验证明了DETR的对象查询没有过拟合到COCO的物体数量分布,它真的学会了"检测物体"这个通用能力,而不是记住了训练集中的模式。

4.4 注意力可视化

研究人员可视化了编码器和解码器的注意力图,看看模型到底在看什么。

在这里插入图片描述

图4:编码器自注意力可视化(来源:论文Figure 3)

结果分析:编码器的自注意力已经能够区分不同的物体实例,每个点的注意力都集中在它所在的物体上。

在这里插入图片描述

图5:解码器注意力可视化(来源:论文Figure 6)

结果分析:解码器的注意力主要集中在物体的边缘部分,比如头、腿、尾巴。这说明模型通过关注物体的特征点来确定物体的边界。

五、核心代码实现

论文中提供了DETR的极简PyTorch实现,不到50行代码就能跑通:

import torch
from torch import nn
from torchvision.models import resnet50

class DETR(nn.Module):
    def __init__(self, num_classes, hidden_dim, nheads,
                 num_encoder_layers, num_decoder_layers):
        super().__init__()
        # 从ResNet-50中提取卷积层,去掉最后的分类层和平均池化层
        self.backbone = nn.Sequential(*list(resnet50(pretrained=True).children())[:-2])
        # 1x1卷积将通道数从2048降到hidden_dim
        self.conv = nn.Conv2d(2048, hidden_dim, 1)
        # 标准Transformer
        self.transformer = nn.Transformer(hidden_dim, nheads,
                                          num_encoder_layers, num_decoder_layers)
        # 分类头:输出num_classes+1个类别(+1是背景类)
        self.linear_class = nn.Linear(hidden_dim, num_classes + 1)
        # 回归头:输出4个box坐标
        self.linear_bbox = nn.Linear(hidden_dim, 4)
        # 可学习的对象查询:100个,每个hidden_dim维
        self.query_pos = nn.Parameter(torch.rand(100, hidden_dim))
        # 可学习的位置编码:行和列各50个,每个hidden_dim//2维
        self.row_embed = nn.Parameter(torch.rand(50, hidden_dim // 2))
        self.col_embed = nn.Parameter(torch.rand(50, hidden_dim // 2))

    def forward(self, inputs):
        # 提取CNN特征
        x = self.backbone(inputs)
        # 降维
        h = self.conv(x)
        H, W = h.shape[-2:]
        # 构建位置编码:拼接行和列的嵌入
        pos = torch.cat([
            self.col_embed[:W].unsqueeze(0).repeat(H, 1, 1),
            self.row_embed[:H].unsqueeze(1).repeat(1, W, 1),
        ], dim=-1).flatten(0, 1).unsqueeze(1)
        # Transformer前向传播
        # 输入:位置编码+展平的特征,对象查询
        h = self.transformer(pos + h.flatten(2).permute(2, 0, 1),
                             self.query_pos.unsqueeze(1))
        # 输出分类和box坐标
        return self.linear_class(h), self.linear_bbox(h).sigmoid()

# 示例用法
if __name__ == "__main__":
    # 初始化DETR模型:COCO有91个类别
    detr = DETR(num_classes=91, hidden_dim=256, nheads=8,
                num_encoder_layers=6, num_decoder_layers=6)
    detr.eval()
    # 模拟输入:1张3通道800x1200的图片
    inputs = torch.randn(1, 3, 800, 1200)
    # 推理
    logits, bboxes = detr(inputs)
    print(f"Logits shape: {logits.shape}")  # [100, 1, 92]
    print(f"Bboxes shape: {bboxes.shape}")  # [100, 1, 4]

六、扩展应用:全景分割

DETR的架构非常灵活,只需要在解码器输出上加一个mask头,就能实现全景分割。

在这里插入图片描述

图6:DETR全景分割头架构(来源:论文Figure 8)

全景分割需要同时检测"事物"(有明确边界的物体,比如人、车)和"东西"(没有明确边界的区域,比如天空、草地)。DETR用统一的方式处理这两类:

  1. 用和检测完全相同的流程预测所有事物和东西的box
  2. 对每个预测的box,用mask头预测一个二进制mask
  3. 最后用像素级的argmax合并所有mask,得到最终的全景分割图

表3:全景分割性能对比(来源:论文Table 5)

Model Backbone PQ PQth PQst
PanopticFPN++ R50 42.4 49.2 32.3
UPSnet-M R50 43.0 48.9 34.1
DETR R50 43.4 48.2 36.3
DETR-DC5 R50 44.6 49.4 37.3
DETR-R101 R101 45.1 50.5 37.0

结果分析:DETR在全景分割上超过了当时所有的基线模型,尤其是在"东西"类别上优势明显(36.3 PQst vs 34.1 PQst)。这再次证明了Transformer的全局推理能力非常适合处理语义分割任务。

七、结论与展望

DETR是目标检测领域的一个里程碑式的工作,它的贡献主要有三点:

  1. 第一次实现了真正的端到端目标检测,彻底抛弃了anchor和NMS
  2. 证明了Transformer可以直接用于目标检测,并且性能和Faster R-CNN相当
  3. 架构非常灵活,可以很容易地扩展到全景分割等其他任务

当然,DETR也有一些局限性:

  • 训练时间太长:需要训练300-500个epoch,而Faster R-CNN只需要12个epoch
  • 小物体检测性能差:这是因为CNN下采样太多,小物体的特征丢失了
  • 推理速度还有提升空间:虽然比Faster R-CNN快,但比YOLO慢

未来的研究方向包括:

  • 改进训练策略,缩短训练时间
  • 结合FPN等多尺度特征,提升小物体检测性能
  • 研究更高效的Transformer架构,提升推理速度
  • 扩展到视频目标检测、实例分割等更多任务

有趣的展望:DETR开启了Transformer在目标检测领域的新时代。现在,几乎所有的目标检测SOTA模型都是基于Transformer的,比如DINO、RT-DETR等。可以说,DETR彻底改变了目标检测的研究方向。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐