Transformer实战-系列教程17:DETR 源码解读4(Joiner类/PositionEmbeddingSine类/位置编码/backbone)

🚩🚩🚩Transformer实战-系列教程总目录

有任何问题欢迎在下面留言
本篇文章的代码运行界面均在Pycharm中进行
本篇文章配套的代码资源已经上传
点我下载源码

DETR 算法解读
DETR 源码解读1(项目配置/CocoDetection类)
DETR 源码解读2(ConvertCocoPolysToMask类)
DETR 源码解读3(DETR类)
DETR 源码解读4(Joiner类/PositionEmbeddingSine类/位置编码/backbone)

5、Joiner类

位置:models/backbone.py/Joiner类

python 复制代码
class Joiner(nn.Sequential):
    def __init__(self, backbone, position_embedding):
        super().__init__(backbone, position_embedding)
    def forward(self, tensor_list: NestedTensor):
        xs = self[0](tensor_list)
        out: List[NestedTensor] = []
        pos = []
        for name, x in xs.items():
            out.append(x)
            pos.append(self[1](x).to(x.tensors.dtype))
        return out, pos
  1. 定义Joiner类,继承自PyTorch的nn.Sequential
  2. 构造函数
  3. 初始化
  4. 前向传播函数,接收一个类型为NestedTensor的参数tensor_list
  5. xs,self[0] 指的是nn.Sequential容器中的第一个模块,根据__init__方法中的定义,这是backbone模块。所以,self[0](tensor_list)表示对输入的tensor_list执行backbone模块的前向传播
  6. 初始化一个空列表out,用于存储backbone输出的特征
  7. pos = []**:初始化一个空列表pos,用于存储由position_embedding`生成的位置编码
  8. 遍历xs
  9. 将当前层的输出x添加到out列表中
  10. self[1] 指的是nn.Sequential容器中的第二个模块,根据初始化时的顺序,这是position_embedding模块。因此,self[1](x)表示对backbone的输出x执行position_embedding模块的前向传播
  11. out、pos

6、PositionEmbeddingSine类

位置:models/position_encoding.py/PositionEmbeddingSine类

DETR提供了两种位置编码方式,一种是和Transformer一样的正余弦,另一种是可学习的位置编码方式,下面是和Transformer一样的正余弦

6.1 构造函数

python 复制代码
class PositionEmbeddingSine(nn.Module):
    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
  1. 继承nn.Module的类
  2. 构造函数
  3. 初始化
  4. num_pos_feats ,每个位置特征数量的一般
  5. temperature ,缩放因子,用于调整位置编码的频率
  6. normalize ,是否对位置坐标进行归一化
  7. scale,在归一化位置坐标时使用的额外缩放因子
  8. 验证scale和normalize参数的兼容性
  9. 设置scale的默认值为2 * math.pi,如果未提供

6.2 前向传播

python 复制代码
    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
  1. 前向传播函数
  2. x,从tensor_list提取张量,torch.Size([2, 2048, 25, 29]),2是batch,2048是一个像素点的特征向量维度,后面是特征图长宽
  3. mask ,从tensor_list提取掩码,torch.Size([2, 25, 29]),这里面存储的全是bool值
  4. 确认mask 存在
  5. 通过对掩码取反获取非掩码区域,这里非掩码区域指的是图像的有效部分
  6. y_embed,计算非掩码区域在垂直(y)方向上的累积和,用于生成位置编码,torch.Size([2, 25, 29])
  7. x_embed,计算非掩码区域在水平(x)方向上的累积和,用于生成位置编码,torch.Size([2, 25, 29])
  8. 如果启用了归一化
  9. 一个很小的数,防止出现除以0
  10. 对y_embed
  11. x_embed进行归一化并应用缩放因子self.scale
  12. dim_t ,torch.Size([128]),生成一个维度张量dim_t,用于控制正弦和余弦函数的频率
  13. dim_t ,torch.Size([128]),根据temperature和num_pos_feats调整其值
  14. pos_x ,对x_embed应用缩放,torch.Size([2, 25, 29, 128])
  15. pos_y ,对y_embed应用缩放,准备生成正弦和余弦编码,torch.Size([2, 25, 29, 128])
  16. pos_x ,分别计算所有偶数位置的正弦值和所有奇数位置的余弦值,将正弦值和余弦值沿着新的维度堆叠起来,将堆叠后的维度(正弦和余弦值对)展平,torch.Size([2, 25, 29, 128])
  17. pos_y ,torch.Size([2, 25, 29, 128])
  18. pos ,将pos_y和pos_x在第3维上进行拼接,形成完整的位置编码,torch.Size([2, 256, 25, 29])
  19. 返回pos

通过这种方式,PositionEmbeddingSine类为每个像素位置生成了一个独特的编码,这个编码通过正弦和余弦函数的交替使用捕获了空间位置信息。正弦和余弦函数的周期性和连续性特点使得这种编码非常适合表示位置关系,有助于提高模型对图像空间信息的理解和处理能力

DETR 算法解读
DETR 源码解读1(项目配置/CocoDetection类)
DETR 源码解读2(ConvertCocoPolysToMask类)
DETR 源码解读3(DETR类)
DETR 源码解读4(Joiner类/PositionEmbeddingSine类/位置编码/backbone)

相关推荐
羊小猪~~4 分钟前
神经网络基础--什么是正向传播??什么是方向传播??
人工智能·pytorch·python·深度学习·神经网络·算法·机器学习
AI小杨6 分钟前
【车道线检测】一、传统车道线检测:基于霍夫变换的车道线检测史诗级详细教程
人工智能·opencv·计算机视觉·霍夫变换·车道线检测
晨曦_子画10 分钟前
编程语言之战:AI 之后的 Kotlin 与 Java
android·java·开发语言·人工智能·kotlin
道可云12 分钟前
道可云人工智能&元宇宙每日资讯|2024国际虚拟现实创新大会将在青岛举办
大数据·人工智能·3d·机器人·ar·vr
人工智能培训咨询叶梓21 分钟前
探索开放资源上指令微调语言模型的现状
人工智能·语言模型·自然语言处理·性能优化·调优·大模型微调·指令微调
zzZ_CMing21 分钟前
大语言模型训练的全过程:预训练、微调、RLHF
人工智能·自然语言处理·aigc
newxtc22 分钟前
【旷视科技-注册/登录安全分析报告】
人工智能·科技·安全·ddddocr
成都古河云23 分钟前
智慧场馆:安全、节能与智能化管理的未来
大数据·运维·人工智能·安全·智慧城市
UCloud_TShare26 分钟前
浅谈语言模型推理框架 vLLM 0.6.0性能优化
人工智能
软工菜鸡30 分钟前
预训练语言模型BERT——PaddleNLP中的预训练模型
大数据·人工智能·深度学习·算法·语言模型·自然语言处理·bert