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

YOLOv9改进策略【模型轻量化】| MoblieNetV3:基于搜索技术和新颖架构设计的轻量型网络模型

一、本文介绍

本文记录的是基于MobileNet V3的YOLOv9目标检测轻量化改进方法研究MobileNet V3的模型结构是通过网络搜索得来的,其中的基础模块结合了MobileNet V1的深度可分离卷积、MobileNet V2的线性瓶颈和倒置残差结构以及MnasNet中基于挤压和激励的轻量级注意力模块,使模型在性能、效率和灵活性方面都具有显著的优势。

模型参数量计算量推理速度(bs=32)
YOLOv9-c50.69M236.6GFLOPs32.1ms
Improved42.05M192.3GFLOPs28.1ms

文章目录

  • 一、本文介绍
  • 二、MoblieNet V3设计原理
  • 三、GhostModuleV2模块的实现代码
  • 四、添加步骤
    • 4.1 修改common.py
    • 4.2 修改yolo.py
  • 五、yaml模型文件
    • 5.1 模型改进⭐
  • 六、成功运行结果


二、MoblieNet V3设计原理

MobileNet V3是基于一系列互补的搜索技术和新颖的架构设计而提出的新一代神经网络模型,其设计的原理和优势主要包括以下几个方面:

  1. 原理
    • 网络搜索
      • 平台感知的NAS(Platform - Aware NAS):用于搜索全局网络结构,通过优化每个网络块来实现。对于大型移动模型,复用了MnasNet - A1的结构,并在此基础上应用NetAdapt和其他优化。对于小型移动模型,观察到原奖励设计未针对其优化,因此调整了权重因子w,重新进行架构搜索以找到初始种子模型。
      • NetAdapt:用于逐层搜索过滤器的数量,是对平台感知的NAS的补充。它从平台感知的NAS找到的种子网络架构开始,通过生成新的提案并根据某些指标选择最佳提案,逐步微调单个层,直到达到目标延迟。在选择提案时,修改了算法以最小化延迟变化和准确率变化的比率。
    • 网络改进
      • 重新设计昂贵层:对网络末尾和开头的一些昂贵层进行修改。对于末尾的层,将产生最终特征的层移动到最终平均池化之后,以降低延迟并保持高维特征,同时去除了之前瓶颈层中的投影和过滤层,进一步降低计算复杂度。对于初始的滤波器层,实验发现使用hard swish非线性函数并将滤波器数量减少到16时,能在保持准确率的同时减少延迟和计算量。
      • 非线性函数:引入了名为h-swish的非线性函数,它是swish非线性函数的改进版本,计算更快且更有利于量化。通过将sigmoid函数替换为分段线性的hard版本(如h - swish [x] = x * ReLU6(x + 3) / 6),并在网络的后半部分使用h-swish,减少了计算成本,同时在准确率上与原始版本没有明显差异。
      • 大的挤压 - 激励(Large squeeze - and - excite):将挤压 - 激励瓶颈的大小固定为扩展层通道数的1 / 4,在增加少量参数的情况下提高了准确率,且没有明显的延迟成本。
    • 高效的移动构建块:结合了MobileNet V1的深度可分离卷积、MobileNet V2的线性瓶颈和倒置残差结构以及MnasNet中基于挤压和激励的轻量级注意力模块,同时升级了这些层,使用修改后的swish非线性函数以提高效率。

在这里插入图片描述

  1. 优势

    • MobileNet V3通过网络搜索和改进,结合了多种技术的优势,在性能、效率和灵活性方面都具有显著的优势,适用于移动设备上的各种计算机视觉任务。并且定义了MobileNetV3 - LargeMobileNetV3 - Small两个模型,分别针对高资源和低资源使用场景,可根据不同需求进行选择和应用。

论文:https://arxiv.org/abs/2211.12905
源码:https://github.com/huawei-noah/Efficient-AI-Backbones/tree/master/ghostnetv2_pytorch

三、GhostModuleV2模块的实现代码

GhostModuleV2模块的实现代码如下:

class h_sigmoid(nn.Module):def __init__(self, inplace=True):super(h_sigmoid, self).__init__()self.relu = nn.ReLU6(inplace=inplace)def forward(self, x):return self.relu(x + 3) / 6class h_swish(nn.Module):def __init__(self, inplace=True):super(h_swish, self).__init__()self.sigmoid = h_sigmoid(inplace=inplace)def forward(self, x):return x * self.sigmoid(x)class SELayer(nn.Module):def __init__(self, channel, reduction=4):super(SELayer, self).__init__()self.avg_pool = nn.AdaptiveAvgPool2d(1)self.fc = nn.Sequential(nn.Linear(channel, channel // reduction),nn.ReLU(inplace=True),nn.Linear(channel // reduction, channel),h_sigmoid())def forward(self, x):b, c, _, _ = x.size()y = self.avg_pool(x)y = y.view(b, c)y = self.fc(y).view(b, c, 1, 1)return x * yclass conv_bn_hswish(nn.Module):def __init__(self, c1, c2, stride):super(conv_bn_hswish, self).__init__()self.conv = nn.Conv2d(c1, c2, 3, stride, 1, bias=False)self.bn = nn.BatchNorm2d(c2)self.act = h_swish()def forward(self, x):return self.act(self.bn(self.conv(x)))def fuseforward(self, x):return self.act(self.conv(x))class MobileNet_Block(nn.Module):def __init__(self, inp, oup, hidden_dim, kernel_size, stride, use_se, use_hs):super(MobileNet_Block, self).__init__()assert stride in [1, 2]self.identity = stride == 1 and inp == oupif inp == hidden_dim:self.conv = nn.Sequential(# dwnn.Conv2d(hidden_dim, hidden_dim, kernel_size, stride, (kernel_size - 1) // 2, groups=hidden_dim,bias=False),nn.BatchNorm2d(hidden_dim),h_swish() if use_hs else nn.ReLU(inplace=True),# Squeeze-and-ExciteSELayer(hidden_dim) if use_se else nn.Sequential(),# pw-linearnn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),nn.BatchNorm2d(oup),)else:self.conv = nn.Sequential(# pwnn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),nn.BatchNorm2d(hidden_dim),h_swish() if use_hs else nn.ReLU(inplace=True),# dwnn.Conv2d(hidden_dim, hidden_dim, kernel_size, stride, (kernel_size - 1) // 2, groups=hidden_dim,bias=False),nn.BatchNorm2d(hidden_dim),# Squeeze-and-ExciteSELayer(hidden_dim) if use_se else nn.Sequential(),h_swish() if use_hs else nn.ReLU(inplace=True),# pw-linearnn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),nn.BatchNorm2d(oup),)def forward(self, x):y = self.conv(x)if self.identity:return x + yelse:return y

四、添加步骤

4.1 修改common.py

此处需要修改的文件是models/common.py

common.py中定义了网络结构的通用模块,我们想要加入新的模块就只需要将模块代码放到这个文件内即可。

此时需要将上方实现的代码添加到common.py中。

在这里插入图片描述

注意❗:在4.2小节中的yolo.py文件中需要声明的模块名称为:conv_bn_hswishMobileNet_Block

4.2 修改yolo.py

此处需要修改的文件是models/yolo.py

yolo.py用于函数调用,我们只需要将common.py中定义的新的模块名添加到parse_model函数下即可。

conv_bn_hswishMobileNet_Block模块添加后如下:

在这里插入图片描述


五、yaml模型文件

5.1 模型改进⭐

在代码配置完成后,配置模型的YAML文件。

此处以models/detect/yolov9-c.yaml为例,在同目录下创建一个用于自己数据集训练的模型文件yolov9-c-mobilenetv3 .yaml

yolov9-c.yaml中的内容复制到yolov9-c-mobilenetv3 .yaml文件下,修改nc数量等于自己数据中目标的数量。

📌 模型的修改方法是将骨干网络中的所有RepNCSPELAN4模块替换成MobileNet_Block模块,搭建MobileNetV3 - Small模型,并将其替换YOLOv9的骨干网络,相比原有的骨干网络,这可以大大减少模型的计算负担,提高推理速度,并且减小后的模型,使其在部署应用方面更加方便。

结构如下:

# YOLOv9# parameters
nc: 1  # number of classes
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple
#activation: nn.LeakyReLU(0.1)
#activation: nn.ReLU()# anchors
anchors: 3# YOLOv9 backbone
backbone:[[-1, 1, Silence, []],  # conv down#  [-1, 1, Conv, [64, 3, 2]],  # 1-P1/2# conv down[-1, 1, conv_bn_hswish, [16, 2]],  # 1-P1/2# elan-1 block[-1, 1, MobileNet_Block, [16,  16, 3, 2, 1, 0]],  # 2-P2/4# avg-conv down[-1, 1, MobileNet_Block, [24,  72, 3, 2, 0, 0]],  # 3-P3/8# elan-2 block[-1, 1, MobileNet_Block, [24,  88, 3, 1, 0, 0]],  # 4# avg-conv down[-1, 1, MobileNet_Block, [40,  96, 5, 2, 1, 1]],  # 5-P4/16# elan-2 block[-1, 1, MobileNet_Block, [40, 240, 5, 1, 1, 1]],  # 6[-1, 1, MobileNet_Block, [40, 240, 5, 1, 1, 1]],  # 7[-1, 1, MobileNet_Block, [48, 120, 5, 1, 1, 1]],  # 8[-1, 1, MobileNet_Block, [48, 144, 5, 1, 1, 1]],  # 9# avg-conv down[-1, 1, MobileNet_Block, [96, 288, 5, 2, 1, 1]],  # 10-P5/32# elan-2 block[-1, 1, MobileNet_Block, [96, 576, 5, 1, 1, 1]],  # 11[-1, 1, MobileNet_Block, [96, 576, 5, 1, 1, 1]],  # 12]# YOLOv9 head
head:[# elan-spp block[-1, 1, SPPELAN, [512, 256]],  # 10# up-concat merge[-1, 1, nn.Upsample, [None, 2, 'nearest']],[[-1, 9], 1, Concat, [1]],  # cat backbone P4# elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 13# up-concat merge[-1, 1, nn.Upsample, [None, 2, 'nearest']],[[-1, 4], 1, Concat, [1]],  # cat backbone P3# elan-2 block[-1, 1, RepNCSPELAN4, [256, 256, 128, 1]],  # 16 (P3/8-small)# avg-conv-down merge[-1, 1, ADown, [256]],[[-1, 16], 1, Concat, [1]],  # cat head P4# elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 19 (P4/16-medium)# avg-conv-down merge[-1, 1, ADown, [512]],[[-1, 13], 1, Concat, [1]],  # cat head P5# elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 22 (P5/32-large)# multi-level reversible auxiliary branch# routing[4, 1, CBLinear, [[256]]], # 23[9, 1, CBLinear, [[256, 512]]], # 24[12, 1, CBLinear, [[256, 512, 512]]], # 25# conv down[0, 1, Conv, [64, 3, 2]],  # 26-P1/2# conv down[-1, 1, Conv, [128, 3, 2]],  # 27-P2/4# elan-1 block[-1, 1, RepNCSPELAN4, [256, 128, 64, 1]],  # 28# avg-conv down fuse[-1, 1, ADown, [256]],  # 29-P3/8[[26, 27, 28, -1], 1, CBFuse, [[0, 0, 0]]], # 30  # elan-2 block[-1, 1, RepNCSPELAN4, [512, 256, 128, 1]],  # 31# avg-conv down fuse[-1, 1, ADown, [512]],  # 32-P4/16[[27, 28, -1], 1, CBFuse, [[1, 1]]], # 33 # elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 34# avg-conv down fuse[-1, 1, ADown, [512]],  # 35-P5/32[[28, -1], 1, CBFuse, [[2]]], # 36# elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 37# detection head# detect[[34, 37, 40, 19, 22, 25], 1, DualDDetect, [nc]],  # DualDDetect(A3, A4, A5, P3, P4, P5)]

六、成功运行结果

分别打印网络模型可以看到MobileNet_Block已经加入到模型中,并可以进行训练了。

yolov9-c-mobilenetv3

                 from  n    params  module                                  arguments                     0                -1  1         0  models.common.Silence                   []                            1                -1  1       464  models.common.conv_bn_hswish            [3, 16, 2]                    2                -1  1       612  models.common.MobileNet_Block           [16, 16, 16, 3, 2, 1, 0]      3                -1  1      3864  models.common.MobileNet_Block           [16, 24, 72, 3, 2, 0, 0]      4                -1  1      5416  models.common.MobileNet_Block           [24, 24, 88, 3, 1, 0, 0]      5                -1  1     13736  models.common.MobileNet_Block           [24, 40, 96, 5, 2, 1, 1]      6                -1  1     55340  models.common.MobileNet_Block           [40, 40, 240, 5, 1, 1, 1]     7                -1  1     55340  models.common.MobileNet_Block           [40, 40, 240, 5, 1, 1, 1]     8                -1  1     21486  models.common.MobileNet_Block           [40, 48, 120, 5, 1, 1, 1]     9                -1  1     28644  models.common.MobileNet_Block           [48, 48, 144, 5, 1, 1, 1]     10                -1  1     91848  models.common.MobileNet_Block           [48, 96, 288, 5, 2, 1, 1]     11                -1  1    294096  models.common.MobileNet_Block           [96, 96, 576, 5, 1, 1, 1]     12                -1  1    294096  models.common.MobileNet_Block           [96, 96, 576, 5, 1, 1, 1]     13                -1  1    550400  models.common.SPPELAN                   [96, 512, 256]                14                -1  1         0  torch.nn.modules.upsampling.Upsample    [None, 2, 'nearest']          15           [-1, 9]  1         0  models.common.Concat                    [1]                           16                -1  1   2882048  models.common.RepNCSPELAN4              [560, 512, 512, 256, 1]       17                -1  1         0  torch.nn.modules.upsampling.Upsample    [None, 2, 'nearest']          18           [-1, 4]  1         0  models.common.Concat                    [1]                           19                -1  1    787712  models.common.RepNCSPELAN4              [536, 256, 256, 128, 1]       20                -1  1    164352  models.common.ADown                     [256, 256]                    21          [-1, 16]  1         0  models.common.Concat                    [1]                           22                -1  1   2988544  models.common.RepNCSPELAN4              [768, 512, 512, 256, 1]       23                -1  1    656384  models.common.ADown                     [512, 512]                    24          [-1, 13]  1         0  models.common.Concat                    [1]                           25                -1  1   3119616  models.common.RepNCSPELAN4              [1024, 512, 512, 256, 1]      26                 4  1      6400  models.common.CBLinear                  [24, [256]]                   27                 9  1     37632  models.common.CBLinear                  [48, [256, 512]]              28                12  1    124160  models.common.CBLinear                  [96, [256, 512, 512]]         29                 0  1      1856  models.common.Conv                      [3, 64, 3, 2]                 30                -1  1     73984  models.common.Conv                      [64, 128, 3, 2]               31                -1  1    212864  models.common.RepNCSPELAN4              [128, 256, 128, 64, 1]        32                -1  1    164352  models.common.ADown                     [256, 256]                    33  [26, 27, 28, -1]  1         0  models.common.CBFuse                    [[0, 0, 0]]                   34                -1  1    847616  models.common.RepNCSPELAN4              [256, 512, 256, 128, 1]       35                -1  1    656384  models.common.ADown                     [512, 512]                    36      [27, 28, -1]  1         0  models.common.CBFuse                    [[1, 1]]                      37                -1  1   2857472  models.common.RepNCSPELAN4              [512, 512, 512, 256, 1]       38                -1  1    656384  models.common.ADown                     [512, 512]                    39          [28, -1]  1         0  models.common.CBFuse                    [[2]]                         40                -1  1   2857472  models.common.RepNCSPELAN4              [512, 512, 512, 256, 1]       41[34, 37, 40, 19, 22, 25]  1  21542822  models.yolo.DualDDetect                 [1, [512, 512, 512, 256, 512, 512]]
yolov9-c-mobilenetv3 summary: 902 layers, 42053396 parameters, 42053364 gradients, 192.3 GFLOPs

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 前端内存泄露案例与解决方案
  • Ubuntu 安装个人热点
  • 字符集介绍
  • 八、2 DMA数据转运 DMA函数介绍
  • 使用 streamlink 把 m3u8 转为 mp4
  • 如何使用IDEA搭建Mybatis框架环境(详细教程)
  • 什么是USB?
  • 前端配置环境
  • RabbitMQ 入门:基本概念、特性及简单示例
  • 开学季老师如何发布分班?
  • 奇偶校验、crc循环冗余检验
  • pg 唯一性约束修复
  • Go语言的编程规则和秘籍
  • dll高级技术--动态注入:ImgWalk动态库,这个DLL用来检测被注入的进程中当前载入的各个模块名称---DLL程序
  • 公安智慧大楼信息化整体建设设计方案
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • Github访问慢解决办法
  • Logstash 参考指南(目录)
  • Spring框架之我见(三)——IOC、AOP
  • Vue 动态创建 component
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 深度学习入门:10门免费线上课程推荐
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 听说你叫Java(二)–Servlet请求
  • 我这样减少了26.5M Java内存!
  • 吴恩达Deep Learning课程练习题参考答案——R语言版
  • 协程
  • 与 ConTeXt MkIV 官方文档的接驳
  • 正则学习笔记
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • ​Benvista PhotoZoom Pro 9.0.4新功能介绍
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • #13 yum、编译安装与sed命令的使用
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • (4)(4.6) Triducer
  • (day 12)JavaScript学习笔记(数组3)
  • (vue)el-tabs选中最后一项后更新数据后无法展开
  • (八十八)VFL语言初步 - 实现布局
  • (规划)24届春招和25届暑假实习路线准备规划
  • (机器学习的矩阵)(向量、矩阵与多元线性回归)
  • (十七)Flink 容错机制
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (原创) cocos2dx使用Curl连接网络(客户端)
  • *Django中的Ajax 纯js的书写样式1
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .[hudsonL@cock.li].mkp勒索加密数据库完美恢复---惜分飞
  • .“空心村”成因分析及解决对策122344
  • .NET CF命令行调试器MDbg入门(一)
  • .NET CORE 第一节 创建基本的 asp.net core
  • .net core docker部署教程和细节问题
  • .NET/C# 如何获取当前进程的 CPU 和内存占用?如何获取全局 CPU 和内存占用?
  • .Net中的集合
  • /run/containerd/containerd.sock connect: connection refused
  • @media screen 针对不同移动设备