DETR论文翻译与理解

DETR(Detection with transformer)

DETR:End to End Object Detection with Transformer

论文链接:2005.12872 (arxiv.org)

参考视频:https://www.bilibili.com/video/BV1GB4y1X72R/?spm_id_from=333.788&vd_source=cdb0bc0dda1dccea0b8dc91485ef3e74

前言

2020年,Facebook使用Transformer进行目标检测。全新的架构,目标检测里程碑式工作。

之前目标检测中不论proposal based的方法还是anchor based 的方法,都需要nms(非极大值抑制)等候处理的方法筛选bbox(bounding box)。由于nms的操作,调参比较复杂,而且模型部署起来也比较困难。因此,一个端到端的目标检测模型是一直以来所追求的。

DERT很好的解决了上述问题,不需要proposal和anchors,利用Transformer全局建模的能力,把目标检测看成集合预测的问题。而且由于全局建模的能力,DETR不会输出太多冗余的边界框,输出直接对应最后bbox,不需要nms进行后处理,大大简化了模型。

摘要

将目标检测看作集合预测任务,不需要nms处理和生成anchor。DETR提出两个东西,一是目标函数,通过二分图匹配的方式,使得模型输出独一无二的预测,就是说没有那么多冗余的框了。二是,使用Transformer的编码器解码器架构。具体还有两个小细节,一个是解码器这边还有另外一个输入,learned object query,类似于anchors,DETR可以将learned object query和全局图像信息结合起来,通过不停的做注意力操作,从而使得模型直接输出最后的预测框。二是并行的方式,与2017Transformer用在NLP领域使用掩码解码器(自回归方式:一个单词一个单词翻译)不同,这里视觉任务中,图像中目标没有依赖关系。另一方面也是希望越快越好。DETR最主要的优点就是非常简单,性能也不错,在COCO数据集可以和Faster RCNN基线网络打平。另外,DETR可以非常简单的拓展到其他任务上,例如全景分割。

1.介绍

目标检测任务是对于每个这个感兴趣的物体区预测出框和物体类别,实际上就是集合预测问题,但是现在都是用间接的方式去处理集合预测的问题。例如proposal的方式,Faster R-CNN、Mask R-CNN、Cascade R-CNN。anchors方式,YOLO、Focal loss。还有no anchor based 的方法,用物体中心点(window centers)Center Net、FCOS。这些都没有直接去做这个几何预测的任务,而是设计了一个替代的,要么是回归要么是分类的任务去解决目标检测问题。但是其性能很大程度上受限于后处理这部操作,即NMS操作,因为这些方法都会生成冗余框,所以需要使用nms。

​ 为简化这些管道,本文提出一种直接集预测方法来绕过代理任务。这种端到端哲学导致了复杂结构化预测任务(如机器翻译或语音识别)的重大进展,但在目标检测方面还没有:以前的尝试要么添加了其他形式的先验知识,要么没有被证明与具有挑战性的冷基准的强大基线具有竞争力。本文旨在弥合这一差距。

不需要很多先验知识,就是端到端得出结果

在这里插入图片描述

DETR训练过程:

第一步用CNN抽特征。

第二步用Transformer编码器(encoder)去学全局特征,为了解码器(decoder)出预测框做铺垫。

  • 为什么使用transformer encoder
    • 如果使用了它,那么每一个点或者每一个特征就和图片里其他的特征都会有交互,因此它大概就知道哪里是该物体,哪里是另一个物体。对同一个物体来说,就应该只出一个框,而不是出好多框。所以这种全局的特征非常有利于移除这种冗余的框。

第三步,结合learned object query用Transformer解码器生成很多预测框。(有了图像的特征之后,会有一个object query,这个Object query就是限定了要出多少个框,然后通过query和这个特征不停地做交互,在decoder里做自注意力操作,从而得到了最后的输出的框,论文里选择的框数=100)

第四步,将预测框与GT框做匹配,在匹配上的框里做目标检测的loss。(100个框如何与Ground truth框做匹配算loss,作者把该问题看成了一个集合预测的问题,最后就能用这种二分图匹配的方法去算loss)

DETR推理过程:

第一步:用CNN抽特征。

第二步:用Transformer编码器去学全局特征,帮助后边做检测。

第三步:结合learned object query用Transformer解码器生成很多预测框。

第四步:置信度大于0.7的作为前景物体保留,其余作为背景

性能方面,在COCO数据集上,能和Faster RCNN打成平手,不论是AP还是模型规模和速度上。DETR对大物体检测效果比较好,不受限于生成anchor 的大小。但DETR在小物体上效果就差一点,但是作者很乐观,接下来会有跟进工作解决小物体检测问题。另一方面是DETR训练比较慢,作者训练了500个epoch,一般只需十几个epoch。

FPN对Faster RCNN通过使用多尺度多特征能够提升小物体的检测

不到半年Deformable DETR出现,不仅很好的通过这种多尺度的特征解决了小物体的问题同时也解决了DETR训练太慢的问题。

DETR对全景分割、目标追踪、视频里的姿态预测、视频里的语义分割等等各种任务。

2.相关工作

2.1 集合预测 set prediction

2.2 Transformer Decoder 并行

2.3 目标检测研究现状

现在研究都是基于初始预测进行检测,two stage 的方法基于proposal,signal stage的方法基于anchors(物体中心点)。最近的一篇论文做了一个详细的比较,之前的这些方法他们的性能与刚开始的初试的猜测非常相关,所以如何进行后处理得到最后的预测对最后的性能的影响是至关重要的。所以作者从两个方面阐述这件事情。

  • proposal和 anchors的联系:当anchor生成以后就要生成最终的Proposal了。首先对anchor有两部分的操作:分类和边框回归。分类通过softmax进行二分类,将anchor分为前景和背景,分别对应positive和negative。边框回归获取anchor针对ground true的偏移。得到这两个信息后开始选取符合条件的anchor作为Proposal。

    第一步:先将前景的anchor按照softmax得到的score进行排序,然后按设定值取前N个positive anchor;

    第二步:利用im_info中保存的信息,将选出的anchor由M×N的尺度还原回P×Q的尺度,刨除超出边界的anchor;

    第三步:执行NMS(nonmaximum suppression,非极大值抑制)

    第四步:将NMS的结果再次按照softmax的score进行排序,取N个anchor作为最终的Proposal;

1.set-based loss(集合的思想)

之前的工作有这种思想的:可以学习的NMS方法、关系型的网络,它们都可以利用类似于注意力的方法去处理物体之间的联系,从而最后能得出独一无二的预测,这样就不需要任何后处理的步骤了。但是这种算法的性能往往比较低,为了与当时比较好的方法性能对齐,这些方法往往加了人工干预,例如用手工设计的场景特征去帮助模型进行学习。但是DETR的目标是想让这个目标检测做的尽可能简单,所以他不希望这个过程特别复杂,也不希望用到过多的这种人工先验的知识。

2.recurrent detectors

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

3.DETR方法部分

3.1 目标检测集合预测的目标函数

DETR最后的输出是一个固定的集合,不论图片是什么,最后都会输出n个输出,这篇论文n=100,如何匹配预测框和ground truth的bounding box,如何算Loss,如何知道哪个预测框对应那个Ground truth框。所以作者将其转化成了一个二分图匹配的问题。

匈牙利算法主要用于解决任务分配问题,即如何将一组任务分配给一组工人,使得总成本最小化。这个问题可以形式化为一个二分图的最大匹配问题,其中每个工人和每项任务是二分图的两个顶点集合,工人与任务之间的成本构成了边的权重。

匈牙利算法解决二分图匹配问题。Scipy中有linear-sum-assignment函数,输入为cost matrix,输出为最优的方案。
在这里插入图片描述
目标检测的损失由两部分组成,一是分类的loss(分类类别对不对),二是目标检测框的准确度。(遍历所有的预测框,那这些预测的框与ground truth的框去算这两个loss,将这个loss放到cost matrix)。

这里找最优匹配的方式和原来利用先验知识去把预测和proposal和anchors匹配的方式一样,只不过这里的约束更强,一定要得到一个一对一的匹配关系,后续就不需要nms处理

在这里插入图片描述
一旦得到了最佳匹配,即知道生成的100个框中哪个与gt是最优匹配的框,就可以进一步与GT框计算损失函数,然后做梯度回传。

作者在这里发现第一部分分类loss去掉log对数,可以使得前后两个损失在大致的取值空间。第二部分边界框回归损失,不仅使用了L1-loss(与边界框有关,大框大loss),还使用了generalize iou loss(跟框大小无关的一个目标函数)。

3.2 DETR模型架构

在这里插入图片描述

第一步,输入3×800×1066,经过CNN得到2048×25×34,然后经过1×1的卷积降维得到256×25×34的特征图,加入位置编码后拉长得到850×256(序列长度850,嵌入维度256)。

第二步进入Transformer encoder得到850×256的输出(可以理解为做了全局信息的编码)。

第三步Transformer decoder的输入为可学习的object queries100×256(100个框256维度)+ encoder得到的全局特征是850×256。反复做自注意力操作,最后得到100*256的特征。encoder和decoder都是6层。decoder每层的输入输出都是100×256保持不变。

  • 补充材料里说明:在decoder里都会先做一次object query的自注意力操作。但是在第一层的decoder里是可以不做,可以省掉,但是后面那些层都不能省掉。目的:移除冗余框。因为它们互相通信之后就知道每个query可能得到什么样的框,尽量不要去做重复的框。
  • 在最后算loss的时候,为了让模型收敛的更快或者训练的更稳定,在这个decoder后面加了很多auxiliary loss,也就是加了很多额外的目标函数。这是一个很常见的trick,分割里经常使用。

第四步通过FFN也就是全连接层,每个框得到6个输出分别对应前景背景概率,框的边界信息(对角线两个坐标。)然后使用匈牙利算法计算最匹配的框,然后根据GT计算梯度,反向回传更新模型。

import torch
from torch import nn
from torchvision.models import resnet50class DETR(nn.Module):def __init__(self, num_classed, hidden_dim, nheads,num_encoder_layers,num_decoder_layers):super().__init__()# we take only convolutional layers from ResNet-50 modelself.backbone = nn.Sequential(*list(resnet50(pretrained=True).children())[:-2])# 投射层,将2048--->256self.conv = nn.Conv2d(2048, hidden_dim, 1)self.transformer = nn.Transformer(hidden_dim, nheads,num_encoder_layers, num_decoder_layers)# 一个FFN做类别的预测self.linear_class = nn.Linear(hidden_dim, num_classed + 1)# 一个FFN做框的预测self.linear_bboc = nn.Linear(hidden_dim, 4)# query objectself.query_pos = nn.Parameter(torch.rand(100, hidden_dim))# row_embedding和col_embedding是最开始与卷积神经网络的特征加在一起的固定的embeddingself.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):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)# flatten 将h拉直变成850*256的特征# transformer两个输入,前者是从图像得出的全局特征输入,后者是object query输入h = self.transformer(pos + h.flatten(2).permute(2, 0, 1),self.query_pos.unsqueeze(1))return self.linear_class(h), self.linear_bbox(h).sigmod()deter = DETR(num_classed=91, hidden_dim=256, nheads=8, num_encoder_layers=6, num_decoder_layers=6)
deter.eval()
inputs = torch.randn(1, 3, 800, 1200)
logits, bboxes = detr(inputs)

img

4.实验部分

4.1性能对比

在这里插入图片描述
gflops代表模型大小,FPS代表推理速度。虽然DETR的GFLOPS和参数量相对于Faster RCNN较少,但是推理速度还是稍微慢一点。对于小物体,Faster -RCNN比DETR要高4个点左右,但是对于大物体,DRTE要比Faster-RCNN高出6个点左右。作者认为DETR没有anchors尺寸的限制,并且使用的Transformer具有全局建模能力,对大物体比较友好。(APs小物体,AP_L大物体)

4.2 可视化

在这里插入图片描述

作者将transformer里的encoder即编码器的注意力可视化出来了,每个物体选一个点计算自注意力。我们可以发现,经过Transformer Encoder后每个物体都可以很好的区分开来了,这时候再去做目标检测或者分割任务就简单很多了。

在这里插入图片描述
不同深度的Transformer层对模型性能的影响。模型越深效果越好,并且没有明显的饱和的倾向。

4.3 Transformer解码器

在这里插入图片描述
把每个物体的自注意力用不同的颜色表示出来

对于小象和大象存在较大的重叠部分,大象用蓝色表示,大象的蹄子部分以及尾巴部分都是蓝色的标记。小象背部黄色的标记。这都说明解码器能够将两个目标各自的部分区分开来。另外就是斑马的条纹,DETR依然能够区分出每个斑马的轮廓并学到各个目标的条纹。

DETR的encoder是学一个全局的特征,让物体之间尽可能分得开。但是对于轮廓点这些细节(例如头尾巴这些极值点)就需要decoder去做,decoder可以很好的处理遮挡问题。

4.4 object query可视化

在这里插入图片描述

作者将COCO数据集上得到的所有输出框全都可视化出来。作者将100个object query中20个拿出来,每个正方形代表一个object query。每个object query相当于一个问问题的人,绿色代表小的检测框(bounding box),红色代表横向大的检测框(bounding box),蓝色代表竖向的大的检测框。

其实object query与anchor有点像,anchor是提前定义好一些bounding box,然后最后将预测的结果与这些提前定义好的bounding box做对比。object query是一个可以学习的东西,例如每次给它一个图片,第一个object query会不断查询左下角是否有小的目标,中间是否有大的横向的目标。当经过100个不同object query查询完成后,目标也就检测完成了。

5.结论

DETR在COCO数据集上与Faster R-CNN基线模型打成平手,并且在分割任务上取得更好的结果。最主要的优势是简单,可以有很大的潜能应用在别的任务上。作者又强调了一下,DETR在大物体上效果非常好(原因:自注意力带来的全局信息)。文章存在的缺点作者也自己指出:推理时间有点长、由于使用了Transformer不好优化、小物体上性能也差一些。后来,Deformable DETR解决了推理时间和小物体检测差的不足。

后续工作:omni-DETR;up-DETR;PnP-DETR;SMAC-DETR;Deformer-DETR;DAB-DETR;SAM-DETR;DN-DETR;OW-DETR;OV-DETR

DETR使用object query代替了原来生成anchors的方式,运用二分图匹配代替了nms这一步,将很多不可学习的东西变得可以学习了,从而得到了一个简单有效的端到端的网络,也因为其使用了transformer,所以后续在它上面做这种多模态的工作也多了很多,也在它的推动之下,后续还有pixel to sequence这篇论文将输入输出全部搞成序列的形式,从而能和NLP那边完美兼容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/54613.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++学习笔记(37)

302、makefile 在实际开发中,项目的源代码文件比较多,按类型、功能、模块分别存放在不同的目录和文件中,哪 些文件需要先编译,那些文件后编译,那些文件需要重新编译,还有更多更复杂的操作。 make 是一个强大…

mysql性能优化- 数据库配置优化

MySQL 性能优化 - 数据库配置优化 MySQL 是一个广泛使用的关系型数据库管理系统,但随着数据量的增长和访问频率的提高,其性能可能会成为瓶颈。为了保持高效的性能,除了应用层的查询优化和索引优化之外,数据库配置优化 也是非常重…

硬件工程师笔试面试——开关

目录 11、开关 11.1 基础 开关原理图 开关实物图 11.1.1 概念 11.1.2 常见的开关类型及其应用 11.2 相关问题 11.2.1 开关的工作原理是什么? 11.2.2 在设计一个电子系统时,如何选择最适合的开关类型? 11.2.3 不同类型的开关在实际应用中有哪些优势和局限性? 11.…

爵士编曲:爵士鼓编写 爵士鼓笔记 底鼓和军鼓 闭镲和开镲 嗵鼓

底鼓和军鼓 底鼓通常是动的音色,军鼓通常是大的音色。 “动”和“大”构成基础节奏。“动大”听着不够有连接性,所以可以加入镲片! 开镲 直接鼓棒敲击是开镲音色 闭镲 当脚踩下踏板,2个镲片合并,然后用鼓棒敲击&am…

C++ Linux IPC进程通信-消息队列MQ

原文链接&#xff1a;C Linux IPC进程通信-消息队列MQ 消息队列库<sys/msg.h> 相比于共享内存和管道,消息队列能够实现指定的消息格式和排序,能实现更复杂的通信 库函数 // 创建消息队列 int msgget(key_t, key, int msgflg); return ID(成功) -1(错误)key为一个标记…

java(3)数组的定义与使用

目录 1.前言 2.正文 2.1数组的概念 2.2数组的创建与初始化 2.2.1数组的创建 2.2.1数组的静态初始化 2.2.2数组的动态初始化 2.3数组是引用类型 2.3.1引用类型与基本类型区别 2.3.2认识NULL 2.4二维数组 2.5数组的基本运用 2.5.1数组的遍历 2.5.2数组转字符串 2.…

面向对象程序设计——set容器の简析

1.set的介绍 • 序列式容器和关联式容器 • 我们已经接触过STL中的部分容器如&#xff1a;string、vector、list、deque、array、forward_list等&#xff0c;这些容器统称为序列式容器&#xff0c;因为逻辑结构为线性序列的数据结构&#xff0c;两个位置存储的值之间⼀般没有紧…

图片马赛克处理(Java)

1.需求 给图片的指定区域打码给整张图片打码马赛克方格取色支持中心点取色和随机取色马赛克支持灰度处理 2.源码 package com.visy.utils;import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOE…

screen使用——关机时在服务器上跑代码

一、连接服务器 原理:通过 SSH(Secure Shell)协议建立本地与远程服务器的安全连接通道,使得可以在本地操作服务器。 操作:使用 VSCode 或 cmd 的 ssh 连接到服务器,这里我选择cmd。 检查是否安装 OpenSSH 在 Windows 10 及以上版本中,系统可能已经自带 OpenSSH 客户端…

(k8s)Kubernetes部署Promehteus

转载&#xff1a;Kubernetes&#xff08;k8s&#xff09;部署Promehteus 一、概述 在1.8版本以后heapster由metrics-server替代&#xff1b;从k8s的v1.11版本开始已经全面转向以Prometheus为核心的新监控体系架构&#xff1b;kube-prometheus 中包含了 prometheus 监控所用到的…

Kubernetes(K8S)实战:构建高可用的微服务架构

Kubernetes(K8S)实战:构建高可用的微服务架构 在云计算与容器化技术日新月异的今天,Kubernetes(简称K8S)凭借其强大的容器编排能力,已成为企业构建云原生应用的首选平台。本文将深入探讨Kubernetes的核心概念、架构设计原则,并通过一个实际案例——构建一个高可用的微…

pg入门18—如何使用pg gis

1. 下载postgre gis镜像 2. 运行镜像 docker run -p 15432:5432 -d -e POSTGRES_PASSWORDAb123456! postgis/postgis:12-3.4-alpine 3. 使用gis # 进入容器&#xff0c;登录pgdocker exec -it bash# 登录数据库psql -U postgres# 创建数据库CREATE DATABASE mygeotest;# 使用…

算法:双指针题目练习

文章目录 算法:双指针移动零复写零快乐数盛最多水的容器有效三角形的个数查找总价格为目标值的两个商品三数之和四数之和 总结 算法:双指针 移动零 定义两个指针,slow和fast.用这两个指针把整个数组分成三块. [0,slow]为非零元素,[slow1,fast-1]为0元素,[fast,num.length]为未…

数据库面试题整理

数据库面试题整理 整理了下常见的有关数据的面试题&#xff0c;持续更新中 1. mysql数据库事务的四个特性&#xff1a; 原子性&#xff08;Atomicity&#xff09;&#xff1a;事务要么做&#xff0c;要么不做一致性&#xff08;Consistency&#xff09;&#xff1a;使数据库从…

Nginx泛域名 解析的匹配前缀绑定或转发到子目录

网站的目录结构为&#xff1a; # tree /home/wwwroot/landui.com /home/wwwroot/landui.com ├── bbs │ └── index.html └── www └── index.html 2 directories, 2 files /home/wwwroot/landui.com为nginx的安装目录下默认的存放源代码的路径。 bbs为论坛…

GPU使用

0. 写这篇文章的背景 最近还是在使用GPU、连接远程服务器上出现了一点问题,发现在这方面的知识还是学得很模糊。(最让人感到困惑的是之前GPU的使用都没有问题) 总结一下最近的问题: 1.每一次连接远程服务器(选择的Ubuntu22.04),使用服务器的文件夹还好(关键是现在用…

YARN性能优化高频面试题及答案

目录 高频面试题及答案1. 什么是YARN?它在Hadoop生态系统中的作用是什么?2. 如何通过合理配置`Container`大小来优化YARN性能?3. 如何通过调整`ResourceManager`的调度策略优化YARN性能?4. 如何优化YARN中`ResourceManager`和`NodeManager`的内存配置?5. 如何通过调节`Map…

【Web】御网杯信息安全大赛2024 wp(全)

目录 input_data admin flask 如此多的FLAG 一夜醒来之全国CTF水平提升1000倍&#x1f60b; input_data 访问./.svn后随便翻一翻拿到flag admin dirsearch扫出来 访问./error看出来是java框架 测出来是/admin;/路由打Spring View Manipulation(Java)的SSTI https:/…

基于ECC簇内分组密钥管理算法的无线传感器网络matlab性能仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于ECC簇内分组密钥管理算法的无线传感器网络matlab性能仿真&#xff0c;对比网络通信开销&#xff0c;存活节点数量&#xff0c;网络能耗以及数据通信量四个指标…

Unity射击游戏开发教程:(36)敌人关卡生成器的设计和开发

丰富多样地游戏关卡生成器能自动生成不同的关卡地图和游戏内容,以增加游戏的可玩性和挑战性。关卡生成可以基于随机算法或者预设的规则生成不同的地图布局、敌人位置、道具位置等。 定义关卡生成器WaveSpawner 如何设置通用的 Wave Spawner?我将此 Wave Spawner 脚本附加到…