ECCV2020-DETR笔记

ECCV2020-DETR-End to End Object Detection with Transformers

arxiv

[打开本地pdf](eccv2020-DETR-End to End Object Detection with Transformers.pdf)

github仓库

DETR的卖点是End-to-End, 它没有复杂的后处理,把目标检测问题当作集合预测问题,直接输出框(只是转换cxcywh和乘宽高)。大致的流程为

  1. cnn抽取特征

  2. 把特征送入transformer encoder-decoder, 输出N(本文N=100)个预测

  3. 训练时把这N个预测和gt做二分图匹配,匹配上的"预测-gt对",计算loss

  4. 预测时输出置信度大于阈值的框
    在这里插入图片描述
    稍微细节一点的流程举例如下
    在这里插入图片描述

  5. 如输入是3x800x1066的图片,经过cnn backbone后,输出2048x25x34的图像特征, 宽高降采样为1/8

backbone = nn.Sequential(
    *list(resnet50(pretrained=True).children())[:-2])
x = backbone(inputs)  # bx2048x25x34
  1. 这里需要一个transformer做encoder, decoder, 设置隐藏层维度hidden_dim为256,encoder, decoder内有6层,8头
transformer = nn.Transformer(256, 8, 6, 6)
  1. 图像特征需要transformer隐藏层保持一个维度, , 输出的图像特征维度是256x25x34
conv = nn.Conv2d(2048, 256, 1)
h = conv(x)  # bx256x25x34
  1. 图像特征要被拉平为序列,序列本身缺乏位置信息,需要给他们加上位置编码,位置编码其实就是一组维度和序列相同的向量,每个位置唯一即可(这里是根据论文的伪代码改编的,实际的代码里还是用的sine和learned), 维度须和图像特征一致
row_embed = nn.Parameter(torch.rand(25, 256 // 2))
col_embed = nn.Parameter(torch.rand(34, 256 // 2))
pos = torch.cat([
    col_embed.unsqueeze(0).repeat(25, 1, 1),    # bx25x34x128
    row_embed.unsqueeze(1).repeat(1, 34, 1)     # bx25x34x128
], dim=-1)                                      # bx25x34x256
  1. 将图像特征和位置编码融合(detr实际代码中,位置编码加在qk上, 这里的伪代码是在qkv都加了)。
pos = pos.flatten(0, 1).unsqueeze(1) # 850x1x256
h = h.flatten(2).permute(2, 0, 1)    # 850xbx256
encoder_input = pos + h              # 850xbx256
  1. transformer输出100个预测(设置的),decoder需要100个query, 维度也是256
object_query = nn.Parameter(torch.rand(100, 256))  # 100x256
object_query = object_query.unsqueeze(1)           # 100x1x256
tout = transformer(encoder_input, object_query)    # 100xbx256
  1. 全连接把100个预测转化为置信度和框坐标, 就是上图中的FFNs(Prediction Feed-forward networks)
linear_class = nn.Linear(256, 91)
linear_bbox = nn.Linear(256, 4)
logits = linear_class(tout)   # 100xbx91
bboxes = linear_bbox(tout)    # 100xbx4

DETR使用scipy.optimize.linear_sum_assignment来做预测和gt的匹配,它的输入是cost matrix,对于一张图就是100xnum_gt的矩阵,i行j列的值为第i个预测与第j个gt的loss, 它返回的是一组匹配的索引,这组匹配的总loss是所有可能的匹配中最小的。

在这之前需要计算每个预测和每个gt的loss,它包含

  • 分类loss: -prob[target_class]

  • L1loss: torch.cdist(out_bbox, target_bbox, p=1)

  • giou loss:

    • 在这里插入图片描述

为了好收敛吧,它在每层decoder的输出都算了loss, 辅助loss是一种常见的trick。

它最好的DETR-DC5-R101的AP=44.9,不如当时最好的检测网络(coco ap=58 huawei 2020-06-11), 他达到了detectron2中 Faster RCNN的水平,下表第一组是detectron中 Faster RCNN,第二组是使用了和DETR一样的训练策略,loss的Faster RCNN. 最后一组为DETR. 注意DETR-DC5-R101和Faster RCNN-R101-FPN+, 参数量相同,gflops相近,但是fps却只有faster rcnn一半,说明相同参数量和计算量下是比faster rcnn慢的。也说明参数量,gflops和速度fps没有直接的关系。DETR和第二栏的faster rcnn+比较,APL要高6个点,APS要低4个点,说明DETR对小物体表现差,对大物体表现好,毕竟没有加FPN之类的结构,也没有针对小物体做针对处理。
在这里插入图片描述
它对encoder的层数做了消融实验,层数越多,精度越高
在这里插入图片描述
对decoder的层数也做了实验,decoder层数越多,就越接近使用nms的性能
在这里插入图片描述
他们可视化了encoder中的自注意力,就是选择下图中4个参考点,并绘制出整图各位置和参考点的自注意力(应该是softmax(qk)),自注意力高的位置接近牛的分割mask了,他想说明encoder的自注意力学到了目标物的区域。
在这里插入图片描述
还可视化了decoder中object_query的注意力,表明decoder更关注物体的边缘区域。
在这里插入图片描述
下面这个消融实验非常有意思,spatial pos表示encoder部分的位置编码,output pos其实是object_query, 就是那100个query, 这是必须要使用的. encoder中spatial pos加在qk上,decoder中加在k上,output pos加在decoder的q上。

  • sine表示使用sin cos的位置编码

  • learned表示使用位置序号乘以可学习的weight作为位置编码

  • at input表示只加在输入上 (标准的transfomer)

  • at attn表示加在输入和encoder或decoder所有中间层上

  • none表示不使用位置编码

在这里插入图片描述
不使用spatial pos也有32的ap, 使用了spatial pos有明显提升(AP32->39), 最好的结果来自于每层都加位置编码,比标准的transformer(只加在输入)好1.4(AP39.2->40.6), spatial pos用sine at attn比用learned at attn好1.0(AP39.6->40.6)

在loss中,giou loss的提升最大, 下表AP35.8->39.9
在这里插入图片描述

DETR给了一份可读性很高的伪代码,很好滴帮助理解detr,前面的详细步骤也是照这个伪代码改的。过去也有人用集合预测做过目标检测,但是不work,detr 能work的主要原因还是在transfomer上. DETR给端到端的目标检测做了一个很好的示范。
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值