大部人还是跟随潮流,把最近热门的技术看看是否能迁移过来。于是……看看
Transformer
DERT——2020
特点
- 利用transformer,将目标检测问题转换为无序集合预测问题【更加直接,目标检测本身其实就是个无序集合的问题】
- 可解释性好;比如对于一个query id=1,那么得到的输出应该是类别为1这个目标的可能所在地;自注意力机制可以理解为对于某一个点,会将同属于这一个物体的像素都给attention到
- 不需要设置anchor,超参数极少,不需要NMS
结构
先用CNN提取特征,论文中用ResNet50【所有BN固定,stem「数据预处理层」和第一个stage不进行更新,学习率小于transformer】
image: (batch, 3, 800, 1200) -> ResNet50 -> (batch, 1024, 25, 38)
将特征变为特征序列,论文中仅用了最后一个stage,并进行降维
(batch, 1024, 25, 38) -> 1*1 conv -> (batch, 256, 25, 38)
将特征序列与位置信息特征相加后,输入到编码器中,输出长度为N的无序集合
(N=100, batch, 256)
;再将输出送入一组解码器中,【解码器的个数越多越好,但是效率的问题,因此论文选择了6个】输出向量(6, batch, 100, 256)
N是指定的,表示一张图片最多包含的物体数目;但不足够的,用no object填充,表示为背景类别;论文中取了100,需要考虑不同数据集
这个集合中每个元素包含物体类别和坐标
编码器:Q、K表示图像特征和位置编码的信息和;V表示图像特征;Object queries作为解码器中引入的新Q,询问某一个Object是否在,然后根据图像的信息做相似计算,那么这个位置的特征就会有一个加权输出。
位置信息特征编码这里用了sincos模式,需要考虑x,y两个方向
123456789101112131415161718192021222324252627282930#输入是b,c,h,w#tensor_list的类型是NestedTensor,内部自动附加了mask,#用于表示动态shape,是pytorch中tensor新特性https://github.com/pytorch/nestedtensorx = tensor_list.tensors # 原始tensor数据# 附加的mask,shape是b,h,w 全是falsemask = tensor_list.masknot_mask = ~mask# 1 1 1 1 .. 2 2 2 2... 3 3 3...y_embed = not_mask.cumsum(1, dtype=torch.float32)# 1 2 3 4 ... 1 2 3 4...x_embed = not_mask.cumsum(2, dtype=torch.float32)if self.normalize:eps = 1e-6y_embed = y_embed / (y_embed[:, -1:, :] + eps) * self.scalex_embed = x_embed / (x_embed[:, :, -1:] + eps) * self.scale# 0~127 self.num_pos_feats=128,因为前面输入向量是256,编码是一半sin,一半cosdim_t = torch.arange(self.num_pos_feats, dtype=torch.float32, device=x.device)# 归一化dim_t = self.temperature ** (2 * (dim_t // 2) / self.num_pos_feats)# 输出shape=(b,h,w,128)pos_x = x_embed[:, :, :, None] / dim_tpos_y = y_embed[:, :, :, None] / dim_tpos_x = torch.stack((pos_x[:, :, :, 0::2].sin(), pos_x[:, :, :, 1::2].cos()), dim=4).flatten(3)pos_y = torch.stack((pos_y[:, :, :, 0::2].sin(), pos_y[:, :, :, 1::2].cos()), dim=4).flatten(3)pos = torch.cat((pos_y, pos_x), dim=3).permute(0, 3, 1, 2)# 每个特征图的xy位置都编码成256的向量,其中前128是y方向编码,而128是x方向编码return pos # (b,n=256,h,w)与原始transformer的不同之处:
- DERT对每个编码器都输入了同一个位置编码向量;而原始的只在第一个编码器中输入了位置编码向量
- DERT将位置编码向量只加入到了QK中,V中没有加入
- DERT解码时将N个无序框并行输出(因为框的顺序不重要,前后框之间也没有什么特别的关系,因此通过一个全0的查询向量,作为BOS_WORD即可);原始的是按照句子按序解码输出的,并且会运用到前面所有解码器的输出信息
- 额外引入可学习的Object queries,相当于可学习的anchor,提供全局注意力
- 可以认为是输出位置编码,主要是在学习过程中提供目标对象和全局图像之间的关系;相当于全局注意力【相当于是一个说明目标相对位置关系的东西,类似于anchor,只是这个是可学习的】
- 但是每个object query都和全局的特征图做attention交互,这本质上也是dense。
将最后一个解码器的输出,送入分类和回归的head中,得到N个无序集合
将无序的预测结果进行后处理,正负样本分配是one-to-one的双边匹配算法optimal bipartite matching——匈牙利算法来匹配【最优分配问题】,提取得到前景类别和对应bbox的坐标。相当于把无序的结果排了个序。【这里实际上比one-stage那么多的anchor匹配好;也不需要two-stage先进行proposal的操作】
12# 根据A和B集合两两元素之间的连接权重,根据重要性进行内部最优匹配scipy.optimize.linear_sum_assignment()将预测的坐标,复原到原始图片上,即乘以
(800, 1200)
.
算法
|
|
RelationNet++:Bridging Visual Representations for Object Detection via Transformer Decoder——NeurlPS2020
针对的问题
- 现有的目标检测框架通常建立在object/part表示的单一格式上,由于异构或非均一性,通常很难将这些表示形式组合(从不同方面提取网络特征)到单个框架中,因此用了注意力机制,以充分利用每种优势。目前的表示有:
- anchor/proposal矩形框
- 中心点:对分类好
- 角点(CornerNet):对定位好
特点
- 提出了一种基于注意力的解码器模块:BVR,类似于transformer,将不同的visual representations bridge起来。
结构
BVR模块
由于特征图上的每一点都可以作为注意力机制中的Key,但是这样导致特征点过多,同时几何项很耗费计算与内存资源
- Key采样,topk采样,用max pooling操作
- 共享位置嵌入:为了减少复杂度
Decoder:multi-head attention
Point head网络预测Key的值:auxilliary特征作为key
用key去增强query的主特征
S表示query和key在外观和几何上的相似度,由于query和key的几何特征不一致(bbox是4d,点的表达是2d),因此先从bbox中提取中心点或角点得到2d表示之后,再计算相似性;外观相似性通过内积计算;几何相似性用小网络计算得到相对位置信息
T将Key的外观特征通过线性变换得到value特征;
计算出的attention,直接加在原始的query特征上
Non-local
输入信号x(feature map),首先用f计算i和j的相似度(等效于attention中计算q和k的相似度),然后和g函数计算出的j位置表示相乘(等效于attention中的positional embedding),最终通过响应因子C(x)进行标准化处理。
GNN
转载请注明出处,谢谢。
愿 我是你的小太阳