Bootstrap

DETR:使用Transformer进行端到端的目标检测

写在前面

DETR将目标检测问题视为集合预测问题,即一次性预测出不包含重复元素的目标集合。而现代多数检测器则是通过在大量的anchor上定义回归和分类代理问题来间接实现集合预测,性能受到以下因素的显著影响:

  • 用于消除重复预测框的后处理;
  • anchor集合的设计方法;
  • 将target分配给anchor的启发式方法。

DETR简化了检测管线,移除了很多需要人工设计的部分,例如NMS和anchor生成等。在给定一组小数量可学习的object queries,DETR就可根据对象和全局图像的上下文关系并行输出最终预测结果的集合。

算法框架其主要部分有两个:

  • 通过二分图匹配(bipartite matching)强制进行预测框与GT一对一匹配的基于集合的全局损失;
  • Transformer encoder-decoder架构。

在COCO检测数据集上达到了与Faster R-CNN相当的准确率和运行性能。其中在大尺寸物体表现出更好的性能,文中指出可能是因为transformer的非局部计算(non-local computations)特性提升了大尺寸物体的性能。


根据上述信息,可以提出以下问题:

  • object query是什么?怎么获得?作用是什么?
  • 二分图匹配是什么?作用是什么?具体过程是什么?
  • 如何做到没有NMS还能实现一个物体只有一个预测框?

带着上述疑问,在论文中寻找答案。


一、图论基础知识

因为文中涉及二分图匹配,所以先补充一些图论的基础知识,了解什么是,什么是二分图,什么是二分图匹配

1. 图论中图的定义

一个图可以形式定义为一个二元组: G = ( V, E ),其中:

  • V 是顶点(结点)的有穷集合。
  • E是连接V中两个不同顶点(顶点对)的边的有限集合。

 如果E中的顶点对是有序的,即E中的每条边都是有方向的,则称G为有向图。如果顶点对是无序对,则称G是无向图

2. 二分图匹配(bipartite matching)

(1)二分图

图的所有顶点可分为两个集合每条边对应的两个顶点分别属于这两个集合。设G=(V,E)是一个无向图,如果结点集V可分割为两个互不相交的子集(V1,V2),并且图中的每条边(i,j)所关联的两个结点i和j分别属于这两个不同的结点集,则称G为一个二分图。


(2)匹配

给定一个二分图G,在G的一个子图M中,M的边集{E}中的任意两条边都不依附于同一个顶点,则称M是一个匹配。翻译成大白话:匹配就是一组边,其中没有两条边共用一个顶点。

(3)极大匹配

在给定图中,无法通过添加任何一条边来扩展匹配而不违反匹配的定义。即极大匹配是这样的匹配:若再试图添加任何一条边,就会出现至少有一个顶点被两条边共用的情况。

 (4)最大匹配

所有匹配中边数最多的匹配。


DETR将预测框与gt配对问题视为二分图最大匹配问题,即预测框为一个顶点集合,gt为另一个顶点集合,以此来实现每个gt对应一个预测框的一对一模式。

为什么是最大匹配呢?因为每个gt都要求有一个预测框与其连接(匹配),而这是边数最多的情况,所以是二分图最大匹配问题(为了表述方便,下文均简称为二分图匹配)。但并不是说随便找一组与gt数目相同的预测框就行,我们需要衡量这组预测框是不是最优的一组,因为预测框与配对的gt之间可以计算损失(回归loss和分类loss),损失最小的一组预测框是我们想要的。文中采用匈牙利匹配算法解决二分图匹配问题。

3.匈牙利匹配算法

略…………

二、DETR模型

1. 目标检测集合预测损失(object detection set prediction loss)

DETR每次推理都会得到固定数量N个预测框(N通常要远大于图像中可能出现的物体数量,文中N设置为100)。那既然模型每次都会输出N个预测结果,那如何对这N个预测结果进行评价(类别,位置,尺寸等)?

文中根据匹配代价函数(match cost)通过匈牙利匹配算法在预测结果和gt中产生一个最优的二分图匹配,然后对该组合中的预测结果进行优化。该过程建模公式、匹配代价函数如下所示:

  • y:GT的集合,使用\varnothing(no object)填充到N的大小,对于每个GT可以看作y_{i}=(c_{i},b_{i})c_{i}表示类别(可能是\varnothing),b_{i}\in [0,1]^{4}表示GT中心点坐标和相对于图像尺寸的高宽;
  • \widehat{y}=\{\widehat{y_{i}}\}^{N}_{i=1}:表示N个预测结果的集合,\widehat{p}_{\sigma(i)}(c_{i})表示索引为\sigma(i)的预测框类别为c_{i}的概率,边界框表示为\widehat{b}_{\sigma(i)}
  • \widehat{\sigma}:表示最优组合;
  • \sigma(i):预测结果的索引;
  • \mathfrak{S}_{N}:N个元素所有可能排列构成的空间。

上述过程的作用完成正负样本的定义,即分配给GT的预测框就是正样本,其他的为负样本,一个GT只会分配到一个预测框,是一对一的关系;而传统检测器通常使用IoU阈值进行正负样本的定义,通常一个GT会分配到很多预测框,是一对多的关系。


完成正负样本定义后,接下来就需要计算loss(文中表述为Hungarian loss)对上一步得到的所有匹配对进行优化。损失函数定义如下:

 根据公式可知,c_{i}\varnothing时不计算box损失,且实际过程中,为了平衡正负样本的loss,c_{i}\varnothing时会对对数概率项的权重降低为1/10。

一个细节需要注意:在匹配代价函数中,直接使用了类别的概率;而在损失函数计算中,使用的是概率的负对数。文中给出的解释是This makes the class prediction term commensurable to \mathcal{L}_{box},即让类别预测项和box损失具有可比性。我个人理解:box损失范围是有限的(因为图像大小是有限的),类别概率的范围是[0 ,1],但概率的负对数范围是负无穷到0且是非线性的,为了让类别预测项与box损失项的贡献具有可比性,所以在匹配代价函数中使用的是概率而非概率的负对数。 


 Bounding box loss采用了L1 Loss和GIoU Loss 。

 2.DETR结构

根据上图可知,DETR模型结构主要分为四部分:

  • backbone:用于提取图像特征;
  • encoder:对特征进行进一步增强;
  • decoder:完成query与自身的交互以及query与encoder输出的交互;
  • FFN:根据decoder最后一层的输出预测box和class。

接下来分别对上述结构进行介绍。


(1)Backbone

文中使用了ResNet-50作为backbone,结构没啥好说的,主要讲一下图像在backbone前向推理过程中的维度变化。例如一张高宽为别为H_{0}W_{0}的三通道图像,经过Backbone后通道数C=2048,高宽分别下采样了32倍,即变成了H=\frac{H_{0}}{32}W=\frac{W_{0}}{32},后续将输入到encoder中。


(2)Encoder

首先通过一个1×1卷积压缩通道数,将2048维压缩到更小的维度d(实际压缩到了256维)。因为encoder的期望输入是序列的形式,所以把特征图进一步展平,得到H\times W个序列,每个序列维度是d。

# 用于压缩维度
self.input_proj = nn.Conv2d(backbone.num_channels, hidden_dim, kernel_size=1)

encoder每由多层(DETR用了6层)encoder layer组成,每一层都是由一个多头自注意力机制模块和一个前馈网络(feed forward network)组成,空间位置编码在每一层的多头自注意力模块都会输入。

(3)Decoder

 结合图例我们可以看出,decoder也是由多层(文中同样设置为6层)decoder layer组成,每一层由多头自注意力模块(query在其内部与自身进行交互,可以起到NMS的作用)和多头交叉注意力模块组成。

但需要强调的是,图中decoder的输入实际有两个,分别是:

  • query:维度为(100, 256),初始值全为0且不可学习;
  • object query:维度(100,256),随机初始化且可学习,作用是学习位置信息,在decoder每一层的注意力模块都会输入。
# object query初始化代码
self.query_embed = nn.Embedding(num_queries, hidden_dim)

# query初始化代码
tgt = torch.zeros_like(query_embed)

因此,decoder第一层输入的q=k=query+object query,v=query。

(4)Prediction feed-forward networks(FFN)

最后的检测框的预测由两个分支完成:

  • 使用ReLU激活函数的3层的多层感知机,负责预测边界框归一化的中心点坐标,和相对于图像尺寸的高宽参数;
  • 使用softmax函数的线性映射层,负责预测边界框的类别。 
# 类别预测分支
self.class_embed = nn.Linear(hidden_dim, num_classes + 1)
# box预测分支
self.bbox_embed = MLP(hidden_dim, hidden_dim, 4, 3)

(5)辅助loss

作者发现在训练期间在decoder每一层后添加prediction FFN和Hungarian loss是有帮助的,特别是可以帮助模型输出每一类物体正确的数量。所有prediction FFN共享参数。

三、总结

实验部分应该很好理解,这里就不再分析,最后做个总结。

DETR提出了一种简洁的端到端的目标检测框架,通过匈牙利算法在训练过程中实现了预测框与GT的一对一匹配,同时decoder中的自注意力机制可起到类似于NMS的作用,因此实现了集合预测的效果。就性能而言,如此简洁的框架可以达到与发展多年的Faster R-CNN相媲美的性能,展示出了巨大的发展潜力。

但仍然存在以下不足:

  • 训练时间较长;
  • 与Faster R-CNN相比小目标性能较差;
  • 达不到SOTA效果。

;