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

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

时间:2024-08-28 17:51:01浏览次数:12  
标签:MQA strides Mobile self YOLOv9 models common 512 256

一、本文介绍

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

文章目录


二、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.py

        3 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_heads
        self.key_dim = key_dim
        self.value_dim = value_dim
        self.query_h_strides = query_h_strides
        self.query_w_strides = query_w_strides
        self.kv_strides = kv_strides
        self.dw_kernel_size = dw_kernel_size
        self.dropout = dropout

        self.head_dim = self.key_dim // num_heads

        if 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-elan
    def __init__(self, c1, c2, c3, c4, c5=1):  # ch_in, ch_out, number, shortcut, groups, expansion
        super().__init__()
        self.c = c3//2
        self.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数量等于自己数据中目标的数量。

标签:MQA,strides,Mobile,self,YOLOv9,models,common,512,256
From: https://blog.csdn.net/qq_42591591/article/details/140667578

相关文章

  • YOLOv9改进策略【卷积层】| 利用MobileNetv4中的UIB、ExtraDW优化RepNCSPELAN4
    一、本文介绍本文记录的是利用ExtraDW优化YOLOv9中的RepNCSPELAN4,详细说明了优化原因,注意事项等。ExtraDW是MobileNetv4模型中提出的新模块,允许以低成本增加网络深度和感受野,具有ConvNext和IB的组合优势。可以在提高模型精度的同时降低一定量的模型参数。文章目录一、......
  • COMP5216 Mobile Computing
    COMP5216MobileComputing2024S2SchoolofComputerSciencePage1of2Assignment1AcademicPlannerAppTotal:5marksDuedate:5pm21stAugust2024(Week04)Submissionrequirements:Submitallprojectfilesasonezippedfile.Youwilldemo......
  • AutodL训练yolov9
    AutodL训练yolov9全过程1、租借Autodl服务器:AutoDL算力云|弹性、好用、省钱。租GPU就上AutoDL选择环境,直接选择镜像,yolov9官方2、创建完成:点击Jupyterlab进入服务器,到这里服务器租用完成2、下载yolov9官网代码:https://github.com/WongKinYiu/yolov93、进入服务器,上......
  • YOLOv8改进系列,YOLOv8替换主干网络为MobileNetV2(轻量化架构+助力涨点)
    原论文摘要MobileNetV2架构在多个任务和基准测试中提高了移动模型的最先进性能,并在不同的模型规模中表现出色。我们还介绍了在一种我们称之为SSDLite的新框架中应用这些移动模型进行目标检测的高效方法。MobileNetV2理论详解可以参考链接:论文地址本文在YOLOv8中的主干......
  • YoloV9改进策略:注意力机制改进|通过iAFF模块优化RepNBottleneck结构,YoloV9性能飞跃|即
    摘要在深度学习和计算机视觉领域,YoloV9以其卓越的目标检测性能赢得了广泛的关注与应用。为了进一步提升YoloV9的识别精度和鲁棒性,我们创新性地在其核心组件——RepNBottleneck模块中引入了迭代注意力特征融合(iAFF)模块。这一改进不仅实现了显著的涨点效果,还展现了在复杂场景......
  • YOLOv5改进 | 主干网络 | 将backbone替换为MobileNetV2【小白必备教程+附完整代码】
    秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转......
  • YOLOv9改进系列,YOLOv9引入SPDConv(新颖的卷积),用于低分辨率图像和小物体目标,实现大幅
    前言卷积神经网络在许多计算机视觉任务中取得了显著成功,例如图像分类和目标检测。然而,在图像分辨率较低或目标较小的更困难任务中,它们的性能会迅速下降。在本文中,指出这根源于现有CNN架构中一个常见但有缺陷的设计,即使用了步幅卷积和/或池化层,这导致了细粒度信息的丢失以......
  • Mobile Systems, Applications, and Services (MobiSys, MOBISYS)
    MobileSystems,Applications,andServices{MobiSys,MOBISYS}1.AssociationforComputingMachinery(ACM)2.ACMConferences3.MobileSystems,Applications,andServices(MobiSys,MOBISYS)3.1.Proceedingsofthe22ndAnnualInternationalCon......
  • Tensorflow 对象检测 API Mobilenet SSD 输入图像大小错误
    我正在尝试使用MobileNetSSDv1fpn640x640使用Tensorflow对象检测API来实现对象检测算法。但我的输入图像大小为1024x25。但是当我运行训练脚本时,它给出了类似“输入尺寸必须大于33”的错误。我想知道使用MobilenetSSD时与输入图像大小相关的约束是什么,以及是......
  • 2. mqant——进阶篇
    6.RPC高级用法6.1动态监听handler有些场景下,我们无法在编译阶段提前实现或注册好所有的handler,但在执行时可以通过一些动态规则动态分配handler。mqant也支持这样的功能场景6.1.1 handler监听器typeRPCListenerinterface{/**NoFoundFunction当未找到请......