04 感知:3D目标检测 注意力机制

1. DETR 2020(DEtection TRansformer)End-to-End Object Detection with Transformers

Best Ref: 理解DETR

可以将DETR视为一个从图像序列到一个集合序列的转换过程。该集合实际上就是一个可学习的位置编码(文章中也称为object queries或者output positional encoding,代码中叫作query_embed)。

1. pos_embed (位置编码)

transformer位置编码:

\[\begin{cases} PE(pos, 2i) = sin(pos/10000^{2i/d_{model}}) \\ PE(pos, 2i+1) = cos(pos/10000^{2i/d_{model}}) \end{cases} \]

pos是词向量在序列中的位置,i是channel的索引。

DETR中位置编码:为二维特征在图像x和y方向分别编码,每个维度编码长度为特征向量长度一半。这样两个维度编码特征拼接后,构成和图像特征长度相等的向量。

class PositionEmbeddingSine(nn.Module):
    """
    This is a more standard version of the position embedding, very similar to the one
    used by the Attention is all you need paper, generalized to work on images.
    """
    def __init__(self, num_pos_feats=64, temperature=10000, normalize=False, scale=None):
        super().__init__()
        self.num_pos_feats = num_pos_feats
        self.temperature = temperature
        self.normalize = normalize
        if scale is not None and normalize is False:
            raise ValueError("normalize should be True if scale is passed")
        if scale is None:
            scale = 2 * math.pi
        self.scale = scale

    def forward(self, tensor_list: NestedTensor):
        x = tensor_list.tensors
        mask = tensor_list.mask
        assert mask is not None
        not_mask = ~mask
        y_embed = not_mask.cumsum(1, dtype=torch.float32)
        x_embed = not_mask.cumsum(2, dtype=torch.float32)
        if self.normalize:
            eps = 1e-6
            y_embed = y_embed / (y_embed[:, -1:, :] + eps) * self.scale
            x_embed = x_embed / (x_embed[:, :, -1:] + eps) * self.scale

        dim_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)

        pos_x = x_embed[:, :, :, None] / dim_t
        pos_y = y_embed[:, :, :, None] / dim_t
        pos_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)
        return pos

2. object queries (query_embed)

这里query_embed的作用表现的和位置编码类似

# embedding_layer = nn.Embedding(num_embeddings=3, embedding_dim=2)
self.query_embed = nn.Embedding(num_queries, hidden_dim)

object queries在经过decoder的计算以后,会输出一个形状为T,N,C的数组,其中T是object queries的序列长度,即100,N是batch size,C是特征channel。
最后通过一个Linear层输出class预测,通过一个多层感知机结构输出box预测:

'''
torch.nn.Linear(in_features, out_features, bias=True)
	- 输入形状:(batch_size, in_features)
	- (batch_size, out_features)
'''

# MLP (also called FFN)
class MLP(nn.Module):
    """ Very simple multi-layer perceptron (also called FFN)"""

    def __init__(self, input_dim, hidden_dim, output_dim, num_layers):
        super().__init__()
        self.num_layers = num_layers
        h = [hidden_dim] * (num_layers - 1)
        self.layers = nn.ModuleList(nn.Linear(n, k) for n, k in zip([input_dim] + h, h + [output_dim]))

    def forward(self, x):
        for i, layer in enumerate(self.layers):
            x = F.relu(layer(x)) if i < self.num_layers - 1 else layer(x)
        return x

self.class_embed = nn.Linear(hidden_dim, num_classes + 1)
self.bbox_embed = MLP(hidden_dim, hidden_dim, 4, 3)

#forward
hs = self.transformer(self.input_proj(src), mask, self.query_embed.weight, pos[-1])[0]
outputs_class = self.class_embed(hs)
outputs_coord = self.bbox_embed(hs).sigmoid()
out = {'pred_logits': outputs_class[-1], 'pred_boxes': outputs_coord[-1]}

3. 为什么DETR不需要NMS处理

假如有N个目标,那么100个object predictions中就会有N个能够匹配到这N个ground truth,其他的都会和“no object”匹配成功,这些predictions的类别label就会被分配为num_classes,即表示该prediction是背景。这样的设计是很不错的,理论上每个object query都有唯一匹配的目标,不会存在重叠,所以DETR不需要nms进行后处理。


补充:

1. nn.Embedding

- nn.Embedding 是一个预定义的层,专门用于将 离散的整数索引(比如单词ID、类别ID)转换为 稠密向量。
- 它内部维护一个可学习的“向量表”(类似字典),通过查表的方式将索引映射成向量。
	- 可学习:向量表中的每个向量都是 nn.Parameter,会被优化器更新。
- 专为离散设计:适合处理文本、类别等离散数据。
- nn.Embedding:就像一本字典,每个单词对应一页解释(向量),这本字典的内容会在训练中不断优化,让解释更准确。

2. 匈牙利匹配算法(带权二分图最大匹配 KM算法)

1. 匈牙利匹配算法

交替路和增广路是用来解决新配对的时候发生冲突的问题。

交替路:就是依次经过非匹配边、匹配边的路

  • (非匹配边) (匹配边) (非匹配边):B--------------a----------------A-----------------c
  • B和c都是没有被匹配过的点,而它又是这条交替路的起点和终点。这条交替路就是增广路。

现在我们要做一个取反操作,怎么取呢,就是将上面这条增广路的匹配边变成不匹配边,不匹配边变成匹配边。

  • (匹配边) (非匹配边) (匹配边):B--------------a----------------A-----------------c

增广路的核心特点就是“起点终点都是非匹配点”,这样就导致非匹配边比匹配边多了一条。增广路建立连接时,必须建立在两者有意向的基础上。这样我们取反,也就是交换匹配和非匹配边的身份。我们就多得到了一条匹配边。这个取反的过程,就是把原本匹配上的两个人拆散,给第三个人腾位置。

参考:Raf 1

2. KM算法

参考:Ref 2

2. DAB-DETR (收敛慢因为: 没有提供位置先验的 learnable queries)

3. DN-DETR (收敛慢因为:匈牙利匹配的离散性和模型训练的随机性,导致了 query 对 gt 的匹配变成了一个动态的、不稳定的过程)

4. Deformable DETR 2021()

Code URL: https://github.com/fundamentalvision/Deformable-DETR
改进:

  1. 减少训练时长:将全局attention转为局部attention
  2. 提升小物体检测准确率:采用多尺度特征图
    原始图片上一个目标物体太小,它在压缩后的特征图上可能就几乎找不到了,因此我们很难将其检测出来。所以一般情况下,小物体我们需要更大尺寸的特征图。想法:让不同尺寸的特征图都参与训练,提高一个物体被检测出来的可能。

1. Deformable attention计算

# ! 此部分代码不完整,完整代码解析查看参考资料:Ref 4.
class MSDeformAttn(nn.Module):
    def __init__(self, d_model=256, n_levels=4, n_heads=8, n_points=4):
        """
        Multi-Scale Deformable Attention Module
        :param d_model      hidden dimension
        :param n_levels     number of feature levels (特征图的数量)
        :param n_heads      number of attention heads
        :param n_points     number of sampling points per attention head per feature level
        """
        super().__init__()
        if d_model % n_heads != 0:
            raise ValueError('d_model must be divisible by n_heads, but got {} and {}'.format(d_model, n_heads))
        _d_per_head = d_model // n_heads
        # you'd better set _d_per_head to a power of 2 which is more efficient in our CUDA implementation
        if not _is_power_of_2(_d_per_head):
            warnings.warn("You'd better set d_model in MSDeformAttn to make the dimension of each attention head a power of 2 "
                          "which is more efficient in our CUDA implementation.")

2. Reference points/ off set 如何产生?

3. Corase2Fine如何实现?

Reference

  1. 简单理解增广路与匈牙利算法:https://zhuanlan.zhihu.com/p/208596378
  2. 从匈牙利算法到KM算法:ttps://zhuanlan.zhihu.com/p/214072424
  3. 理解DETR:https://zhuanlan.zhihu.com/p/348060767
  4. 再读deformable detr:https://zhuanlan.zhihu.com/p/700776674
posted @ 2025-02-26 19:03  ldfm  阅读(153)  评论(0)    收藏  举报