当前位置: 首页 > news >正文

【论文#目标检测】End-to-End Object Detection with Transformers

目录

  • 摘要
  • 1.引言
  • 2.相关工作
    • 2.1 集合预测
    • 2.2 Transformer和并行解码
    • 2.3 目标检测
  • 3.DETR模型
    • 3.1 目标检测集合预测损失
    • 3.2 DETR架构
  • 4.实验
    • 4.1 与Faster R-CNN的比较
    • 4.2 消融研究
    • 4.3 分析
    • 4.4 DETR用于全景分割
  • 5.结论
  • 6.致谢

Author: Nicolas Carion, Francisco Massa, Gabriel Synnaeve, Nicolas Usunier, Alexander Kirillov, Sergey Zagoruyko
Subjects: Computer Vision and Pattern Recognition (cs.CV)
Cite as: arXiv:2005.12872 [cs.CV] (or arXiv:2005.12872v3 [cs.CV] for this version)
https://doi.org/10.48550/arXiv.2005.12872

摘要

我们提出了一种新方法,将目标检测视为一个直接的集合预测问题。我们的方法简化了检测流程,有效地消除了许多手工设计组件的需求,例如非极大值抑制(Non-Maximum Suppression)程序或锚点生成,这些组件明确地编码了我们对任务的先验知识。这种新框架被称为DEtection TRansformer(DETR),其主要组成部分是一个基于集合的全局损失函数,通过二分图匹配强制进行唯一预测,以及一个Transformer编码器-解码器架构。给定一组固定且经过学习的目标查询,DETR会推理目标之间的关系以及全局图像上下文,以直接并行输出最终的预测集合。这种新模型在概念上非常简单,不需要专门的库,这与许多其他现代检测器不同。DETR在具有挑战性的COCO目标检测数据集上展示了与经过良好验证且高度优化的Faster R-CNN基线相当的准确性和运行时性能。此外,DETR可以轻松地推广以统一的方式生成全景分割(panoptic segmentation)。我们证明了它显著优于竞争基线。训练代码和预训练模型可在https://github.com/facebookresearch/detr获取。

1.引言

目标检测的目标是为每个感兴趣的物体预测一组边界框和类别标签。现代检测器通过在大量候选区域 [37,5]、锚点 [23] 或窗口中心 [53,46] 上定义替代的回归和分类问题,以间接的方式解决这个集合预测任务。它们的性能显著受到后处理步骤的影响,这些步骤用于合并近乎重复的预测,同时也受到锚点集合的设计以及将目标框分配给锚点的启发式方法 [52] 的影响。为了简化这些流程,我们提出了一种直接的集合预测方法,以绕过这些替代任务。这种端到端的哲学已经在机器翻译或语音识别等复杂的结构化预测任务中取得了重大进展,但在目标检测中尚未如此:以前的尝试 [43,16,4,39] 要么增加了其他形式的先验知识,要么在具有挑战性的基准测试中尚未证明能够与强大的基线竞争。本文旨在弥合这一差距。

我们将目标检测视为一个直接的集合预测问题,从而简化了训练流程。我们采用了基于Transformer的编码器-解码器架构 [47],这是一种流行的序列预测架构。Transformer的自注意力机制明确地模拟了序列中各元素之间的所有成对交互,这使得这种架构特别适合集合预测的特定约束,例如去除重复预测。

我们的DEtection TRansformer(DETR,见图1)一次性预测所有目标,并通过一个集合损失函数进行端到端训练,该函数在预测目标和真实目标之间执行二分图匹配。DETR通过丢弃多个手工设计的组件来简化检测流程,这些组件编码了先验知识,例如空间锚点或非极大值抑制。与大多数现有的检测方法不同,DETR不需要任何定制层,因此可以在包含标准CNN和Transformer类的任何框架中轻松复现。
在这里插入图片描述
与大多数先前关于直接集合预测的工作相比,DETR的主要特点是二分图匹配损失函数与Transformer的结合,以及(非自回归)并行解码 [29,12,10,8]。相比之下,先前的工作集中在使用RNN的自回归解码 [43,41,30,36,42]。我们的匹配损失函数唯一地将一个预测分配给一个真实目标,并且对预测目标的排列是不变的,因此我们可以并行地输出它们。

我们在最受欢迎的目标检测数据集之一COCO [24]上评估了DETR,并将其与极具竞争力的Faster R-CNN基线 [37]进行了对比。Faster R-CNN经历了多次设计迭代,其性能自最初发表以来有了显著提升。我们的实验表明,我们的新模型达到了相当的性能。更具体地说,DETR在大目标上的表现明显更好,这可能是由于Transformer的非局部计算所实现的。然而,它在小目标上的表现较低。我们预计,未来的研究将像FPN [22]的发展为Faster R-CNN所做的那样,改善这一方面。

DETR的训练设置在多个方面与标准目标检测器不同。新模型需要额外长的训练时间,并且从Transformer中的辅助解码损失中受益。我们彻底探索了哪些组件对于所展示的性能至关重要。

DETR的设计理念可以轻松扩展到更复杂的任务。在我们的实验中,我们表明,在预训练的DETR之上训练的一个简单的分割头在全景分割 [19] 任务上超越了竞争基线,这是一个最近变得流行的具有挑战性的像素级识别任务。

2.相关工作

我们的工作在多个领域的先前研究基础上进行了拓展:集合预测的二分图匹配损失函数、基于Transformer的编码器-解码器架构、并行解码以及目标检测方法。

2.1 集合预测

目前并没有一个标准的深度学习模型可以直接预测集合。基本的集合预测任务是多标签分类(例如,在计算机视觉的背景下,可以参考[40,33]),而基线方法“一对一剩余”(one-vs-rest)并不适用于像检测这样的问题,因为在这些问题中,元素之间存在着底层结构(例如,近乎相同的边界框)。这些任务中的第一个难点是避免近乎重复的预测。大多数当前的检测器使用诸如非极大值抑制(Non-Maximum Suppression)之类的后处理方法来解决这一问题,但直接的集合预测是无需后处理的。它们需要一种全局推理方案,以模拟所有预测元素之间的相互作用,从而避免冗余。对于固定大小的集合预测,密集的全连接网络[9]是足够的,但成本较高。一种通用的方法是使用自回归序列模型,例如循环神经网络[48]。在所有情况下,损失函数都应该对预测的排列顺序保持不变。通常的解决方案是基于匈牙利算法[20]设计一个损失函数,以在真实值和预测值之间找到一个二分图匹配。这可以强制执行排列不变性,并保证每个目标元素都有一个唯一的匹配。我们遵循二分图匹配损失的方法。然而,与大多数先前的工作不同,我们摒弃了自回归模型,转而使用具有并行解码的Transformer,下面我们将对此进行描述。

2.2 Transformer和并行解码

Transformer由Vaswani等人[47]作为机器翻译中基于注意力的新构建模块引入。注意力机制[2]是神经网络层,能够从整个输入序列中聚合信息。Transformer引入了自注意力层,类似于非局部神经网络[49],它会扫描序列的每个元素,并通过聚合整个序列的信息来更新它。基于注意力的模型的主要优势之一是其全局计算能力和完美的记忆能力,这使得它们在处理长序列时比RNN更适合。Transformer现在正在取代自然语言处理、语音处理和计算机视觉[8,27,45,34,31]中的许多问题中的RNN。

Transformer最初用于自回归模型,遵循早期的序列到序列模型[44],逐个生成输出标记。然而,高昂的推理成本(与输出长度成正比,且难以批处理)促使了并行序列生成的发展,涉及领域包括音频[29]、机器翻译[12,10]、词表示学习[8],以及最近的语音识别[6]。我们也将Transformer和并行解码结合起来,以在计算成本和执行集合预测所需的全局计算能力之间取得合适的平衡。

2.3 目标检测

现代目标检测方法:大多数现代目标检测方法都是基于一些初始猜测来进行预测的。两阶段检测器 [37,5] 会相对于候选区域(proposals)来预测边界框,而单阶段方法则相对于锚点 [23] 或可能的目标中心网格 [53,46] 进行预测。最近的研究 [52] 表明,这些系统的最终性能在很大程度上取决于这些初始猜测的设置方式。在我们的模型中,我们能够去除这种手工设计的过程,并通过直接相对于输入图像进行绝对边界框预测,而不是相对于锚点,来简化检测流程。

集合损失:一些目标检测器 [9,25,35] 使用了二分图匹配损失。然而,在这些早期的深度学习模型中,不同预测之间的关系仅通过卷积层或全连接层进行建模,并且手工设计的非极大值抑制(NMS)后处理可以提升它们的性能。更近期的检测器 [37,23,53] 使用了非唯一的分配规则,将真实值与预测值联系起来,并结合了NMS。

可学习的NMS方法 [16,4] 和关系网络 [17] 明确地使用注意力机制来建模不同预测之间的关系。通过直接使用集合损失,它们不需要任何后处理步骤。然而,这些方法使用了额外的手工设计的上下文特征,如候选框坐标,来高效地建模检测之间的关系,而我们则寻求减少模型中编码的先验知识。

循环检测器:与我们的方法最接近的是目标检测 [43] 和实例分割 [41,30,36,42] 的端到端集合预测。与我们类似,它们使用基于CNN激活的编码器-解码器架构和二分图匹配损失来直接生成一组边界框。然而,这些方法仅在小型数据集上进行了评估,并且没有与现代基线进行对比。特别是,它们基于自回归模型(更准确地说是RNN),因此没有利用最近的Transformer和并行解码。

3.DETR模型

在目标检测中实现直接集合预测,有两个关键要素:(1)一个集合预测损失函数,它强制预测框与真实框之间进行唯一匹配;(2)一个架构,该架构能够在单次传递中预测一组目标并建模它们之间的关系。我们在图2中详细描述了我们的架构。

3.1 目标检测集合预测损失

DETR通过单次解码器传递推断一个固定大小的N个预测集合,其中N被设置为显著大于图像中典型目标数量。训练的主要难点之一是对预测目标(类别、位置、大小)相对于真实目标进行评分。我们的损失函数在预测目标和真实目标之间产生一个最优的二分图匹配,然后优化特定目标(边界框)的损失。

y y y 表示真实目标集合, y ^ = { y ^ i } i = 1 N \hat{y} = \{\hat{y}_i\}_{i=1}^{N} y^={y^i}i=1N 表示N个预测集合。假设N大于图像中目标的数量,我们将 y y y 也视为一个大小为N的集合,用空集 ∅ \emptyset (无目标)填充。为了在这两个集合之间找到一个二分图匹配,我们寻找一个排列 σ ∈ S N \sigma \in S_N σSN,使得损失最低:
在这里插入图片描述
其中 L match ( y i , y ^ σ ( i ) ) L_{\text{match}}(y_i, \hat{y}_{\sigma(i)}) Lmatch(yi,y^σ(i)) 是真实目标 y i y_i yi 与索引为 σ ( i ) \sigma(i) σ(i) 的预测之间的成对匹配成本。这个最优分配是通过匈牙利算法高效计算的,这遵循了先前的工作(例如 [43])。

匹配成本同时考虑了类别预测和预测框与真实框的相似性。真实目标集合中的每个元素 i i i 可以表示为 y i = ( c i , b i ) y_i = (c_i, b_i) yi=(ci,bi),其中 c i c_i ci 是目标类别标签(可能为空 ∅ \emptyset ),而 b i ∈ [ 0 , 1 ] 4 b_i \in [0, 1]^4 bi[0,1]4 是一个向量,定义了真实框中心坐标及其相对于图像大小的高度和宽度。对于索引为 σ ( i ) \sigma(i) σ(i) 的预测,我们定义类别 c i c_i ci 的概率为 p ^ σ ( i ) ( c i ) \hat{p}_{\sigma(i)}(c_i) p^σ(i)(ci),预测框为 b ^ σ ( i ) \hat{b}_{\sigma(i)} b^σ(i)。用这些符号,我们定义 L match ( y i , y ^ σ ( i ) ) L_{\text{match}}(y_i, \hat{y}_{\sigma(i)}) Lmatch(yi,y^σ(i)) − 1 { c i ≠ ∅ } p ^ σ ( i ) ( c i ) + 1 { c i ≠ ∅ } L box ( b i , b ^ σ ( i ) ) . \mathbb{-1}_{\{c_i \neq \emptyset\}} \hat{p}_{\sigma(i)}(c_i) + 1_{\{c_i \neq \emptyset\}}L_{\text{box}}(b_i, \hat{b}_{\sigma(i)}). 1{ci=}p^σ(i)(ci)+1{ci=}Lbox(bi,b^σ(i)).

寻找匹配的过程与现代检测器中用于将候选区域 [37] 或锚点 [22] 匹配到真实目标的启发式分配规则起到了相同的作用。主要区别在于,我们需要为直接集合预测找到一对一的匹配,且不出现重复。

第二步是计算损失函数,即在前一步中匹配的所有对的匈牙利损失(Hungarian loss)。我们定义的损失与常见目标检测器的损失类似,即类别预测的负对数似然和稍后定义的框损失的线性组合:
在这里插入图片描述
其中, σ ^ \hat{\sigma} σ^ 是在第一步(1)中计算出的最优分配。在实际应用中,当 c i = ∅ c_i = \emptyset ci= 时,我们将对数概率项的权重降低10倍,以解决类别不平衡问题。这类似于Faster R-CNN训练过程中通过下采样来平衡正/负候选区域的方式 [37]。需要注意的是,目标与 ∅ \emptyset 之间的匹配成本不依赖于预测结果,这意味着在这种情况下成本是一个常数。在匹配成本中,我们使用概率 p ^ σ ^ ( i ) ( c i ) \hat{p}_{\hat{\sigma}(i)}(c_i) p^σ^(i)(ci) 而不是对数概率。这使得类别预测项与 L box ( ⋅ , ⋅ ) L_{\text{box}}(\cdot, \cdot) Lbox(,)(下面将描述)具有可比性,我们观察到更好的实证性能。

边界框损失。匹配成本和匈牙利损失的第二部分是 L box ( ⋅ ) L_{\text{box}}(\cdot) Lbox(),用于评估边界框。与许多将边界框预测视为相对于某些初始猜测的 Δ \Delta Δ 的检测器不同,我们直接进行边界框预测。虽然这种方法简化了实现,但它带来了损失相对缩放的问题。最常用的 ℓ 1 \ell_1 1 损失即使在它们的相对误差相似的情况下,也会对小框和大框有不同的尺度。为了缓解这一问题,我们使用 ℓ 1 \ell_1 1 损失和广义IoU损失 [38] L IoU ( ⋅ , ⋅ ) L_{\text{IoU}}(\cdot, \cdot) LIoU(,) 的线性组合,后者是尺度不变的。总体而言,我们的框损失是 L box ( b i , b ^ σ ^ ( i ) ) L_{\text{box}}(b_i, \hat{b}_{\hat{\sigma}(i)}) Lbox(bi,b^σ^(i)),定义为 λ IoU L IoU ( b i , b ^ σ ^ ( i ) ) + λ L 1 ∥ b i − b ^ σ ^ ( i ) ∥ 1 \lambda_{\text{IoU}} L_{\text{IoU}}(b_i, \hat{b}_{\hat{\sigma}(i)}) + \lambda_{L1} \|b_i - \hat{b}_{\hat{\sigma}(i)}\|_1 λIoULIoU(bi,b^σ^(i))+λL1bib^σ^(i)1,其中 λ IoU , λ L 1 ∈ R \lambda_{\text{IoU}}, \lambda_{L1} \in \mathbb{R} λIoU,λL1R 是超参数。这两种损失都通过批次内的目标数量进行归一化。

注解
(1) σ \sigma σ 定义了一种方式,通过这种方式可以将预测集合 𝑦 ^ \hat{𝑦} y^​中的元素重新排序,以便与真实目标集合 y y y中的元素一一对应,而 σ ^ \hat{\sigma} σ^表示的是最佳的匹配方式。匹配问题的本质是,在目标检测任务中,模型生成的预测集合 𝑦 ^ \hat{𝑦} y^通常包含多个预测框(每个框对应一个可能的目标),而真实目标集合 y y y 则由图像中的实际目标组成。由于模型可能会生成多余的真实目标数量的预测,或者有些预测并不对应任何实际目标,因此需要一种机制将这些预测与真实目标进行匹配。
(2)如果模型生成预测目标数量多余真实目标数量,使用空集合进行扩展,使得二者匹配,这样才能够进行匈牙利算法的计算。匈牙利算法的一个通俗的解释:完全搞懂匈牙利算法原理。
(3) 1 { c i ≠ ∅ } 1_{\{c_i \neq \emptyset\}} 1{ci=}表示一个bool变量,如果满足 c i ≠ ∅ c_i \neq \emptyset ci= ,则为1,否则为0。
(4)第一步是找到最佳的匹配序列,计算的方式是寻找 L m a t c h L_{match} Lmatch 最小的匹配方式,使用匈牙利算法获得;第二步是根据前面获得的最佳匹配序列,计算损失 L H u n g a r i a n L_{Hungarian} LHungarian,这里表示的是基于前面的匈牙利算法获得的预测损失(名称容易让人误解)。
(5) L m a t c h L_{match} Lmatch L H u n g a r i a n L_{Hungarian} LHungarian 的计算公式非常相似,不同之处在于 L H u n g a r i a n L_{Hungarian} LHungarian 在概率计算部分使用了对数 l o g log log ,因此损失函数 L H u n g a r i a n L_{Hungarian} LHungarian 中需要计算背景目标的分类损失。
(6) L b o x L_{box} Lbox 的计算方式在附录给出
在这里插入图片描述

3.2 DETR架构

DETR的整体架构令人惊讶地简单,如图2所示。它包含三个主要组件,我们将在下面进行描述:用于提取紧凑特征表示的CNN主干网络、编码器-解码器Transformer,以及一个用于进行最终检测预测的简单前馈网络(FFN)。与许多现代检测器不同,DETR可以在任何提供通用CNN主干网络和Transformer架构实现的深度学习框架中,仅用几百行代码实现。DETR的推理代码可以在PyTorch [32] 中用不到50行代码实现。我们希望我们方法的简单性能够吸引新的研究人员加入目标检测领域。
在这里插入图片描述
主干网络:从初始图像 x img ∈ R 3 × H 0 × W 0 x_{\text{img}} \in \mathbb{R}^{3 \times H_0 \times W_0} ximgR3×H0×W0(包含3个颜色通道)开始,传统的CNN主干网络生成一个低分辨率的激活图 f ∈ R C × H × W f \in \mathbb{R}^{C \times H \times W} fRC×H×W。我们通常使用的典型值是 C = 2048 C = 2048 C=2048,而 H , W = H 0 32 , W 0 32 H, W = \frac{H_0}{32}, \frac{W_0}{32} H,W=32H0,32W0

Transformer编码器:首先,一个1x1卷积将高级激活图 f f f 的通道维度从 C C C 降低到一个较小的维度 d d d,从而创建一个新的特征图 z 0 ∈ R d × H × W z_0 \in \mathbb{R}^{d \times H \times W} z0Rd×H×W。编码器期望输入是一个序列,因此我们将 z 0 z_0 z0 的空间维度合并为一个维度,得到一个 d × H W d \times HW d×HW 的特征图。每个编码器层都有一个标准的架构,包括一个多头自注意力模块和一个前馈网络(FFN)。由于Transformer架构对排列顺序是不变的,我们通过向每个注意力层的输入添加固定的正弦和余弦位置编码 [31,3] 来补充它。详细的架构定义已推迟到附录中,它遵循了 [47] 中描述的架构。

Transformer解码器:解码器遵循Transformer的标准架构,使用多头自注意力和编码器-解码器注意力机制,将 N N N 个大小为 d d d 的嵌入进行转换。与原始Transformer的不同之处在于,我们的模型在每个解码器层中并行解码 N N N 个目标,而Vaswani等人 [47] 使用的是自回归模型,逐个元素地预测输出序列。对于不熟悉这些概念的读者,我们建议参考附录材料。由于解码器也是排列不变的,因此 N N N 个输入嵌入必须不同,才能产生不同的结果。这些输入嵌入是学习到的位置编码,我们称之为目标查询(object queries),类似于编码器,我们将它们添加到每个注意力层的输入中。

N N N 个目标查询通过解码器被转换为输出嵌入。然后,这些输出嵌入通过一个前馈网络(在下一小节中描述)独立解码为边界框坐标和类别标签,最终得到 N N N 个预测结果。通过对这些嵌入进行自注意力和编码器-解码器注意力操作,模型能够利用全局信息和目标之间的成对关系,同时将整个图像作为上下文进行推理。

预测前馈网络(FFNs):最终预测是通过一个具有ReLU激活函数和隐藏维度 d d d 的3层感知器,以及一个线性投影层来计算的。FFN预测边界框相对于输入图像的归一化中心坐标、高度和宽度,而线性层使用softmax函数预测类别标签。由于我们预测的是一个固定大小的 N N N 个边界框集合,而 N N N 通常远大于图像中实际感兴趣目标的数量,因此我们引入了一个额外的特殊类别标签 ∅ \emptyset ,用于表示某个位置没有检测到目标。这个类别在标准目标检测方法中类似于“背景”类别。

辅助解码损失:我们在训练期间发现,在解码器中使用辅助损失 [1] 是有帮助的,尤其是为了帮助模型输出每个类别的正确目标数量。我们在每个解码器层之后添加了预测FFN和匈牙利损失。所有预测FFN共享它们的参数。我们还使用了一个额外的共享层归一化层,以归一化来自不同解码器层的预测FFN的输入。

注解
(1)DETR整体的架构如下

CNN Backbone → 特征图 (H/32 × W/32) → Transformer Encoder → Memory
→ Transformer Decoder (使用 Memory + Object Queries) → 输出预测 (pred_logits, pred_boxes)

(2)DETR使用的backbone默认为Resnet50,这在main.py中的输入参数解析可以看出

parser.add_argument('--backbone', default='resnet50', type=str,help="Name of the convolutional backbone to use")

(3)在构建backbone时,会同时构建position encoding,构建位置在detr/models/backbone.py

def build_backbone(args):# 构建position encodingposition_embedding = build_position_encoding(args)train_backbone = args.lr_backbone > 0return_interm_layers = args.masks# 构建backbonebackbone = Backbone(args.backbone, train_backbone, return_interm_layers, args.dilation)model = Joiner(backbone, position_embedding)model.num_channels = backbone.num_channelsreturn model

buid_position_encoding()定义在detr/models/position_encoding.py中,支持sine函数的编码方式,也支持learned学习的方式进行学习

def build_position_encoding(args):N_steps = args.hidden_dim // 2if args.position_embedding in ('v2', 'sine'):# TODO find a better way of exposing other argumentsposition_embedding = PositionEmbeddingSine(N_steps, normalize=True)elif args.position_embedding in ('v3', 'learned'):position_embedding = PositionEmbeddingLearned(N_steps)else:raise ValueError(f"not supported {args.position_embedding}")return position_embedding

PositionEmbeddingSine()定义了位置编码的计算方式

class PositionEmbeddingSine(nn.Module):"""This is a more standard version of the position embedding, very similar to the oneused by the Attention is all you need paper, generalized to work on images."""def __init__(self, num_pos_feats=64, temperature=10000, normalize=False, scale=None):super().__init__()self.num_pos_feats = num_pos_featsself.temperature = temperatureself.normalize = normalizeif scale is not None and normalize is False:raise ValueError("normalize should be True if scale is passed")if scale is None:scale = 2 * math.piself.scale = scaledef forward(self, tensor_list: NestedTensor):# tensors: 图像特征张量,[batch, C, H, W]x = tensor_list.tensors# mask: 处理图像的掩码, [batch, H, W]mask = tensor_list.maskassert mask is not None# 掩码取反,表示有效的像素位置not_mask = ~mask# 1.获取公式中的pos数值# cumsum(1)计算第1个维度的数值累积和,这里是有效像素的在高度上的数量,即图像高度# 维度为 [batch, H, W]y_embed = not_mask.cumsum(1, dtype=torch.float32)# cumsum(2)计算第2个维度的数值累计和,即图像宽度# 维度为 [batch, H, W]x_embed = not_mask.cumsum(2, dtype=torch.float32)# 如果进行normalize,将数据缩放到 [0, 2*pi]if self.normalize:eps = 1e-6y_embed = y_embed / (y_embed[:, -1:, :] + eps) * self.scalex_embed = x_embed / (x_embed[:, :, -1:] + eps) * self.scale# 2.生成频率因子,即公式中的分母 10000^(2i/d_model)# dim_t = [0, 1, ..., num_pos_feats -1]dim_t = torch.arange(self.num_pos_feats, dtype=torch.float32, device=x.device)# dim_t = 10000^[(2 * i // 2) / num_pos_feats]dim_t = self.temperature ** (2 * (dim_t // 2) / self.num_pos_feats)# 3.计算 pos/[10000^(2i/d_model)]# pos_x的维度 [batch, H, W, num_pos_feats]pos_x = x_embed[:, :, :, None] / dim_t# pos_y的维度 [batch, H, W, num_pos_feats]pos_y = y_embed[:, :, :, None] / dim_t# 4.计算sin{pos/[10000^(2i/d_model)]}和cos{pos/[10000^(2i/d_model)]},交错存储# 交错sin/cos [batch, H, W, num_pos_feats]pos_x = torch.stack((pos_x[:, :, :, 0::2].sin(), pos_x[:, :, :, 1::2].cos()), dim=4).flatten(3)# 交错sin/cos [batch, H, W, num_pos_feats]pos_y = torch.stack((pos_y[:, :, :, 0::2].sin(), pos_y[:, :, :, 1::2].cos()), dim=4).flatten(3)# [batch, 2*num_pos_feats, H, W]pos = torch.cat((pos_y, pos_x), dim=3).permute(0, 3, 1, 2)return pos

(4)Transformer模型的构建由build_transformer()实现,包括encoder和decoder

def build_transformer(args):return Transformer(d_model=args.hidden_dim,dropout=args.dropout,nhead=args.nheads,dim_feedforward=args.dim_feedforward,num_encoder_layers=args.enc_layers,num_decoder_layers=args.dec_layers,normalize_before=args.pre_norm,return_intermediate_dec=True,)# Transformer类的定义
class Transformer(nn.Module):def __init__(self, d_model=512, nhead=8, num_encoder_layers=6,num_decoder_layers=6, dim_feedforward=2048, dropout=0.1,activation="relu", normalize_before=False,return_intermediate_dec=False):super().__init__()encoder_layer = TransformerEncoderLayer(d_model, nhead, dim_feedforward,dropout, activation, normalize_before)# 是否要前置一个norm层encoder_norm = nn.LayerNorm(d_model) if normalize_before else Noneself.encoder = TransformerEncoder(encoder_layer, num_encoder_layers, encoder_norm)decoder_layer = TransformerDecoderLayer(d_model, nhead, dim_feedforward,dropout, activation, normalize_before)decoder_norm = nn.LayerNorm(d_model)self.decoder = TransformerDecoder(decoder_layer, num_decoder_layers, decoder_norm,return_intermediate=return_intermediate_dec)self._reset_parameters()self.d_model = d_modelself.nhead = nheaddef _reset_parameters(self):for p in self.parameters():if p.dim() > 1:nn.init.xavier_uniform_(p)def forward(self, src, mask, query_embed, pos_embed):# flatten NxCxHxW to HWxNxC# src: [batch_size, channels, height, width] (e.g., [2, 256, 20, 20])# mask: [batch_size, height, width] (padding mask)# query_embed: [num_queries, d_model] (e.g., [100, 256])# pos_embed: [batch_size, d_model, height, width] (位置编码),这里的d_model=2*num_pos_featsbs, c, h, w = src.shape# 修改src的维度为[HW, batch_size, d_model] (e.g., [400, 2, 256])src = src.flatten(2).permute(2, 0, 1) # 修改pos的维度为[HW, batch_size, d_model]pos_embed = pos_embed.flatten(2).permute(2, 0, 1)# [num_queries, batch_size, d_model]query_embed = query_embed.unsqueeze(1).repeat(1, bs, 1)# [batch_size, HW]mask = mask.flatten(1)# 初始化查询向量 query(全零)tgt = torch.zeros_like(query_embed)# encodermemory = self.encoder(src, src_key_padding_mask=mask, pos=pos_embed)# decoderhs = self.decoder(tgt, memory, memory_key_padding_mask=mask,pos=pos_embed, query_pos=query_embed)return hs.transpose(1, 2), memory.permute(1, 2, 0).view(bs, c, h, w)

(5)上面的self.encoder为TransformerEncoder

class TransformerEncoder(nn.Module):# encoder_layer为TransformerEncoderLayer# num_layer默认为6,即encoder由6层encoder_layer组成def __init__(self, encoder_layer, num_layers, norm=None):super().__init__()self.layers = _get_clones(encoder_layer, num_layers)self.num_layers = num_layersself.norm = normdef forward(self, src,mask: Optional[Tensor] = None,src_key_padding_mask: Optional[Tensor] = None,pos: Optional[Tensor] = None):output = srcfor layer in self.layers:output = layer(output, src_mask=mask,src_key_padding_mask=src_key_padding_mask, pos=pos)if self.norm is not None:output = self.norm(output)return output

TransformerEncoder由多层TransformerEncoderLayer组成

class TransformerEncoderLayer(nn.Module):def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1,activation="relu", normalize_before=False):super().__init__()self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)# Implementation of Feedforward modelself.linear1 = nn.Linear(d_model, dim_feedforward)self.dropout = nn.Dropout(dropout)self.linear2 = nn.Linear(dim_feedforward, d_model)self.norm1 = nn.LayerNorm(d_model)self.norm2 = nn.LayerNorm(d_model)self.dropout1 = nn.Dropout(dropout)self.dropout2 = nn.Dropout(dropout)self.activation = _get_activation_fn(activation)self.normalize_before = normalize_before# 默认情况下,pos不会为Nonedef with_pos_embed(self, tensor, pos: Optional[Tensor]):return tensor if pos is None else tensor + pos# 通常使用post处理方式def forward_post(self,src,src_mask: Optional[Tensor] = None,src_key_padding_mask: Optional[Tensor] = None,pos: Optional[Tensor] = None):# q和k都包括了内容特征(src)和位置信息(pos)# 根据公式, softmax(q * k^T / sqrt(dk)) * V# q * k^T 表示img与img的转置相乘,表示图像的自相关信息,之中还附带了位置信息# 这里简单的将src + pos,维度不变,仅改变特征值q = k = self.with_pos_embed(src, pos)# 计算自注意力src2 = self.self_attn(q, k, value=src, attn_mask=src_mask,key_padding_mask=src_key_padding_mask)[0]src = src + self.dropout1(src2)src = self.norm1(src)src2 = self.linear2(self.dropout(self.activation(self.linear1(src))))src = src + self.dropout2(src2)src = self.norm2(src)return src// ...def forward(self, src,src_mask: Optional[Tensor] = None,src_key_padding_mask: Optional[Tensor] = None,pos: Optional[Tensor] = None):if self.normalize_before:return self.forward_pre(src, src_mask, src_key_padding_mask, pos)return self.forward_post(src, src_mask, src_key_padding_mask, pos)

nn.MultiheadAttention()是多头注意力机制的计算方法,其前向推理函数接受query,key和value,返回注意力加权后的结果output,以及每个权重头的注意力矩阵(attention_weight,可选)

outputs, attention_weight(optional) = forward(query, key, value, key_padding_mask=None, attn_mask=None)

对于图像中自注意力的简单理解,是图像当中比较重要的区域(或注意的区域),图像矩阵A和矩阵A的转置相乘,表示的是图像的相似性矩阵。因为矩阵的点积是行乘以列,所以 A A A A T A^T AT 的相乘计算的就是 A A A 当中行与行之间的点积。如果 A A A 的第 i i i 行与 A T A^T AT 的第 j j j 列的点积非常大,说明 A A A 当中的第 i i i 行和第 j j j 行对应的向量方向一致,即相似程度很高。这两行很相似,说明这两行对应的像素很有可能属于同一个物体,这是网络训练能够进行目标区域性识别的根本原因。

TransformerEncoderLayer的示意图如下。其中,残差连接用于组合融合的特征以及基础特征;dropout用于随机丢弃一些参数,防止过拟合;nn.LayerNorm用于归一化每个样本的特征,稳定训练过程,加速收敛,提高模型性能。TransformerEncoder输出的最终输出output是记忆张量(Memory Tensor),包含了丰富的图像特征信息。在这个上下文中,编码器的输出作为“记忆”提供给解码器,使得解码器可以访问到整个图像的信息。

(6)self.decoder为TransformerDecoder

class TransformerDecoder(nn.Module):# decoder_layer为TransformerDecoderLayer# num_layers = 6,即有6层decoder_layerdef __init__(self, decoder_layer, num_layers, norm=None, return_intermediate=False):super().__init__()self.layers = _get_clones(decoder_layer, num_layers)self.num_layers = num_layersself.norm = normself.return_intermediate = return_intermediatedef forward(self, tgt, memory,tgt_mask: Optional[Tensor] = None,memory_mask: Optional[Tensor] = None,tgt_key_padding_mask: Optional[Tensor] = None,memory_key_padding_mask: Optional[Tensor] = None,pos: Optional[Tensor] = None,query_pos: Optional[Tensor] = None):output = tgtintermediate = []for layer in self.layers:output = layer(output, memory, tgt_mask=tgt_mask,memory_mask=memory_mask,tgt_key_padding_mask=tgt_key_padding_mask,memory_key_padding_mask=memory_key_padding_mask,pos=pos, query_pos=query_pos)if self.return_intermediate:intermediate.append(self.norm(output))if self.norm is not None:output = self.norm(output)if self.return_intermediate:intermediate.pop()intermediate.append(output)if self.return_intermediate:return torch.stack(intermediate)return output.unsqueeze(0)

TransformerDecoderLayer的定义

class TransformerDecoderLayer(nn.Module):def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1,activation="relu", normalize_before=False):super().__init__()self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)self.multihead_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)# Implementation of Feedforward modelself.linear1 = nn.Linear(d_model, dim_feedforward)self.dropout = nn.Dropout(dropout)self.linear2 = nn.Linear(dim_feedforward, d_model)self.norm1 = nn.LayerNorm(d_model)self.norm2 = nn.LayerNorm(d_model)self.norm3 = nn.LayerNorm(d_model)self.dropout1 = nn.Dropout(dropout)self.dropout2 = nn.Dropout(dropout)self.dropout3 = nn.Dropout(dropout)self.activation = _get_activation_fn(activation)self.normalize_before = normalize_beforedef with_pos_embed(self, tensor, pos: Optional[Tensor]):return tensor if pos is None else tensor + pos# 输入的tgt是query向量,每个查询向量可以看作一个 “物体槽”,模型通过注意力机制在图像中寻找可能存在的物体,并填充到这些槽中# 训练时通过匈牙利匹配算法将预测结果与真实标注唯一匹配,查询向量逐渐学会关注不同位置、不同类别的物体#(例如某些查询可能偏向检测“人”,另一些偏向“车”,但这是隐式学习的,而非显式指定)# 输入参数:# tgt = tgt# memory = memory# memory_key_padding_mask = mask# pos = pos_embed# query_pos = query_embeddef forward_post(self, tgt, memory,tgt_mask: Optional[Tensor] = None,memory_mask: Optional[Tensor] = None,tgt_key_padding_mask: Optional[Tensor] = None,memory_key_padding_mask: Optional[Tensor] = None,pos: Optional[Tensor] = None,query_pos: Optional[Tensor] = None):# 对于第一层的decoderlayer,tgt中的值为全零,默认一共有6层# query_pos为可学习的参数(真正的语义引导)q = k = self.with_pos_embed(tgt, query_pos)# 实际上是query_pos的自注意力计算,在迭代训练过程中会增强这些查询的能力# 查询的对象是图像的高级特征表示memorytgt2 = self.self_attn(q, k, value=tgt, attn_mask=tgt_mask,key_padding_mask=tgt_key_padding_mask)[0]tgt = tgt + self.dropout1(tgt2)tgt = self.norm1(tgt)# 将图像特征memory与查询query进行交互,从而提取信息,计算的是交叉注意力# 计算的公式 ≈ (Q * K^T) * V,(Q * K^T)计算的结果是注意力得分矩阵# 实际上是强化了memory中代表的特征信息(类比图像锐化等操作)tgt2 = self.multihead_attn(query=self.with_pos_embed(tgt, query_pos),key=self.with_pos_embed(memory, pos),value=memory, attn_mask=memory_mask,key_padding_mask=memory_key_padding_mask)[0]tgt = tgt + self.dropout2(tgt2)tgt = self.norm2(tgt)tgt2 = self.linear2(self.dropout(self.activation(self.linear1(tgt))))tgt = tgt + self.dropout3(tgt2)tgt = self.norm3(tgt)return tgt// ...def forward(self, tgt, memory,tgt_mask: Optional[Tensor] = None,memory_mask: Optional[Tensor] = None,tgt_key_padding_mask: Optional[Tensor] = None,memory_key_padding_mask: Optional[Tensor] = None,pos: Optional[Tensor] = None,query_pos: Optional[Tensor] = None):if self.normalize_before:return self.forward_pre(tgt, memory, tgt_mask, memory_mask,tgt_key_padding_mask, memory_key_padding_mask, pos, query_pos)return self.forward_post(tgt, memory, tgt_mask, memory_mask,tgt_key_padding_mask, memory_key_padding_mask, pos, query_pos)

TransformerDecoderLayer的结构如下图所示

DETR会默认检测图像当中能够识别的所有物体种类,默认为识别100个。如果想要仅仅识别某一些类别,需要在数据集当中去掉这些标注信息。

4.实验

我们展示了DETR在COCO上的定量评估中与Faster R-CNN相比具有竞争力的结果。然后,我们提供了对架构和损失函数的详细消融研究,并提供了见解和定性结果。最后,为了展示DETR是一个多功能且可扩展的模型,我们展示了在固定DETR模型上仅训练一个小扩展的全景分割的结果。我们在https://github.com/facebookresearch/detr提供了复现我们实验的代码和预训练模型。

数据集:我们在COCO 2017目标检测和全景分割数据集 [24,18] 上进行了实验,这些数据集包含11.8万张训练图像和5,000张验证图像。每张图像都标注了边界框和全景分割。平均每张图像有7个实例,训练集中单张图像最多有63个实例,这些实例在同一图像中从小到大不等。如果没有特别说明,我们报告的AP是边界框AP,即在多个阈值上的积分指标。为了与Faster R-CNN进行比较,我们报告了最后一个训练周期的验证AP;对于消融研究,我们报告了最后10个周期的验证结果的中位数。

技术细节:我们使用AdamW [26] 训练DETR,将Transformer的初始学习率设置为 1 0 − 4 10^{-4} 104,主干网络的设置为 1 0 − 5 10^{-5} 105,权重衰减设置为 1 0 − 4 10^{-4} 104。所有Transformer权重都使用Xavier初始化 [11],主干网络使用torchvision中预训练的ResNet模型 [15],并冻结了批量归一化层。我们报告了两种不同主干网络的结果:ResNet50和ResNet-101。相应的模型分别称为DETR和DETR-R101。按照 [21] 的方法,我们还在主干网络的最后阶段添加了扩张,并从该阶段的第一个卷积中移除步幅,从而提高了特征分辨率。相应的模型分别称为DETR-DC5和DETR-DC5-R101(扩张的C5阶段)。这一修改将分辨率提高了两倍,从而提高了对小目标的性能,但代价是编码器的自注意力计算成本增加了16倍,导致总体计算成本增加了2倍。这些模型与Faster R-CNN的FLOPs完整比较见表1。
在这里插入图片描述
我们使用了尺度增强,将输入图像调整为最短边至少为480像素,最长边最多为1333像素,而最短边最多为800像素 [50]。为了帮助通过编码器的自注意力学习全局关系,我们在训练期间还应用了随机裁剪增强,从而提高了大约1 AP的性能。具体来说,以0.5的概率将训练图像裁剪为一个随机矩形区域,然后再将其调整为800-1333像素的大小。Transformer的默认dropout设置为0.1。在推理时,一些槽位会预测为空类别。为了优化AP(平均精度),我们将这些槽位的预测替换为得分第二高的类别,并使用相应的置信度。与过滤掉空槽位相比,这种方法可以将AP提高2个百分点。

其他训练超参数可以在附录A.4节中找到。在我们的消融实验中,我们使用了300个周期的训练计划,并在200个周期后将学习率降低10倍。一个周期是指对所有训练图像进行一次遍历。在16块V100 GPU上,每块GPU处理4张图像(因此总批量大小为64),训练基础模型300个周期需要3天。为了与Faster R-CNN进行比较,我们使用了更长的训练计划,训练了500个周期,并在400个周期后降低学习率。这种更长的训练计划比短训练计划额外提高了1.5 AP。

4.1 与Faster R-CNN的比较

Transformer通常使用Adam或Adagrad优化器进行训练,训练周期很长,并且会使用dropout,DETR也是如此。然而,Faster R-CNN是使用SGD进行训练的,数据增强非常有限,我们没有发现成功应用Adam或dropout的案例。尽管存在这些差异,我们还是尝试让Faster R-CNN的基线更强。为了使其与DETR保持一致,我们在边界框损失中加入了广义IoU [38],并采用了相同的随机裁剪增强和已知可以改善结果的长训练周期 [13]。结果展示在表1中。在表的上半部分,我们展示了Detectron2模型库 [50] 中使用3x训练计划训练的Faster R-CNN的结果。在中间部分,我们展示了使用9x训练计划(109个周期)和上述增强训练的相同模型的结果(带有“+”),总共增加了1-2 AP。在表1的最后一部分,我们展示了多个DETR模型的结果。为了在参数数量上具有可比性,我们选择了一个具有6个Transformer层和6个解码器层、宽度为256、8个注意力头的模型。与带有FPN的Faster R-CNN一样,该模型拥有4130万参数,其中2350万在ResNet-50中,1780万在Transformer中。尽管Faster R-CNN和DETR在更长的训练周期后都有可能进一步提升,但我们可以得出结论,DETR在参数数量相同的情况下可以与Faster R-CNN相媲美,在COCO验证子集上达到了42 AP。DETR实现这一目标的方式是提高了大目标的AP(+7.8),但请注意,该模型在小目标的AP上仍然落后(-5.5)。DETR-DC5在参数数量和FLOP计数上与之相似,其AP更高,但在APS上仍然显著落后。带有ResNet-101主干的Faster R-CNN和DETR也显示出相当的结果。

4.2 消融研究

Transformer解码器中的注意力机制是建模不同检测特征表示之间关系的关键组件。在我们的消融分析中,我们探讨了架构和损失的其他组成部分对最终性能的影响。为此,我们选择了基于ResNet-50的DETR模型,该模型具有6个编码器层、6个解码器层,宽度为256。该模型拥有4130万参数,在短训练周期和长训练周期上分别达到了40.6和42.0的AP,并且运行速度为每秒28帧,与具有相同主干网络的Faster R-CNN-FPN相当。

编码器层数量:我们通过改变编码器层数来评估全局图像级自注意力的重要性(见表2)。如果没有编码器层,整体AP会下降3.9个百分点,而在大目标上AP会显著下降6.0个百分点。我们推测,通过使用全局场景推理,编码器对于分离目标非常重要。在图3中,我们可视化了一个训练有素模型的最后一个编码器层的注意力图,重点关注图像中的几个点。编码器似乎已经分离了实例,这可能简化了解码器的目标提取和定位。
在这里插入图片描述
在这里插入图片描述
解码器层数量:我们在每个解码层之后应用辅助损失(见第3.2节),因此,预测FFN被设计为从每个解码器层的输出中预测目标。我们通过评估每个解码阶段将要预测的目标来分析每个解码器层的重要性(见图4)。AP和AP50在每一层之后都有所提高,从第一层到最后一层总共提高了非常显著的8.2/9.5 AP。由于其基于集合的损失,DETR在设计上不需要NMS。为了验证这一点,我们对每个解码器的输出运行了标准的NMS程序,并使用默认参数[50]。对于第一个解码器的预测,NMS提高了性能。这可以解释为,Transformer的一个解码层无法计算输出元素之间的任何交叉相关性,因此它容易对同一目标做出多个预测。在第二层及之后的层中,激活上的自注意力机制允许模型抑制重复预测。我们观察到,随着深度的增加,NMS带来的改进逐渐减少。在最后几层中,我们观察到AP有小幅下降,因为NMS错误地移除了真正的正预测。
在这里插入图片描述

与可视化编码器注意力类似,我们在图6中可视化了解码器的注意力,为每个预测目标的注意力图用不同颜色标记。我们观察到解码器的注意力相对局部化,这意味着它主要关注目标的边缘部分,如头部或腿部。我们推测,在编码器通过全局注意力分离实例之后,解码器只需要关注边缘部分来提取类别和目标边界。
在这里插入图片描述
FFN的重要性:Transformer中的FFN可以被视为1×1卷积层,使编码器类似于注意力增强的卷积网络[3]。我们尝试完全移除它,只在Transformer层中保留注意力。通过将网络参数数量从4130万减少到2870万,仅在Transformer中保留1080万参数,性能下降了2.3 AP。因此,我们得出结论,FFN对于获得良好结果非常重要。

位置编码的重要性:我们的模型中有两种位置编码:空间位置编码和输出位置编码(目标查询)。我们尝试了固定和学习编码的各种组合,结果见表3。输出位置编码是必需的,不能移除,因此我们尝试在解码器输入处传递它们一次,或在每个解码器注意力层中添加到查询中。在第一个实验中,我们完全移除了空间位置编码,并在输入处传递输出位置编码,有趣的是,该模型仍然实现了超过32的AP,比基线低7.8 AP。然后,我们传递固定的正弦空间位置编码和在输入处的输出编码,如原始Transformer[47]中那样,并发现这比直接在注意力中传递位置编码导致了1.4 AP的下降。传递给注意力的学习空间编码给出了类似的结果。令人惊讶的是,我们发现仅在编码器中不传递任何空间编码只会导致AP小幅下降1.3 AP。当我们传递编码到注意力时,它们在所有层中共享,输出编码(目标查询)始终是学习的。
在这里插入图片描述

鉴于这些消融实验,我们得出结论,Transformer组件:编码器中的全局自注意力、FFN、多个解码器层和位置编码,都显著地对最终的目标检测性能做出了贡献。

损失消融:为了评估匹配成本和损失的不同组成部分的重要性,我们训练了几个模型,开启和关闭它们。损失有三个组成部分:分类损失、L1边界框距离损失和GIoU[38]损失。分类损失对于训练至关重要,不能关闭,因此我们训练了一个没有边界框距离损失的模型,一个没有GIoU损失的模型,并与使用所有三种损失训练的基线进行比较。结果见表4。GIoU损失本身占据了模型性能的大部分,与使用综合损失的基线相比仅损失了0.7 AP。仅使用L1而不使用GIoU显示出较差的结果。我们只研究了不同损失的简单消融(每次都使用相同的权重),但其他组合它们的方式可能会产生不同的结果。
在这里插入图片描述

4.3 分析

解码器输出槽分析:在图7中,我们可视化了DETR在COCO 2017验证集的所有图像上,由不同槽位预测的边界框。DETR为每个查询槽位学习了不同的专长。我们观察到每个槽位有几种操作模式,专注于不同的区域和框大小。特别是,所有槽位都有一个模式用于预测全图像范围的框(在图中表现为排列在中间的红点)。我们推测这与COCO中目标的分布有关。
在这里插入图片描述

对未见实例数量的泛化能力:在COCO中,有些类别并没有在单张图像中出现许多相同类别的实例。例如,在训练集中没有任何一张图像包含超过13只长颈鹿。我们创建了一张合成图像来验证DETR的泛化能力(见图5)。我们的模型能够在图像中找到全部24只长颈鹿,这显然超出了训练分布的范围。这个实验确认了每个目标查询并没有强烈的类别专长。

4.4 DETR用于全景分割

全景分割 [19] 最近引起了计算机视觉界的广泛关注。类似于Faster R-CNN [37] 扩展到Mask R-CNN [14],DETR可以通过在解码器输出上添加一个掩码头(mask head)自然地进行扩展。在本节中,我们展示了这种掩码头可以用于生成全景分割 [19],通过统一处理“stuff”(背景)和“thing”(目标)类别。我们在COCO数据集的全景注释上进行了实验,该数据集除了80个“thing”类别外,还有53个“stuff”类别。

我们在COCO上训练DETR,使其能够预测围绕“stuff”和“thing”类别的边界框,使用与之前相同的方法。预测边界框是训练所必需的,因为匈牙利匹配是通过计算边界框之间的距离来完成的。我们还添加了一个掩码头,它为每个预测的边界框预测一个二进制掩码,见图8。它以每个目标的Transformer解码器输出为输入,并计算这个嵌入在编码器输出上的多头(M个头)注意力分数,为每个目标生成M个小分辨率的注意力热图。为了进行最终预测并提高分辨率,我们使用了一种类似FPN的架构。我们在补充材料中更详细地描述了这种架构。掩码的最终分辨率是步长为4,每个掩码都独立地使用DICE/F-1损失 [28] 和Focal损失 [23] 进行监督。
在这里插入图片描述

掩码头可以与DETR联合训练,也可以采用两步过程:首先只训练DETR预测边界框,然后冻结所有权重,仅训练掩码头25个周期。实验表明,这两种方法的结果相似,我们报告了后一种方法的结果,因为它导致了更短的总训练时间。

为了预测最终的全景分割,我们简单地在每个像素的掩码分数上使用argmax,并将相应的类别分配给结果掩码。这个过程保证了最终掩码之间没有重叠,因此,DETR不需要经常用于对齐不同掩码的启发式方法 [19]。

训练细节:我们按照边界框检测的方案训练DETR、DETR-DC5和DETR-R101模型,以预测COCO数据集中“stuff”和“thing”类别的边界框。新的掩码头训练了25个周期(具体细节见补充材料)。在推理过程中,我们首先过滤掉置信度低于85%的检测,然后计算每个像素的argmax,以确定每个像素属于哪个掩码。然后,我们将同一“stuff”类别的不同掩码预测合并为一个,并过滤掉空掩码(少于4个像素)。

主要结果:定性结果如图9所示。在表5中,我们将我们的统一全景分割方法与几种已建立的方法进行了比较,这些方法分别处理“thing”和“stuff”。我们报告了全景质量(PQ)以及“thing”(PQth)和“stuff”(PQst)的细分。我们还报告了掩码AP(在“thing”类别上计算),在进行任何全景后处理之前(在我们的情况下,是在进行像素级argmax之前)。我们展示了DETR在COCO-val 2017上的表现超过了已发表的结果,以及我们强大的PanopticFPN基线(使用与DETR相同的数据增强进行训练,以进行公平比较)。结果细分表明,DETR在“stuff”类别上特别占优势,我们推测编码器注意力所允许的全局推理是这一结果的关键因素。对于“thing”类别,尽管在掩码AP计算上与基线相比有高达8 mAP的严重不足,但DETR获得了有竞争力的PQth。我们还在COCO数据集的测试集上评估了我们的方法,并获得了46 PQ。我们希望我们的方法能够激发未来工作中对全景分割的全统一模型的探索。
在这里插入图片描述
在这里插入图片描述

5.结论

我们介绍了DETR,这是一种基于Transformer和二分图匹配损失进行直接集合预测的目标检测系统的新设计。该方法在具有挑战性的COCO数据集上实现了与优化后的Faster R-CNN基线相当的结果。DETR易于实现,具有灵活的架构,可以轻松扩展到全景分割,并取得了具有竞争力的结果。此外,它在大目标上的性能显著优于Faster R-CNN,这可能得益于自注意力处理的全局信息。

这种检测器的新设计也带来了新的挑战,特别是在训练、优化以及小目标性能方面。当前的检测器经过多年的改进才解决了类似的问题,我们期望未来的研究能够成功地为DETR解决这些问题。

6.致谢

我们感谢Sainbayar Sukhbaatar、Piotr Bojanowski、Natalia Neverova、David Lopez-Paz、Guillaume Lample、Danielle Rothermel、Kaiming He、Ross Girshick、Xinlei Chen以及整个Facebook AI Research巴黎团队的讨论和建议,没有他们的帮助,这项工作将无法完成。

相关文章:

  • WPS PPT设置默认文本框
  • pytorch小记(二十一):PyTorch 中的 torch.randn 全面指南
  • 系统架构设计(十一):架构风格总结2
  • 服务间的“握手”:OpenFeign声明式调用与客户端负载均衡
  • 自动化脚本开发:Python调用云手机API实现TikTok批量内容发布
  • OpenHarmony:开源操作系统重塑产业数字化底座
  • Linux服务器安全如何加固?禁用不必要的服务与端口如何操作?
  • Codex与LangChain结合的智能代理架构:重塑软件开发的未来
  • 当语言模型学会犯错和改正:搜索流(SoS)方法解析
  • 【Linux 学习计划】-- yum
  • 计网| 网际控制报文协议(ICMP)
  • 我的创作纪念日——《惊变256天》
  • arduino平台读取鼠标光电传感器
  • [逆向工程]C++实现DLL卸载(二十六)
  • 2025系统架构师---选择题知识点(押题)
  • 电容触摸按键PCB设计
  • Python训练营打卡 Day28
  • 一二维前缀和与差分
  • 十二、Hive 函数
  • 文件转Markdown工具有哪些
  • 看展 | 黄永玉新作展,感受赤子般的生命力
  • “先增聘再离任”又添一例,景顺长城基金经理鲍无可官宣辞职
  • 林诗栋/蒯曼混双取胜,国乒赢得多哈世乒赛开门红
  • 全国多家健身房女性月卡延长,补足因月经期耽误的健身时间
  • 信俗与共:清代新疆回疆儒释道庙宇的中华政教
  • 纪念|脖子上挂着红领巾的陈逸飞