当前位置: 首页 > news >正文

YOLO11改进|上采样篇|引入DySample轻量级动态上采样器

在这里插入图片描述

目录

    • 一、DySample轻量级动态上采样器
      • 1.1DySample上采样模块介绍
      • 1.2DySample核心代码
    • 五、添加DySample上采样器
      • 5.1STEP1
      • 5.2STEP2
      • 5.3STEP3
      • 5.4STEP4
    • 六、yaml文件与运行
      • 6.1yaml文件
      • 6.2运行成功截图

一、DySample轻量级动态上采样器

1.1DySample上采样模块介绍

在这里插入图片描述

DySample是一种基于采样的动态上采样(Sampling based dynamic upsampling)机制,用于提升图像或特征图的分辨率。主要分为三部分:采样点生成(sampling point generator)、静态和动态作用域因子(Static Scope Factor 和 Dynamic Scope Factor)。下面我将对每个部分的工作流程和其优势做一个简要介绍。

  1. 采样点生成和网格采样
    采样点生成器(Sampling point generator) 会生成一个采样点集,用于决定在哪些点上进行上采样。接着,使用 网格采样(Grid Sample) 方法对原始特征图进行采样,生成一个新的高分辨率特征图 𝑋′。这种基于采样点的上采样方法具有动态性,意味着它可以根据输入特征图的不同自动调整采样点,避免了传统插值方法的局限性,使得上采样更加灵活和精确。

  2. 静态作用域因子(Static Scope Factor)
    在这个模块中,输入特征图 𝑋,先通过一个线性变换生成低维特征。然后乘以一个固定因子(例如0.25),再进行 Pixel Shuffle 操作。最终,将生成的高分辨率特征 𝐺 和一个由固定范围因子 𝑂计算出来的偏移特征图相加,得到输出 𝑆。
    优势:静态因子使得上采样具有稳定性和可控性,适合处理那些具有一致性尺度变化的场景。

  3. 动态作用域因子(Dynamic Scope Factor)
    与静态作用域因子类似,但动态作用域因子会根据输入的特征图动态调整缩放因子(如图中的 0.5a),然后再通过 Pixel Shuffle 操作放大特征图。同样,生成的特征图 𝐺 和动态偏移特征图 𝑂相加得到最终输出 𝑆。
    优势:动态因子能够自适应地调整不同输入的缩放尺度,特别适合处理多尺度特征或分辨率变化较大的图像。这种机制可以更好地捕捉不同尺度下的细节信息,提高模型的灵活性和适应性。
    DySample动态点采样器的结构如下:
    在这里插入图片描述

1.2DySample核心代码

import torch
import torch.nn as nn
import torch.nn.functional as F__all__ = ['Dy_Sample']def normal_init(module, mean=0, std=1, bias=0):if hasattr(module, 'weight') and module.weight is not None:nn.init.normal_(module.weight, mean, std)if hasattr(module, 'bias') and module.bias is not None:nn.init.constant_(module.bias, bias)def constant_init(module, val, bias=0):if hasattr(module, 'weight') and module.weight is not None:nn.init.constant_(module.weight, val)if hasattr(module, 'bias') and module.bias is not None:nn.init.constant_(module.bias, bias)class Dy_Sample(nn.Module):def __init__(self, in_channels, scale=2, style='lp', groups=4, dyscope=False):super().__init__()self.scale = scaleself.style = styleself.groups = groupsassert style in ['lp', 'pl']if style == 'pl':assert in_channels >= scale ** 2 and in_channels % scale ** 2 == 0assert in_channels >= groups and in_channels % groups == 0if style == 'pl':in_channels = in_channels // scale ** 2out_channels = 2 * groupselse:out_channels = 2 * groups * scale ** 2self.offset = nn.Conv2d(in_channels, out_channels, 1)normal_init(self.offset, std=0.001)if dyscope:self.scope = nn.Conv2d(in_channels, out_channels, 1)constant_init(self.scope, val=0.)self.register_buffer('init_pos', self._init_pos())def _init_pos(self):h = torch.arange((-self.scale + 1) / 2, (self.scale - 1) / 2 + 1) / self.scalereturn torch.stack(torch.meshgrid([h, h])).transpose(1, 2).repeat(1, self.groups, 1).reshape(1, -1, 1, 1)def sample(self, x, offset):B, _, H, W = offset.shapeoffset = offset.view(B, 2, -1, H, W)coords_h = torch.arange(H) + 0.5coords_w = torch.arange(W) + 0.5coords = torch.stack(torch.meshgrid([coords_w, coords_h])).transpose(1, 2).unsqueeze(1).unsqueeze(0).type(x.dtype).to(x.device)normalizer = torch.tensor([W, H], dtype=x.dtype, device=x.device).view(1, 2, 1, 1, 1)coords = 2 * (coords + offset) / normalizer - 1coords = F.pixel_shuffle(coords.view(B, -1, H, W), self.scale).view(B, 2, -1, self.scale * H, self.scale * W).permute(0, 2, 3, 4, 1).contiguous().flatten(0, 1)return F.grid_sample(x.reshape(B * self.groups, -1, H, W), coords, mode='bilinear',align_corners=False, padding_mode="border").view(B, -1, self.scale * H, self.scale * W)def forward_lp(self, x):if hasattr(self, 'scope'):offset = self.offset(x) * self.scope(x).sigmoid() * 0.5 + self.init_poselse:offset = self.offset(x) * 0.25 + self.init_posreturn self.sample(x, offset)def forward_pl(self, x):x_ = F.pixel_shuffle(x, self.scale)if hasattr(self, 'scope'):offset = F.pixel_unshuffle(self.offset(x_) * self.scope(x_).sigmoid(), self.scale) * 0.5 + self.init_poselse:offset = F.pixel_unshuffle(self.offset(x_), self.scale) * 0.25 + self.init_posreturn self.sample(x, offset)def forward(self, x):if self.style == 'pl':return self.forward_pl(x)return self.forward_lp(x)if __name__ == '__main__':x = torch.rand(2, 64, 4, 7)dys = Dy_Sample(64)print(dys(x).shape)

五、添加DySample上采样器

5.1STEP1

首先找到ultralytics/nn文件路径下新建一个Add-module的python文件包【这里注意一定是python文件包,新建后会自动生成_init_.py】,如果已经跟着我的教程建立过一次了可以省略此步骤,随后新建一个DySample.py文件并将上文中提到的注意力机制的代码全部粘贴到此文件中,如下图所示在这里插入图片描述

5.2STEP2

在STEP1中新建的_init_.py文件中导入增加改进模块的代码包如下图所示在这里插入图片描述

5.3STEP3

找到ultralytics/nn文件夹中的task.py文件,在其中按照下图添加在这里插入图片描述

5.4STEP4

定位到ultralytics/nn文件夹中的task.py文件中的def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)函数添加如图代码,【如果不好定位可以直接ctrl+f搜索定位】

在这里插入图片描述

   elif m in {Dy_Sample}:c2=ch[f]args=[c2,*args]

六、yaml文件与运行

6.1yaml文件

以下是添加DySample动态上采样的yaml文件,大家可以注释自行调节,效果以自己的数据集结果为准

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLO11 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolo11n.yaml' will call yolo11.yaml with scale 'n'# [depth, width, max_channels]n: [0.50, 0.25, 1024] # summary: 319 layers, 2624080 parameters, 2624064 gradients, 6.6 GFLOPss: [0.50, 0.50, 1024] # summary: 319 layers, 9458752 parameters, 9458736 gradients, 21.7 GFLOPsm: [0.50, 1.00, 512] # summary: 409 layers, 20114688 parameters, 20114672 gradients, 68.5 GFLOPsl: [1.00, 1.00, 512] # summary: 631 layers, 25372160 parameters, 25372144 gradients, 87.6 GFLOPsx: [1.00, 1.50, 512] # summary: 631 layers, 56966176 parameters, 56966160 gradients, 196.0 GFLOPs# YOLO11n backbone
backbone:# [from, repeats, module, args]- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4- [-1, 2, C3k2, [256, False, 0.25]]- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8- [-1, 2, C3k2, [512, False, 0.25]]- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16- [-1, 2, C3k2, [512, True]]- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32- [-1, 2, C3k2, [1024, True]]- [-1, 1, SPPF, [1024, 5]] # 9- [-1, 2, C2PSA, [1024]] # 10# YOLO11n head
head:- [-1, 1, Dy_Sample, []]- [[-1, 6], 1, Concat, [1]] # cat backbone P4- [-1, 2, C3k2, [512, False]] # 13- [-1, 1, Dy_Sample, []]- [[-1, 4], 1, Concat, [1]] # cat backbone P3- [-1, 2, C3k2, [256, False]] # 16 (P3/8-small)- [-1, 1, Conv, [256, 3, 2]]- [[-1, 13], 1, Concat, [1]] # cat head P4- [-1, 2, C3k2, [512, False]] # 19 (P4/16-medium)- [-1, 1, Conv, [512, 3, 2]]- [[-1, 10], 1, Concat, [1]] # cat head P5- [-1, 2, C3k2, [1024, True]] # 22 (P5/32-large)- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)

以上添加位置仅供参考,具体添加位置以及模块效果以自己的数据集结果为准

6.2运行成功截图

在这里插入图片描述

OK 以上就是添加DySample上采样的全部过程了,后续将持续更新尽情期待

在这里插入图片描述


http://www.mrgr.cn/news/41753.html

相关文章:

  • 昇思MindSpore进阶教程--在ResNet-50网络上应用二阶优化实践(上)
  • 计算机网络期末复习真题(附真题答案)
  • 奶茶在线小程序介绍
  • Linux运维必知应知命令集合
  • 物联网智能项目探究和方案设计
  • ChatGPT效率指南!轻松掌握提高生产力的秘诀!
  • 06 Docker容器内部管理的终极指南:掌握核心技巧与最佳实践
  • 图形化部署Java Web项目的3款工具大全
  • SQL Server—T-sql使用Select查询详解
  • 基于SSM的校园快递一站式服务系统【附源码】
  • 在一个克隆的仓库中设置远程仓库并同步最新的更改
  • 【Linux私房菜(九)之进程间通信】
  • 性能测试为什么需要收集度量指标
  • oracle virtualBox 拖动文件到虚拟机内报错
  • 24-10-2-读书笔记(二十二)-《契诃夫文集》(一)上([俄] 契诃夫 [译] 汝龙)啊!真想生活。
  • VMware Aria Operations for Networks 6.13 发布,新增功能概览
  • MeterSphere压测配置说明
  • GEE 案例:利用MODIS中EVI数据计算2001-2024年变化最强的区域(利用slope显著性变化监测)——以北京市为例
  • 利用函数模块化代码实操 ← Python
  • 使用python基于DeepLabv3实现对图片进行语义分割