[pytorch] detr源码浅析

[pytorch] detr源码浅析

  • 1. backbone部分
  • 2. encoder部分
  • 3. decoder部分
  • 4. 输出预测

为之后SAM的代码分析做铺垫

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

1. backbone部分

  • detr.py中的DETR class
class DETR(nn.Module):def __init__(self, backbone, transformer, num_classes, num_queries, aux_loss=False):...def forward(self, samples: NestedTensor):features, pos = self.backbone(samples)# 第一步,从图像提取特征# 返回值:特征图,pos位置编码(当前得到的特征图编码.不是对原始图像)# 跳到backbone - backbone.py里的Joiner函数
  • backbone.py 中的 Joiner class
class Joiner(nn.Sequential):def __init__(self, backbone, position_embedding):super().__init__(backbone, position_embedding)def forward(self, tensor_list: NestedTensor):# print(tensor_list.tensor.shape)xs = self[0](tensor_list)# 输入图像经过resnet# 得到特征图out: List[NestedTensor] = []pos = []for name, x in xs.items():out.append(x)pos.append(self[1](x).to(x.tensors.dtype))# 跳到position encoding.pyreturn out, pos
  • position encoding.py
    第一种:Attention Is All You Need中的正余弦编码方式,不用学习,默认方法
    在这里插入图片描述
class PositionEmbeddingSine(nn.Module):"""This is a more standard version of the position embedding, very similar to the oneused 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_featsself.temperature = temperature # 经验值self.normalize = normalizeif 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.piself.scale = scaledef forward(self, tensor_list: NestedTensor):x = tensor_list.tensors# 输入特征图大小 batch, c, h, w    resnet50 c = 2048mask = tensor_list.mask# mask 表示实际的特征true  还是padding出来的false# 大小 batch,h,wassert mask is not Nonenot_mask = ~masky_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.scalex_embed = x_embed / (x_embed[:, :, -1:] + eps) * self.scaledim_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_tpos_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) # 前一半是pos_x 后一半是pos_yreturn pos

第二种:可学习的位置编码

class PositionEmbeddingLearned(nn.Module):"""Absolute pos embedding, learned."""def __init__(self, num_pos_feats=256):super().__init__()# 行和列进行编码self.row_embed = nn.Embedding(50, num_pos_feats)  self.col_embed = nn.Embedding(50, num_pos_feats)# 50经验值self.reset_parameters()def reset_parameters(self):nn.init.uniform_(self.row_embed.weight)nn.init.uniform_(self.col_embed.weight)def forward(self, tensor_list: NestedTensor):x = tensor_list.tensorsh, w = x.shape[-2:]i = torch.arange(w, device=x.device)j = torch.arange(h, device=x.device)x_emb = self.col_embed(i)y_emb = self.row_embed(j)pos = torch.cat([x_emb.unsqueeze(0).repeat(h, 1, 1),y_emb.unsqueeze(1).repeat(1, w, 1),], dim=-1).permute(2, 0, 1).unsqueeze(0).repeat(x.shape[0], 1, 1, 1)return pos

2. encoder部分

  • detr.py中的DETR class
class DETR(nn.Module):def __init__(self, backbone, transformer, num_classes, num_queries, aux_loss=False):self.input_proj = nn.Conv2d(backbone.num_channels, hidden_dim, kernel_size=1)...def forward(self, samples: NestedTensor):features, pos = self.backbone(samples)src, mask = features[-1].decompose()# features和pos保存的都是cnn中每个block的结果,用的时候取最后一个block的结果# features大小 batch, c, h, w    resnet50 c = 2048# mask 大小 batch, h, w 是否paddingassert mask is not Nonehs = self.transformer(self.input_proj(src), mask, self.query_embed.weight, pos[-1])[0]# self.input_proj降维 cnn得到的特征图维度2048太大了把它降低到256# 跳到 transformer.py中的Transformer class
  • transformer.py中的Transformer class
class Transformer(nn.Module):def __init__(self, d_model=512, nhead=8, num_encoder_layers=6,num_decoder_layers=6, dim_feedforward=2048, dropout=0.1,activation="relu", normalize_before=False,return_intermediate_dec=False):super().__init__()encoder_layer = TransformerEncoderLayer(d_model, nhead, dim_feedforward,dropout, activation, normalize_before)encoder_norm = nn.LayerNorm(d_model) if normalize_before else Noneself.encoder = TransformerEncoder(encoder_layer, num_encoder_layers, encoder_norm)decoder_layer = TransformerDecoderLayer(d_model, nhead, dim_feedforward,dropout, activation, normalize_before)decoder_norm = nn.LayerNorm(d_model)self.decoder = TransformerDecoder(decoder_layer, num_decoder_layers, decoder_norm,return_intermediate=return_intermediate_dec)self._reset_parameters()self.d_model = d_modelself.nhead = nheaddef _reset_parameters(self):for p in self.parameters():if p.dim() > 1:nn.init.xavier_uniform_(p)def forward(self, src, mask, query_embed, pos_embed):# flatten NxCxHxW to HWxNxCbs, c, h, w = src.shapesrc = src.flatten(2).permute(2, 0, 1) # NxCxHxW to HWxNxC# N是batchsize大小 把特征图长×宽得到token个数# 输出大小 [token个数,batch size,token 长度]pos_embed = pos_embed.flatten(2).permute(2, 0, 1) # NxCxHxW to HWxNxCquery_embed = query_embed.unsqueeze(1).repeat(1, bs, 1)# query_embed 在decoder中用到,大小为[100,batch size,token 长度]mask = mask.flatten(1) # mask大小 [token个数,batch size]tgt = torch.zeros_like(query_embed)# tgt在decoder中用到memory = self.encoder(src, src_key_padding_mask=mask, pos=pos_embed)# 跳到  transformer.py中的TransformerEncoderLayer class# encoder的输出大小 [token个数,batch size,token长度]hs = self.decoder(tgt, memory, memory_key_padding_mask=mask,pos=pos_embed, query_pos=query_embed)return hs.transpose(1, 2), memory.permute(1, 2, 0).view(bs, c, h, w)
  • transformer.py中的TransformerEncoderLayer class
class TransformerEncoderLayer(nn.Module):def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1,activation="relu", normalize_before=False):super().__init__()self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)# Implementation of Feedforward modelself.linear1 = nn.Linear(d_model, dim_feedforward)self.dropout = nn.Dropout(dropout)self.linear2 = nn.Linear(dim_feedforward, d_model)self.norm1 = nn.LayerNorm(d_model)self.norm2 = nn.LayerNorm(d_model)self.dropout1 = nn.Dropout(dropout)self.dropout2 = nn.Dropout(dropout)self.activation = _get_activation_fn(activation)self.normalize_before = normalize_beforedef with_pos_embed(self, tensor, pos: Optional[Tensor]):return tensor if pos is None else tensor + posdef forward_post(self,src,src_mask: Optional[Tensor] = None,src_key_padding_mask: Optional[Tensor] = None,pos: Optional[Tensor] = None):q = k = self.with_pos_embed(src, pos) # 只有K和Q 加入了位置编码# q k 的大小都为 [token个数,batch size,token长度]src2 = self.self_attn(q, k, value=src, attn_mask=src_mask,key_padding_mask=src_key_padding_mask)[0]# pytorch自带函数# src_mask 是nlp中防止透题用的,这里不用# src_key_padding_mask padding为true的不计算# 返回值 [新的特征图,权重项] 第二项不需要src = src + self.dropout1(src2)src = self.norm1(src)src2 = self.linear2(self.dropout(self.activation(self.linear1(src))))src = src + self.dropout2(src2)src = self.norm2(src)return src
  • transformer.py中的TransformerEncoder class
    将TransformerEncoderLayer 重复多次
class TransformerEncoder(nn.Module):def __init__(self, encoder_layer, num_layers, norm=None):super().__init__()self.layers = _get_clones(encoder_layer, num_layers)self.num_layers = num_layersself.norm = normdef forward(self, src,mask: Optional[Tensor] = None,src_key_padding_mask: Optional[Tensor] = None,pos: Optional[Tensor] = None):output = srcfor layer in self.layers:output = layer(output, src_mask=mask,src_key_padding_mask=src_key_padding_mask, pos=pos)if self.norm is not None:output = self.norm(output)return output

3. decoder部分

在这里插入图片描述
detr要学习的核心 100个queries向量tgt 大小[100,batch size,token长度]
第一次初始值都为0
最终输出的100个queries最后预测框
无论输入为什么,都输出100个框

  • transformer.py中的Transformer class
class Transformer(nn.Module):def __init__(self, d_model=512, nhead=8, num_encoder_layers=6,num_decoder_layers=6, dim_feedforward=2048, dropout=0.1,activation="relu", normalize_before=False,return_intermediate_dec=False):super().__init__()encoder_layer = TransformerEncoderLayer(d_model, nhead, dim_feedforward,dropout, activation, normalize_before)encoder_norm = nn.LayerNorm(d_model) if normalize_before else Noneself.encoder = TransformerEncoder(encoder_layer, num_encoder_layers, encoder_norm)decoder_layer = TransformerDecoderLayer(d_model, nhead, dim_feedforward,dropout, activation, normalize_before)decoder_norm = nn.LayerNorm(d_model)self.decoder = TransformerDecoder(decoder_layer, num_decoder_layers, decoder_norm,return_intermediate=return_intermediate_dec)self._reset_parameters()self.d_model = d_modelself.nhead = nheaddef _reset_parameters(self):for p in self.parameters():if p.dim() > 1:nn.init.xavier_uniform_(p)def forward(self, src, mask, query_embed, pos_embed):# flatten NxCxHxW to HWxNxCbs, c, h, w = src.shapesrc = src.flatten(2).permute(2, 0, 1) # NxCxHxW to HWxNxC# N是batchsize大小 把特征图长×宽得到token个数# 输出大小 [token个数,batch size,token 长度]pos_embed = pos_embed.flatten(2).permute(2, 0, 1) # NxCxHxW to HWxNxCquery_embed = query_embed.unsqueeze(1).repeat(1, bs, 1)# query_embed 在decoder中用到,大小为[100,batch size,token 长度]mask = mask.flatten(1) # mask大小 [token个数,batch size]tgt = torch.zeros_like(query_embed) # 一开始初始化为0# tgt在decoder中用到memory = self.encoder(src, src_key_padding_mask=mask, pos=pos_embed)hs = self.decoder(tgt, memory, memory_key_padding_mask=mask,pos=pos_embed, query_pos=query_embed)# 跳到  transformer.py中的TransformerDecoderLayer classreturn hs.transpose(1, 2), memory.permute(1, 2, 0).view(bs, c, h, w)
  • transformer.py中的TransformerDecoderLayer class
class TransformerDecoderLayer(nn.Module):def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1,activation="relu", normalize_before=False):super().__init__()self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)self.multihead_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)# Implementation of Feedforward modelself.linear1 = nn.Linear(d_model, dim_feedforward)self.dropout = nn.Dropout(dropout)self.linear2 = nn.Linear(dim_feedforward, d_model)self.norm1 = nn.LayerNorm(d_model)self.norm2 = nn.LayerNorm(d_model)self.norm3 = nn.LayerNorm(d_model)self.dropout1 = nn.Dropout(dropout)self.dropout2 = nn.Dropout(dropout)self.dropout3 = nn.Dropout(dropout)self.activation = _get_activation_fn(activation)self.normalize_before = normalize_beforedef with_pos_embed(self, tensor, pos: Optional[Tensor]):return tensor if pos is None else tensor + posdef forward_post(self, tgt, memory,tgt_mask: Optional[Tensor] = None,memory_mask: Optional[Tensor] = None,tgt_key_padding_mask: Optional[Tensor] = None,memory_key_padding_mask: Optional[Tensor] = None,pos: Optional[Tensor] = None,query_pos: Optional[Tensor] = None):q = k = self.with_pos_embed(tgt, query_pos)# 大小[100,batch size,token长度]tgt2 = self.self_attn(q, k, value=tgt, attn_mask=tgt_mask,key_padding_mask=tgt_key_padding_mask)[0]# 先自注意力机制# tgt_mask 和 tgt_key_padding_mask 都为Nonetgt = tgt + self.dropout1(tgt2)tgt = self.norm1(tgt)tgt2 = self.multihead_attn(query=self.with_pos_embed(tgt, query_pos),key=self.with_pos_embed(memory, pos),value=memory, attn_mask=memory_mask,key_padding_mask=memory_key_padding_mask)[0]# q 是 100个queries# 图像提供k,v 大小[图像token个数,batch size,token 长度]tgt = tgt + self.dropout2(tgt2)tgt = self.norm2(tgt)tgt2 = self.linear2(self.dropout(self.activation(self.linear1(tgt))))tgt = tgt + self.dropout3(tgt2)tgt = self.norm3(tgt)return tgt
  • transformer.py中的TransformerDecoder class
    将TransformerDecoderLayer 重复多次
    tgt 在经过第一层之后就不为0了
class TransformerDecoder(nn.Module):def __init__(self, decoder_layer, num_layers, norm=None, return_intermediate=False):super().__init__()self.layers = _get_clones(decoder_layer, num_layers)self.num_layers = num_layersself.norm = normself.return_intermediate = return_intermediatedef forward(self, tgt, memory,tgt_mask: Optional[Tensor] = None,memory_mask: Optional[Tensor] = None,tgt_key_padding_mask: Optional[Tensor] = None,memory_key_padding_mask: Optional[Tensor] = None,pos: Optional[Tensor] = None,query_pos: Optional[Tensor] = None):output = tgtintermediate = []for layer in self.layers:output = layer(output, memory, tgt_mask=tgt_mask,memory_mask=memory_mask,tgt_key_padding_mask=tgt_key_padding_mask,memory_key_padding_mask=memory_key_padding_mask,pos=pos, query_pos=query_pos)if self.return_intermediate:intermediate.append(self.norm(output))if self.norm is not None:output = self.norm(output)if self.return_intermediate:intermediate.pop()intermediate.append(output)if self.return_intermediate:return torch.stack(intermediate)return output.unsqueeze(0)

4. 输出预测

  • detr.py中的DETR class
    把decoder产生的100个token进行输出
    两个任务:检测(回归4个值)和分类
class DETR(nn.Module):def __init__(self, backbone, transformer, num_classes, num_queries, aux_loss=False):...self.class_embed = nn.Linear(hidden_dim, num_classes + 1)self.bbox_embed = MLP(hidden_dim, hidden_dim, 4, 3)def forward(self, samples: NestedTensor):features, pos = self.backbone(samples)hs = self.transformer(self.input_proj(src), mask, self.query_embed.weight, pos[-1])[0]# decoder输出大小 [batch size,100,token长度]outputs_class = self.class_embed(hs) # 分类任务outputs_coord = self.bbox_embed(hs).sigmoid() # 检测/回归任务,输出四个值,sigmoid让输出为正数out = {'pred_logits': outputs_class[-1], 'pred_boxes': outputs_coord[-1]}

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

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

相关文章

78K0最小硬件系统分析

78K0最小硬件系统如下图所示。 在应用APPlilet2软件创建一个工程时,软件会第一时间弹出系统设置对话框和看门狗定时器设置对话框。这是对最小硬件系统的初始设置。包括如下选项: (1)系统时钟设置 体现在硬件初始化函数hdwinit中。…

【漏洞分析】Confluence 数据中心和服务器中的严重漏洞 CVE-2023-22515

Confluence 数据中心和服务器中的严重漏洞 CVE-2023-22515 一、简述二、利用(一)第一阶段 设置“设置过程尚未完成”(二)第二阶段,访问setupadministrator端点(三)、利用新创建管理员账户登录 三、POC 一、简述 Confluence 的开发者 Atlassian 已公告此…

易大师B版运势测算系统源码-八字周易运势塔罗-含视频搭建教程

2024最新易大师B版运势测算系统源码-八字周易运势塔罗等测算源码 基于上个版本再次做了数据优化和部分bug修复,青狐独家维护版本。 测算周易系统一直都是很好变现和运营的,玩法操作也比较简单,也很容易被百度收录推广。 大致功能&#xff1a…

Github Action Auto build docker Auto deploy

简介 整个流程比较清晰,实现的是基于Github 定向的往ECS做发布 探索 自动化打包发布一般流程: 本地环境打镜像 CI/CD 环境打镜像 以上的流程使用于比较大的项目,受限于环境,打算对上面流程做简化,使用github acti…

栈和队列的学习

存储方式分两类:顺序存储和链式存储 栈:只允许从一端进行数据插入和删除的线性表:先进后出 FILO 队列:只允许从一端进行数据插入,另一端进行数据删除的线性表:先进先出 FIFO 栈 创建空栈,创建…

(AtCoder Beginner Contest 327) --- F-Apples --- 题解 (一个比较难想的线段树题)

目录 F-Apples: 题目大意: ​编辑​编辑 思路解析: 代码实现: F-Apples: 题目大意: 样例解释: 思路解析: 题目要求我们选择任意一对S,L,让苹果满足 S-0.…

北航悉尼大学联合研发突破性高效AI技术:双重二值化方法重塑大型语言模型效率

论文题目: DB-LLM: Accurate Dual-Binarization for Efficient LLMs 论文链接: https://arxiv.org/abs/2402.11960 大型语言模型(LLMs)的双重二值化方法:新纪元的高效自然语言处理。随着大型语言模型(LLMs&…

Amazon SageMaker + Stable Diffusion 搭建文本生成图像模型

如果我们的计算机视觉系统要真正理解视觉世界,它们不仅必须能够识别图像,而且必须能够生成图像。文本到图像的 AI 模型仅根据简单的文字输入就可以生成图像。 近两年,以ChatGPT为代表的AIGC技术崭露头角,逐渐从学术研究的象牙塔迈…

应急救援装备无人机是否必要?无人机在应急救援中的具体应用案例有哪些?

无人机(Drone)是一种能够飞行并自主控制或远程操控的无人驾驶飞行器。它们通常由航空器、控制系统、通讯链路和电源系统组成,并可以根据任务需求搭载不同类型的传感器、摄像头、货物投放装置等设备。 无人机的种类繁多,从大小、形…

Android Handler使用介绍

Android 中的 Handler 是用来和线程通信的重要工具。它主要用于在后台线程中执行任务,并将结果传递回主线程以更新用户界面。 一、基本概念 线程间通信: Android 应用通常具有主线程(也称为 UI 线程)和后台线程。Handler 允许您从…

操作系统面经-程序和进程的区别

1.程序、进程、线程简述 程序的基本概念 程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。 进程的基本概念 在多道程序环境下,允许多个程序并发执行,此时它们将失去封闭性&#xf…

Verilog刷题笔记41

题目:Create 8 D flip-flops with active high asynchronous reset. All DFFs should be triggered by the positive edge of clk. 解题: module top_module (input clk,input areset, // active high asynchronous resetinput [7:0] d,output [7:0]…

哪些事是你当了领导才明白的?

哪些事是你当了领导才明白的? 毕业5年,17年开始带团队,确实很多事不做到管理这一层,就真的意识不到。 带着【执行者】和【管理者】这2个视角,再结合我毕业至今这5年的所有职场经历,聊聊“职场潜规则”。 …

docker swarm 集群创建

1,目的: 通过docker swarm 工具将一台或者多台安装了docker的服务器组成一个完整的集群,该集群中的node节点可以通过Leader节点管理。在使用docker stack部署时,可以将容器自动分发到合适的节点上。 2,服务器准备&am…

python统计分析——t分布、卡方分布、F分布

参考资料:python统计分析【托马斯】 一些常见的连续型分布和正态分布分布关系紧密。 t分布:正态分布的总体中,样本均值的分布。通常用于小样本数且真实的均值/标准差不知道的情况。 卡方分布:用于描述正态分布数据的变异程度。 F分…

R语言Meta分析核心技术:科研论文写作与数据可视化技巧

R语言作为一种强大的统计分析和绘图语言,在科研领域发挥着日益重要的作用。其中,Meta分析作为一种整合多个独立研究结果的统计方法,在R语言中得到了广泛的应用。通过R语言进行Meta分析,研究者能够更为准确、全面地评估某一研究问题…

ShardingSphere+JPA+Druid实现分表操作

要在SpringBoot项目中实现分表操作,本文使用的是ShardingSphereJPADruid实现。过程中出现问题记录一下。 准备MySQL数据库表 这里准备的是一张主表test_cost,两张从表test_cost_0和test_cost_1,结构需要相同,主表只是声明了表结构…

用大语言模型控制交通信号灯,有效缓解拥堵!

城市交通拥堵是一个全球性的问题,在众多缓解交通拥堵的策略中,提高路口交通信号控制的效率至关重要。传统的基于规则的交通信号控制(TSC)方法,由于其静态的、基于规则的算法,无法完全适应城市交通不断变化的…

Tensorflow2.0笔记 - 链式法则例子

本笔记简单记录链式法则的原理,关于链式法则,本身和高等数学中的链式求导法则是一样的,深度学习中相关资料可以参考这里: 【深度学习之美22】BP算法详解之链式法则 - 知乎10.5 什么是计算图?我们知道, 神经…

Windows环境下编译ffmpeg 6.1源码--Virtual Studio + Msys2方式

环境准备 约定:源码全部放到sources下,目录结构说明 /d/java/ffmpeg #工程工目录 ├── build #存放编译文件的目录,子目录为具体模块的构建目录 │ ├── fdk-aac │ ├── ffmpeg │ └── x264 ├── instal…