从代码角度理解DETR

news/2024/11/29 4:39:20/

  1. 一个cnn的backbone, 提图像的feature, 比如, HWC.
  2. 同时对这个feature做position_embedding.
  3. 然后二者相加 (在Transformer里面就是二者相加)
  4. 输入encoder,
  5. 输入decoder (这里有object queries.)
  6. 然后接Prediction Heads, 比如分类和回归.

下面的代码参考自: https://github.com/facebookresearch/detr
commit-id: 3af9fa8
在这里插入图片描述
可以看到, 这里传入的有backbone, transformer, 输入的类别个数(用来确定head的输出维度), num_quries, 以及是否需要aux_loss等.

先看一下forward的解释
在这里插入图片描述
输入是一堆图片和对应的mask. 这里mask先不管. 后面再来细看其具体起的作用;
输出是logits, boxes, 还有aux_outputs(只有在用aux_loss的时候才会有这个的输出)

接下来看第一步
在这里插入图片描述

backbone部分

从这里在这里插入图片描述
可以看出来, backbone是这两个的结合.
在这里插入图片描述
也就是说最终backbone输出的第一个其实是图像backbone提的feature, 第二个是每个feature所对应的 position encoding.

Transormer部分

transformer的输入如下

在这里插入图片描述
由于没有跑代码. 这里
src: 先理解成是images的feature, pos[-1], 先理解成是position-encoding

这里input_proj. 是对输入的src做了一个FC.
在这里插入图片描述
这里的query_embed是

在这里插入图片描述
可以理解成是一个query的词典表.

之后如图
在这里插入图片描述
encoder部分和原始transformer是一致的, 而decoder部分, 原始transformer输入的是trg_seq. 而这里是一个全0的矩阵. 大小与query_embed一样大.

之前transformer的decoder中是trg_seq 与 src_seq的encoder的output 做encoder-decoder-attention. 但是现在detr里的decoder中, 到现在还没有用到groundtruth.

head部分

在这里插入图片描述
这里bbox的coord取sigmoid的原因是gt是按图像的长宽给的比例.
在这里插入图片描述

aux_loss

loss部分

bbox-loss. 采用的有 l1-loss 以及giou loss, 这里用giou-loss的原因是scale-不变.

在这里插入图片描述

SetCriterion

在这里插入图片描述

这里写得很清晰, 即对gt和dt做一次Hungarian匹配, 然后, 将匹配到的pair, 去算loss, loss包括类别和bbox.
我理解这个过程相当于label-assign, 只不过特殊的地方是这个label-assign 是一个一对一的, 这是和之前一些一阶段和二阶段检测不太一样的地方. 比如使用anchor的方法中, 可能多个anchor会对应到一个gt上面, 这也是为啥那些方法的后处理中要使用NMS, 相当于是一种搜索排查式的检测方式,先检测出一堆proposals, 再选出置信度较高的.

loss_cardinality

这其实不是一个loss, 就是为了统计预测的object的数量与ground-truth数量之间的差异. 用来观测.

HungarianMatcher

这个就是一个匈牙利匹配, 用的 from scipy.optimize import linear_sum_assignment, 这里用pytorch的方式封装了一下.

mask起的作用

二维positionEncoding的细节

paper-reading

Abstract

  1. 把目标检测视为一个集合预测问题. 从设计上去掉了很多的人为操作,比如anchor设定, nms 等.
  2. 更关注object与image context 之间的本质, 直接去预测最终的结果集合. 而非"搜索式检测"
  3. 不需要开发额外的库,比如roi-align, roi-pooling, 这些操作…
  4. 很容易换一个head就可以去做分割的任务,

pipline


整个Pipline看上去很好理解, 细节主要体现在 图像的backbone的features如何转化成为 word-embeding似的输入, 进入到transformer中.

在大目标上面要比小目标上好

在这里插入图片描述
这里解释说在大目标上效果比较好是因为transormer的non-local的机制, 这一点我的理解是, transformer由于内部的self-attention操作, 使得输入的一句话中每一个词彼此之间都会去算attention的加权分数。 所以哪怕是某一个词的预测,它也是依赖于整个句子的. 所以是一个non-local的操作.
而小目标, 因为占据的图像中的位置比较少. 别的位置对于这个小目标的attention不那么重要, 因此这种non-local的操作,对于小目标不太友好.
当然作者也提了可以用其他的方式来缓解小目标不好的问题, 比如FPN.

训练时间长

在这里插入图片描述

对于set prediction问题, 两个重要的部件

set prediction loss

这个主要用于在predictin和ground-truth之间建立one-one map.
DETR是预测N个objects, N是一个超参, 比如100.

能够预测objects以及他们之间关系的模型结构. 这里就是指的是DETR

backbone

在这里插入图片描述
比较好理解,就是正常的 2d-backbone.

encoder

在这里插入图片描述
关键的部分也都在上面标出来了.

decoder

在这里插入图片描述

说实话,没太理解 N个, object-query 到最后为啥能够预测 N个 final predictions. 背后的原因是啥?

prediction Heads

这个就是正常的heads.

auxiliary losses

为了帮助模型训练, 在每个decoder层后面, 加了PredictionHeads 和Hungarian loss 来做监督, 并且这些 层是share 参数的.
在这里插入图片描述

实验对比

encoder层的影响

从下表可以看出来, 用encoder还是很有用的.
在这里插入图片描述

而且有可视化结果证明, encoder 层似乎已经把目标分离开来了.
在这里插入图片描述

decoder层数的影响

在这里插入图片描述

  1. decoder层数的增加, 效果变好,
  2. 当decoder层数只有一层的时候, NMS有用.
  3. 当decoder层数大于一层的时候, NMS几乎没有什么用.
    这说明 单个decoder层不足以表现不同输出间的关系.
    在这里插入图片描述

FFN层的重要性

去掉之后会掉点.
在这里插入图片描述

PositionEncoding 的重要性

  1. spatioal position encoding 在encoder 和decoder 中都非常重要. 没有的话会掉6个点左右.
    在这里插入图片描述

object_query

从代码里看, 是这样的流程.

在这里插入图片描述
比如 num_queries 是100, 而 hidden_dim 是64的话.

那么query_embed.weight 也是 [100, 64] 维的.

这里进去encoder的, tgt 每次其实都是0. 而query_embed.weight 充当的是query_pos.

我理解这个就是上面说的, output position encodings.

因此当normalize_before=False的时候, decoder的时候会直接走forward_post,
从下面的代码可以看出
在这里插入图片描述

在decoder的时候, 最初的一层的输入, 因为tgt都是0, 所以 q=k=query_pos.

所以这里的object_query 其实就是随机初始化的 query_embed.weight.

这里解释下nn.embedding 是什么意思.

nn.embedding可以理解为是一个词嵌入模块. 它是有weight的. 这是一个可以学习的层, 有参数,类似于conv2d.

比如上面的例子中, query_embed 就可以理解为是一个词典, 只不过这个词典有点小, 只有100个词, 每个词的embedding的大小是64.
forward的时候,可以传入indices, 来得到对应的每个单词的embeddings. 可以传入batch的indices.

推理的时候query_embed充当什么角色?


http://www.ppmy.cn/news/96028.html

相关文章

Ovirt 开源虚拟化平台安装

ovirt官网 一、资源规划介绍 1.1、服务规划 ovirt版本 ovirt engine 4.3.10 ovirt node 4.3.10 ovirt.node01.opsvv.com 负责托管引擎服务 1.2、资源划分 1.2.1、节点划分 密码均为:12345678 Node02无法开启虚拟化,只演示加入集群节点使用 节点…

Mac下好用的日记、电子书阅读器、RSS订阅软件​

Mac下好用的日记笔记本、电子书阅读器和RSS订阅、播客订阅等软件推荐。我们收录到 Mac下好用的日记、电子书阅读器、RSS订阅软件​http://www.webhub123.com/#/home/detail?pLZPL-2ofIu 收录效果如下 ​也可以使用分组视图来查看各类软件网址 ​ 登录后可一键保存全部软件网址…

C语言中获得结构体成员的相对偏移量(Linux内核源码解读)

问题起源 这篇文章的起源是读到了一句代码 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)这是一个宏定义,这个宏定义来自Linux内核源码,它的作用是获取一个结构体中的变量相对于这个结构体的偏移量。这么讲有点抽象&#xf…

Pandas识别中文日期,这4步轻松搞定!

在使用Pandas处理含有中文日期的CSV文件时,中文日期列无法直接被识别为datetime类型,这会造成该列无法进行时间序列操作。那么,如何让Pandas正确解析中文日期列,并将其转换为datetime64类型呢? 今天分享在Pandas识别中文日期的4大…

15_Linux工程目录与顶层Makefile

目录 Linux 工程目录分析 顶层Makefile详解 make xxx_defconfig过程 Makefile.build脚本分析 make过程 built-in.o文件编译生成过程 make zImage过程 Linux 工程目录分析 将正点原子提供的Linux源码进行解压,解压完成以后的目录如图所示: 图就是正点原子提供的未编译的…

C++高性能优化编程之如何测量性能(一)

系列文章目录 性能测量 系列文章目录1、为什么要进行性能优化2、性能测试的指标是什么3、测量性能及改善变更记录文档4、性能测量分析工具的使用4.1、使用Linux Perf性能分析器进行性能测量分析4.2、使用Google GperfTools性能分析器进行性能测量分析 5、性能测量微基准测试分析…

Webpack打包图片-JS-Vue

1 Webpack打包图片 2 Webpack打包JS代码 3 Babel和babel-loader 5 resolve模块解析 4 Webpack打包Vue webpack5打包 的过程: 在webpack的配置文件里面编写rules,type类型有多种,每个都有自己的作用,想要把小内存的图片转成bas…

nodejs+vue大学生招聘网站应聘系统设计与实现5b14b

目前,伴随着Internet技术的日益成熟,互联网需要提供更多的服务,发达国家已形成以信息技术为核心,招聘网站支撑的现代化招聘公司技术格局。这便是今天为大家所熟悉的管理信息系统,网络发展为招聘网站实现信息化、自动化、智能化和集…