YOLOv9改进策略【注意力机制篇】| 引入MobileNetv4中的Mobile MQA,提高模型效率

本文主要是介绍YOLOv9改进策略【注意力机制篇】| 引入MobileNetv4中的Mobile MQA,提高模型效率,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、本文介绍

本文记录的是基于Mobile MQA模块的YOLOv9目标检测改进方法研究MobileNetv4中的Mobile MQA模块是用于模型加速,减少内存访问的模块,相比其他全局的自注意力,其不仅加强了模型对全局信息的关注,同时也显著提高了模型效率。

文章目录

  • 一、本文介绍
  • 二、Mobile MQA注意力原理
  • 三、Mobile MQA的实现代码
  • 四、添加步骤
    • 4.1 修改common.py
      • 4.1.1 创新模块⭐
    • 4.2 修改yolo.py
  • 五、yaml模型文件
    • 5.1 模型改进⭐
  • 六、成功运行结果


二、Mobile MQA注意力原理

在论文《MobileNetV4 - Universal Models for the Mobile Ecosystem》中,提出了Mobile MQA

一、原理

  1. 基于MQA改进并结合不对称空间下采样
    • MQA(Multi-Query Attention)简化了传统的多头注意力机制,通过共享keysvalues来减少内存访问需求。在移动混合模型中,当批量大小较小时,这种方式能有效提高运算强度。
    • 借鉴MQA中对querieskeysvalues的不对称计算方式,Mobile MQA引入了空间缩减注意力(SRA),对keysvalues进行下采样,同时保持高分辨率的queries。这是因为在混合模型中,早期层的空间混合卷积滤波器使得空间上相邻的标记具有相关性。
    • Mobile MQA的计算公式为:
      M o b i l e _ M Q A ( X ) = C o n c a t ( a t t e n t i o n 1 , . . . , a t t e n t i o n n ) W O Mobile\_MQA(X)= Concat(attention_1,...,attention_n)W^{O} Mobile_MQA(X)=Concat(attention1,...,attentionn)WO
      其中 a t t e n t i o n j = s o f t m a x ( ( X W Q j ) ( S R ( X ) W K ) T d k ) ( S R ( X ) W V ) attention_j = softmax(\frac{(XW^{Q_j})(SR(X)W^{K})^{T}}{\sqrt{d_k}})(SR(X)W^{V}) attentionj=softmax(dk (XWQj)(SR(X)WK)T)(SR(X)WV),这里SR可以是空间缩减操作(在设计中是一个步长为2的3x3深度卷积),也可以是恒等函数(当不进行空间缩减时)。

二、特点

  1. 针对加速器优化:专门为移动加速器进行了优化,考虑了移动加速器的计算和内存特性。
  2. 不对称空间下采样:通过对keysvalues进行下采样,保持queries的高分辨率,在不损失太多精度的情况下,显著提高了效率。
  3. 操作简单高效:相比传统的注意力机制,Mobile MQA的设计更加简单,操作更加高效,更适合在移动设备上运行。

论文:http://arxiv.org/abs/2404.10518
源码:https://github.com/tensorflow/models/blob/master/official/vision/modeling/backbones/mobilenet.py

三、Mobile MQA的实现代码

Mobile MQA模块的实现代码如下:

class MultiQueryAttentionLayerWithDownSampling(nn.Module):def __init__(self, in_channels, num_heads, key_dim, value_dim, query_h_strides, query_w_strides, kv_strides, dw_kernel_size=3, dropout=0.0):"""Multi Query Attention with spatial downsampling.Referenced from here https://github.com/tensorflow/models/blob/master/official/vision/modeling/layers/nn_blocks.py3 parameters are introduced for the spatial downsampling:1. kv_strides: downsampling factor on Key and Values only.2. query_h_strides: vertical strides on Query only.3. query_w_strides: horizontal strides on Query only.This is an optimized version.1. Projections in Attention is explict written out as 1x1 Conv2D.2. Additional reshapes are introduced to bring a up to 3x speed up."""super(MultiQueryAttentionLayerWithDownSampling, self).__init__()self.num_heads = num_headsself.key_dim = key_dimself.value_dim = value_dimself.query_h_strides = query_h_stridesself.query_w_strides = query_w_stridesself.kv_strides = kv_stridesself.dw_kernel_size = dw_kernel_sizeself.dropout = dropoutself.head_dim = self.key_dim // num_headsif self.query_h_strides > 1 or self.query_w_strides > 1:self._query_downsampling_norm = nn.BatchNorm2d(in_channels)self._query_proj = conv2d(in_channels, self.num_heads * self.key_dim, 1, 1, norm=False, act=False)if self.kv_strides > 1:self._key_dw_conv = conv2d(in_channels, in_channels, dw_kernel_size, kv_strides, groups=in_channels,norm=True, act=False)self._value_dw_conv = conv2d(in_channels, in_channels, dw_kernel_size, kv_strides, groups=in_channels,norm=True, act=False)self._key_proj = conv2d(in_channels, key_dim, 1, 1, norm=False, act=False)self._value_proj = conv2d(in_channels, key_dim, 1, 1, norm=False, act=False)self._output_proj = conv2d(num_heads * key_dim, in_channels, 1, 1, norm=False, act=False)self.dropout = nn.Dropout(p=dropout)def forward(self, x):bs, seq_len, _, _ = x.size()# print(x.size())if self.query_h_strides > 1 or self.query_w_strides > 1:q = F.avg_pool2d(self.query_h_strides, self.query_w_strides)q = self._query_downsampling_norm(q)q = self._query_proj(q)else:q = self._query_proj(x)px = q.size(2)q = q.view(bs, self.num_heads, -1, self.key_dim)  # [batch_size, num_heads, seq_len, key_dim]if self.kv_strides > 1:k = self._key_dw_conv(x)k = self._key_proj(k)v = self._value_dw_conv(x)v = self._value_proj(v)else:k = self._key_proj(x)v = self._value_proj(x)k = k.view(bs, 1, self.key_dim, -1)   # [batch_size, 1, key_dim, seq_length]v = v.view(bs, 1, -1, self.key_dim)    # [batch_size, 1, seq_length, key_dim]# calculate attention score# print(q.shape, k.shape, v.shape)attn_score = torch.matmul(q, k) / (self.head_dim ** 0.5)attn_score = self.dropout(attn_score)attn_score = F.softmax(attn_score, dim=-1)# context = torch.einsum('bnhm,bmv->bnhv', attn_score, v)# print(attn_score.shape, v.shape)context = torch.matmul(attn_score, v)context = context.view(bs, self.num_heads * self.key_dim, px, px)output = self._output_proj(context)# print(output.shape)return output
参数解释
in_channels输入通道数
num_heads自注意力头的数量
key_dim键的维度
key_dim值的维度
value_dim仅用于查询的,在H方向上的步长
query_h_strides仅用于查询的,在W方向上的步长
query_w_strides仅对键和值进行下采样,1不进行下采样,2下采样
dw_kernel_size=3深度可分离卷积的卷积核大小
dropout=0.0随机丢失比例

四、添加步骤

4.1 修改common.py

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

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

4.1.1 创新模块⭐

模块改进方法:基于Mobile MQA模块RepNCSPELAN4

改进方法是对YOLOv9中的RepNCSPELAN4模块进行改进。RepNCSPELAN4模块的创新思想是将CSPELAN相结合。CSP可以有效地分割梯度流,减少计算量的同时保持准确性。ELAN则通过灵活的层聚合方式,增强网络的学习能力。而MobileNetv4中的Mobile MQA模块则是用于模型加速,减少内存访问的模块,相比其他全局的自注意力,利用Mobile MQA替换RepNCSPELAN4模块中的卷积层后,不仅加强了模型对全局信息的关注,同时也显著提高了模型效率。

改进代码如下:参考代码

class MMQARepNCSPELAN4(nn.Module):# csp-elandef __init__(self, c1, c2, c3, c4, c5=1):  # ch_in, ch_out, number, shortcut, groups, expansionsuper().__init__()self.c = c3//2self.cv1 = Conv(c1, c3, 1, 1)self.cv2 = nn.Sequential(RepNCSP(c3//2, c4, c5), MultiQueryAttentionLayerWithDownSampling(c4, 8, 48, 48, 1, 1, 1))self.cv3 = nn.Sequential(RepNCSP(c4, c4, c5), MultiQueryAttentionLayerWithDownSampling(c4, 8, 48, 48, 1, 1, 1))self.cv4 = Conv(c3+(2*c4), c2, 1, 1)def forward(self, x):y = list(self.cv1(x).chunk(2, 1))y.extend((m(y[-1])) for m in [self.cv2, self.cv3])return self.cv4(torch.cat(y, 1))def forward_split(self, x):y = list(self.cv1(x).split((self.c, self.c), 1))y.extend(m(y[-1]) for m in [self.cv2, self.cv3])return self.cv4(torch.cat(y, 1))

在这里插入图片描述

在这里插入图片描述

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

4.2 修改yolo.py

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

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

MultiQueryAttentionLayerWithDownSampling模块以及MMQARepNCSPELAN4模块添加后如下:

在这里插入图片描述


五、yaml模型文件

5.1 模型改进⭐

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

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

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

📌 模型的修改方法是将骨干网络中的所有RepNCSPELAN4模块替换成MMQARepNCSPELAN4模块,优化整体,提高效率。

结构如下:

# 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, [128, 3, 2]],  # 2-P2/4# elan-1 block[-1, 1, MMQARepNCSPELAN4, [256, 128, 64, 1]],  # 3  修改此处# avg-conv down[-1, 1, ADown, [256]],  # 4-P3/8# elan-2 block[-1, 1, MMQARepNCSPELAN4, [512, 256, 128, 1]],  # 5  修改此处# avg-conv down[-1, 1, ADown, [512]],  # 6-P4/16# elan-2 block[-1, 1, MMQARepNCSPELAN4, [512, 512, 256, 1]],  # 7  修改此处# avg-conv down[-1, 1, ADown, [512]],  # 8-P5/32# elan-2 block[-1, 1, MMQARepNCSPELAN4, [512, 512, 256, 1]],  # 9  修改此处]# YOLOv9 head
head:[# elan-spp block[-1, 1, SPPELAN, [512, 256]],  # 10# up-concat merge[-1, 1, nn.Upsample, [None, 2, 'nearest']],[[-1, 7], 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, 5], 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, 13], 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, 10], 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[5, 1, CBLinear, [[256]]], # 23[7, 1, CBLinear, [[256, 512]]], # 24[9, 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[[23, 24, 25, -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[[24, 25, -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[[25, -1], 1, CBFuse, [[2]]], # 36# elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 37# detection head# detect[[31, 34, 37, 16, 19, 22], 1, DualDDetect, [nc]],  # DualDDetect(A3, A4, A5, P3, P4, P5)]

六、成功运行结果

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

yolov9-c-MMQARepNCSPELAN4

                 from  n    params  module                                  arguments                     0                -1  1         0  models.common.Silence                   []                            1                -1  1      1856  models.common.Conv                      [3, 64, 3, 2]                 2                -1  1     73984  models.common.Conv                      [64, 128, 3, 2]               3                -1  1    249472  models.common.MMQARepNCSPELAN4          [128, 256, 128, 64, 1]        4                -1  1    164352  models.common.ADown                     [256, 256]                    5                -1  1    773376  models.common.MMQARepNCSPELAN4          [256, 512, 256, 128, 1]       6                -1  1    656384  models.common.ADown                     [512, 512]                    7                -1  1   2119168  models.common.MMQARepNCSPELAN4          [512, 512, 512, 256, 1]       8                -1  1    656384  models.common.ADown                     [512, 512]                    9                -1  1   2119168  models.common.MMQARepNCSPELAN4          [512, 512, 512, 256, 1]       10                -1  1    656896  models.common.SPPELAN                   [512, 512, 256]               11                -1  1         0  torch.nn.modules.upsampling.Upsample    [None, 2, 'nearest']          12           [-1, 7]  1         0  models.common.Concat                    [1]                           13                -1  1   3119616  models.common.RepNCSPELAN4              [1024, 512, 512, 256, 1]      14                -1  1         0  torch.nn.modules.upsampling.Upsample    [None, 2, 'nearest']          15           [-1, 5]  1         0  models.common.Concat                    [1]                           16                -1  1    912640  models.common.RepNCSPELAN4              [1024, 256, 256, 128, 1]      17                -1  1    164352  models.common.ADown                     [256, 256]                    18          [-1, 13]  1         0  models.common.Concat                    [1]                           19                -1  1   2988544  models.common.RepNCSPELAN4              [768, 512, 512, 256, 1]       20                -1  1    656384  models.common.ADown                     [512, 512]                    21          [-1, 10]  1         0  models.common.Concat                    [1]                           22                -1  1   3119616  models.common.RepNCSPELAN4              [1024, 512, 512, 256, 1]      23                 5  1    131328  models.common.CBLinear                  [512, [256]]                  24                 7  1    393984  models.common.CBLinear                  [512, [256, 512]]             25                 9  1    656640  models.common.CBLinear                  [512, [256, 512, 512]]        26                 0  1      1856  models.common.Conv                      [3, 64, 3, 2]                 27                -1  1     73984  models.common.Conv                      [64, 128, 3, 2]               28                -1  1    212864  models.common.RepNCSPELAN4              [128, 256, 128, 64, 1]        29                -1  1    164352  models.common.ADown                     [256, 256]                    30  [23, 24, 25, -1]  1         0  models.common.CBFuse                    [[0, 0, 0]]                   31                -1  1    847616  models.common.RepNCSPELAN4              [256, 512, 256, 128, 1]       32                -1  1    656384  models.common.ADown                     [512, 512]                    33      [24, 25, -1]  1         0  models.common.CBFuse                    [[1, 1]]                      34                -1  1   2857472  models.common.RepNCSPELAN4              [512, 512, 512, 256, 1]       35                -1  1    656384  models.common.ADown                     [512, 512]                    36          [25, -1]  1         0  models.common.CBFuse                    [[2]]                         37                -1  1   2857472  models.common.RepNCSPELAN4              [512, 512, 512, 256, 1]       38[31, 34, 37, 16, 19, 22]  1  21542822  DualDDetect                             [1, [512, 512, 512, 256, 512, 512]]
yolov9-c-MMQARepNCSPELAN4 summary: 1018 layers, 49485350 parameters, 49485318 gradients, 236.8 GFLOPs

这篇关于YOLOv9改进策略【注意力机制篇】| 引入MobileNetv4中的Mobile MQA,提高模型效率的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1105778

相关文章

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

java中反射(Reflection)机制举例详解

《java中反射(Reflection)机制举例详解》Java中的反射机制是指Java程序在运行期间可以获取到一个对象的全部信息,:本文主要介绍java中反射(Reflection)机制的相关资料... 目录一、什么是反射?二、反射的用途三、获取Class对象四、Class类型的对象使用场景1五、Class

基于Flask框架添加多个AI模型的API并进行交互

《基于Flask框架添加多个AI模型的API并进行交互》:本文主要介绍如何基于Flask框架开发AI模型API管理系统,允许用户添加、删除不同AI模型的API密钥,感兴趣的可以了解下... 目录1. 概述2. 后端代码说明2.1 依赖库导入2.2 应用初始化2.3 API 存储字典2.4 路由函数2.5 应

一文教你Python引入其他文件夹下的.py文件

《一文教你Python引入其他文件夹下的.py文件》这篇文章主要为大家详细介绍了如何在Python中引入其他文件夹里的.py文件,并探讨几种常见的实现方式,有需要的小伙伴可以根据需求进行选择... 目录1. 使用sys.path动态添加路径2. 使用相对导入(适用于包结构)3. 使用pythonPATH环境

SpringBoot如何通过Map实现策略模式

《SpringBoot如何通过Map实现策略模式》策略模式是一种行为设计模式,它允许在运行时选择算法的行为,在Spring框架中,我们可以利用@Resource注解和Map集合来优雅地实现策略模式,这... 目录前言底层机制解析Spring的集合类型自动装配@Resource注解的行为实现原理使用直接使用M

Redis 内存淘汰策略深度解析(最新推荐)

《Redis内存淘汰策略深度解析(最新推荐)》本文详细探讨了Redis的内存淘汰策略、实现原理、适用场景及最佳实践,介绍了八种内存淘汰策略,包括noeviction、LRU、LFU、TTL、Rand... 目录一、 内存淘汰策略概述二、内存淘汰策略详解2.1 ​noeviction(不淘汰)​2.2 ​LR

C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)

《C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)》本文主要介绍了C#集成DeepSeek模型实现AI私有化的方法,包括搭建基础环境,如安装Ollama和下载DeepS... 目录前言搭建基础环境1、安装 Ollama2、下载 DeepSeek R1 模型客户端 ChatBo

Nginx之upstream被动式重试机制的实现

《Nginx之upstream被动式重试机制的实现》本文主要介绍了Nginx之upstream被动式重试机制的实现,可以通过proxy_next_upstream来自定义配置,具有一定的参考价值,感兴... 目录默认错误选择定义错误指令配置proxy_next_upstreamproxy_next_upst

SpringBoot快速接入OpenAI大模型的方法(JDK8)

《SpringBoot快速接入OpenAI大模型的方法(JDK8)》本文介绍了如何使用AI4J快速接入OpenAI大模型,并展示了如何实现流式与非流式的输出,以及对函数调用的使用,AI4J支持JDK8... 目录使用AI4J快速接入OpenAI大模型介绍AI4J-github快速使用创建SpringBoot

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应