DETR:End-to-End Object Detection with Transformers

【DETR 论文精读【论文精读】-哔哩哔哩】 https://b23.tv/Iy9k4O2

【DETR源码解读4-哔哩哔哩】 https://b23.tv/Qp1uH5v

简介:

时间:2020

会议:ECCV

作者:Nicolas Carion, Francisco Massa, Gabriel Synnaeve, Nicolas Usunier, Alexander Kirillov和Sergey Zagoruyko,来自Paris Dauphine University和Facebook AI

摘要:

将目标检测看作一个集合预测的问题

任务:给定一张图片,预测一组框,每个框需要得到坐标信息和包含的物体类别信息,将框可以视为集合,不同图片所对应的框不同,则所对应的集合就不同

去除:NMS、生成anchor

创新:

①提出一个目标函数,通过二分图匹配的方式强制模型输出一组独一无二的预测(去除冗余框,每个物体的理想状态下就会生成一个框)

②使用Transformer 的encoder、decoder架构:

(1)在Transformer解码器中提出learned object query,它可以和全局图像信息结合,通过不停做注意力操作,让模型直接输出一组预测框

(2)并行出框

导言:

背景:

大部分目标检测器采用间接方式预测,或用回归和分类替代目标检测问题

性能受限于后处理(NMS)操作,处理大量冗余框

流程:

①用卷积神经网络提取特征

②将特征拉直,送入Transformer的encoder、decoder,进一步学习全局信息,将每一个点的信息与全局做交互

③生成框输出,通过object query限制框的个数

④使用二分图匹配计算Loss,计算预测框和GT Box的matching loss决定预测框中对应GT Box的框;选择后计算分类损失、Bounding Box Loss;没有匹配上的框被标记为背景

相关工作:

两阶段目标检测:proposal

单阶段目标检测:anchor、center

基于集合:

关系型网络、Learnable NMS利用类似于自注意力的方法去处理物体间联系

无需后处理

性能低,使用了人工干预

基于Encoder Decoder:

得到更全局的信息

并行输出目标框,时效性增强

Encoder:

代码结构与图对应 : 

(0): TransformerEncoderLayer(
          (self_attn): MultiheadAttention(
            (out_proj): NonDynamicallyQuantizableLinear(in_features=256, out_features=256, bias=True)
          )
          (linear1): Linear(in_features=256, out_features=2048, bias=True)
          (dropout): Dropout(p=0.1, inplace=False)
          (linear2): Linear(in_features=2048, out_features=256, bias=True)
          (norm1): LayerNorm((256,), eps=1e-05, elementwise_affine=True)
          (norm2): LayerNorm((256,), eps=1e-05, elementwise_affine=True)
          (dropout1): Dropout(p=0.1, inplace=False)
          (dropout2): Dropout(p=0.1, inplace=False)
        )
# 图像特征和位置编码相加得到了q、k
q = k = self.with_pos_embed(src, pos)
# value还是特征
src2 = self.self_attn(q, k, value=src, attn_mask=src_mask,
                              key_padding_mask=src_key_padding_mask)[0]

改进后的Decoder:

# 将encoder出来的4个值传入decoder进行处理
hs = self.decoder(tgt, memory, memory_key_padding_mask=mask,
                          pos=pos_embed, query_pos=query_embed)

代码结构与图对应:

(0): TransformerDecoderLayer(
          (self_attn): MultiheadAttention(
            (out_proj): NonDynamicallyQuantizableLinear(in_features=256, out_features=256, bias=True)
          )
          (multihead_attn): MultiheadAttention(
            (out_proj): NonDynamicallyQuantizableLinear(in_features=256, out_features=256, bias=True)
          )
          (linear1): Linear(in_features=256, out_features=2048, bias=True)
          (dropout): Dropout(p=0.1, inplace=False)
          (linear2): Linear(in_features=2048, out_features=256, bias=True)
          (norm1): LayerNorm((256,), eps=1e-05, elementwise_affine=True)
          (norm2): LayerNorm((256,), eps=1e-05, elementwise_affine=True)
          (norm3): LayerNorm((256,), eps=1e-05, elementwise_affine=True)
          (dropout1): Dropout(p=0.1, inplace=False)
          (dropout2): Dropout(p=0.1, inplace=False)
          (dropout3): Dropout(p=0.1, inplace=False)
        )

解码器部分的第一部分用到的是Multi-Head Self-Attention ,而第二部分用到的则是Multi-Head Attention  

第一个MHSA:

q = k = self.with_pos_embed(tgt, query_pos)
# tgt当作第一个value进行self-aattention
# 计算每个目标表示与其他目标表示之间的注意力分数
 tgt2 = self.self_attn(q, k, value=tgt, attn_mask=tgt_mask,
                              key_padding_mask=tgt_key_padding_mask)[0]
第二个MHA:

# 通过多头自注意力层计算目标表示和图像特征表示之间的注意力分数
tgt2 = self.multihead_attn(
                           # q:第一个attention的输出+位置编码
                           query=self.with_pos_embed(tgt, query_pos),
                           # k:encoder输出+position embedding(空间位置编码)
                           key=self.with_pos_embed(memory, pos),
                           # v:encoder输出(memory)
                           value=memory, 
                           attn_mask=memory_mask,
                           key_padding_mask=memory_key_padding_mask)[0]
原因:

Queries 内部先进行协同工作(通过 MHSA)

然后再与图像特征交互提取有用的信息(通过 MHA)

DETR:

class DETR(nn.Module):
    def __init__(self, num_classes, hidden_dim, nheads, num_encoder_layers, num_decoder_layers, num_queries):
        super(DETR, self).__init__()
        # Encoder
        self.transformer = TransformerEncoder(d_model=hidden_dim, nhead=nheads, num_encoder_layers=num_encoder_layers)
        
        # Decoder
        self.transformer_decoder = TransformerDecoder(d_model=hidden_dim, nhead=nheads, num_decoder_layers=num_decoder_layers)
        
        # Object queries
        self.query_embed = nn.Embedding(num_queries, hidden_dim)
        
        # Prediction heads
        self.class_embed = nn.Linear(hidden_dim, num_classes + 1)  # +1 for background
        self.bbox_embed = MLP(hidden_dim, hidden_dim * 4, 4, 3)

    def forward(self, images):
        # 假设images已经通过CNN处理成[batch_size, num_channels, H, W]
        # 这里略过CNN部分,直接模拟CNN输出特征
        src = ...  # [batch_size, src_seq_len, hidden_dim],其中src_seq_len是特征图的序列长度
        
        # 目标查询
        hs = self.query_embed.weight.unsqueeze(0).repeat(images.shape[0], 1, 1)  # [batch_size, num_queries, hidden_dim]
        
        # Encoder
        memory = self.transformer(src)
        
        # Decoder
        tgt = torch.zeros_like(hs)  # 初始化为零的目标查询
        outputs = self.transformer_decoder(tgt, memory, tgt_mask=None, memory_key_padding_mask=None)
        
        # 输出预测
        outputs_class = self.class_embed(outputs)
        outputs_coord = self.bbox_embed(outputs).sigmoid()  # 假设使用sigmoid来限制坐标范围
        
        return outputs_class, outputs_coord

基于集合的目标函数:

使用cost matrix:类似于三个工人分配三个工作,使每个工人被分配其最擅长的工作

使用scipy包中提供的linear-sum-assignment函数,将cost matrix作为函数输入

a、b、c看作100个框,x、y、z看作GT框 

损失函数:

包含分类Loss和出框Loss

为了使两个Loss在相近的取值空间,将log去除,得到更好的效果

在Bounding Box中,使用L_1 Loss可能会产生问题,于是加入了genralized IoU Loss(与框大小无关)

细节:为了让模型收敛更快,训练的更稳定,在Decoder后加入很多auxiliary loss(额外的目标函数);

### DETR 模型概述 DETR (Detection Transformer) 是一种基于变压器架构的目标检测方法,它通过将目标检测视为集合预测问题来简化传统的两阶段管道[^3]。该模型的核心思想在于使用编码器-解码器结构,其中自注意力机制能够显式建模序列中所有成对交互关系,这使得其特别适合处理诸如消除重复预测之类的集合预测约束。 #### 编码器-解码器架构 DETR 使用了一种基于变压器的编码器-解码器架构。输入图像被划分为固定数量的 patches,并传递到 CNN 提取特征图。随后,这些特征图被展平并送入变压器编码器部分进行全局上下文建模。接着,在解码器端引入一组可学习的位置嵌入(称为查询),用于表示潜在的对象位置和属性。最终,解码器输出一系列边界框坐标以及对应的类别标签。 以下是实现 DETR 的基本代码框架: ```python import torch from torchvision.models.detection import detr_resnet50 # 加载预训练的 DETR 模型 model = detr_resnet50(pretrained=True) # 设置为评估模式 model.eval() # 输入张量形状 (batch_size, channels, height, width) input_tensor = torch.rand(1, 3, 800, 800) # 进行推理 outputs = model(input_tensor) print(outputs) ``` 此代码片段展示了如何加载一个预先训练好的 DETR 模型,并对其进行简单的前向传播操作以获取预测结果。 #### 训练流程优化 为了进一步提升性能,研究者们还提出了一些改进措施。例如,在小样本场景下,可以通过迁移学习技术增强泛化能力;或者设计专门针对稀有类别的损失函数来缓解数据不平衡现象[^4]。 ### 应用实例:全景分割 除了常规的目标检测任务外,DETR 同样可以扩展至更复杂的视觉理解领域——比如全景分割。具体而言,只需稍作调整即可让同一套网络同时完成语义分割与实例分割两项子任务。下面给出一段展示如何利用官方 Colab 笔记本运行 DEMO 的链接说明[^1]: [Panoptic Colab Notebook](https://github.com/facebookresearch/detr/blob/main/notebooks/panoptic.ipynb).
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值