YOLO11改进|注意力机制篇|引入注意力与卷积混合的ACmix

news2024/10/4 10:50:00

在这里插入图片描述

目录

    • 一、ACmix注意力机制
      • 1.1ACmix注意力介绍
      • 1.2ACmix核心代码
    • 二、添加ACmix注意力机制
      • 2.1STEP1
      • 2.2STEP2
      • 2.3STEP3
      • 2.4STEP4
    • 三、yaml文件与运行
      • 3.1yaml文件
      • 3.2运行成功截图

一、ACmix注意力机制

1.1ACmix注意力介绍

在这里插入图片描述

ACmix设计为一个结合了卷积和自注意力机制优势的混合模块,旨在通过融合两种机制的优点来增强模型的表示能力和性能。工作流程图如下所示其中:(a)卷积(Convolution)、(b)自注意力(Self-Attention) 和 ©ACMix。每种方法处理特征的方式不同,以下我将为您简要介绍每个模块的工作流程和其作用。

  1. 卷积(Convolution) (a)
    Stage I: 输入的特征图通过多个1x1卷积进行特征投影,目的是将通道数减少或映射到不同的空间维度。这一步相当于一个线性变换。
    Stage II: 接下来通过一个标准的3x3卷积核对特征图进行局部特征提取,这是一种固定的窗口操作,只关注局部邻域内的信息。
    作用:卷积操作是一种高效的局部信息提取方式,在保持计算效率的同时能够有效捕捉局部模式。但其局限性在于缺乏对远程依赖关系的建模能力。

  2. 自注意力(Self-Attention) (b)
    Stage I: 同样通过1x1卷积进行特征投影,将特征图映射到键(key)、查询(query)、值(value)的特征空间。
    Stage II: 使用键和查询进行相似度匹配,生成注意力权重,进而通过权重加权得到新的特征表示。这个过程是全局的,因此每个位置的特征都可以与其他所有位置进行交互。
    作用:自注意力机制的优势在于其能够建模全局依赖关系,使得每个特征点都可以捕捉到其他点的信息,特别适合处理长距离依赖的问题。然而,它的计算成本较高,特别是在大规模特征图上。

  3. ACMix ©
    Stage I: 首先通过1x1卷积将输入特征投影到较低的通道空间,随后进行位移和求和操作。这一步允许特征在空间上有一定的移动(Shift),增强了特征的多样性。
    Stage II: 分别在空间域和通道域进行不同的操作。在空间域,进行类似卷积的局部特征提取;在通道域,采用注意力机制进行全局依赖关系建模。最后,将两者的结果通过加权方式融合。
    作用:ACMix 模块结合了卷积的局部特征提取优势和自注意力的全局信息建模能力,在保持较高计算效率的同时兼具全局与局部特征的处理。它的创新点在于通过对空间和通道的分离操作,减少了全局建模的计算成本,同时提升了模型的表达能力。

总结:
卷积模块(图a)适用于局部特征提取,计算效率高但缺乏全局信息。
自注意力模块(图b)擅长全局依赖建模,但计算成本较高。
ACMix模块(图c)结合了卷积和自注意力的优点,能够有效处理局部和全局信息,同时保持相对较低的计算复杂度,非常适合需要在效率与全局依赖建模间平衡的任务。
在这里插入图片描述

1.2ACmix核心代码

import torch
import torch.nn as nn
 
def position(H, W, type, is_cuda=True):
    if is_cuda:
        loc_w = torch.linspace(-1.0, 1.0, W).cuda().unsqueeze(0).repeat(H, 1).to(type)
        loc_h = torch.linspace(-1.0, 1.0, H).cuda().unsqueeze(1).repeat(1, W).to(type)
    else:
        loc_w = torch.linspace(-1.0, 1.0, W).unsqueeze(0).repeat(H, 1)
        loc_h = torch.linspace(-1.0, 1.0, H).unsqueeze(1).repeat(1, W)
    loc = torch.cat([loc_w.unsqueeze(0), loc_h.unsqueeze(0)], 0).unsqueeze(0)
    return loc
 
def stride(x, stride):
    b, c, h, w = x.shape
    return x[:, :, ::stride, ::stride]
 
def init_rate_half(tensor):
    if tensor is not None:
        tensor.data.fill_(0.5)
 
def init_rate_0(tensor):
    if tensor is not None:
        tensor.data.fill_(0.)
 
 
class ACmix(nn.Module):
    def __init__(self, in_planes, kernel_att=7, head=4, kernel_conv=3, stride=1, dilation=1):
        super(ACmix, self).__init__()
        out_planes = in_planes
        self.in_planes = in_planes
        self.out_planes = out_planes
        self.head = head
        self.kernel_att = kernel_att
        self.kernel_conv = kernel_conv
        self.stride = stride
        self.dilation = dilation
        self.rate1 = torch.nn.Parameter(torch.Tensor(1))
        self.rate2 = torch.nn.Parameter(torch.Tensor(1))
        self.head_dim = self.out_planes // self.head
 
        self.conv1 = nn.Conv2d(in_planes, out_planes, kernel_size=1)
        self.conv2 = nn.Conv2d(in_planes, out_planes, kernel_size=1)
        self.conv3 = nn.Conv2d(in_planes, out_planes, kernel_size=1)
        self.conv_p = nn.Conv2d(2, self.head_dim, kernel_size=1)
 
        self.padding_att = (self.dilation * (self.kernel_att - 1) + 1) // 2
        self.pad_att = torch.nn.ReflectionPad2d(self.padding_att)
        self.unfold = nn.Unfold(kernel_size=self.kernel_att, padding=0, stride=self.stride)
        self.softmax = torch.nn.Softmax(dim=1)
 
        self.fc = nn.Conv2d(3 * self.head, self.kernel_conv * self.kernel_conv, kernel_size=1, bias=False)
        self.dep_conv = nn.Conv2d(self.kernel_conv * self.kernel_conv * self.head_dim, out_planes,
                                  kernel_size=self.kernel_conv, bias=True, groups=self.head_dim, padding=1,
                                  stride=stride)
 
        self.reset_parameters()
 
    def reset_parameters(self):
        init_rate_half(self.rate1)
        init_rate_half(self.rate2)
        kernel = torch.zeros(self.kernel_conv * self.kernel_conv, self.kernel_conv, self.kernel_conv)
        for i in range(self.kernel_conv * self.kernel_conv):
            kernel[i, i // self.kernel_conv, i % self.kernel_conv] = 1.
        kernel = kernel.squeeze(0).repeat(self.out_planes, 1, 1, 1)
        self.dep_conv.weight = nn.Parameter(data=kernel, requires_grad=True)
        self.dep_conv.bias = init_rate_0(self.dep_conv.bias)
 
    def forward(self, x):
        q, k, v = self.conv1(x), self.conv2(x), self.conv3(x)
        scaling = float(self.head_dim) ** -0.5
        b, c, h, w = q.shape
        h_out, w_out = h // self.stride, w // self.stride
 
        # ### att
        # ## positional encoding
        pe = self.conv_p(position(h, w, x.dtype, x.is_cuda))
 
        q_att = q.view(b * self.head, self.head_dim, h, w) * scaling
        k_att = k.view(b * self.head, self.head_dim, h, w)
        v_att = v.view(b * self.head, self.head_dim, h, w)
 
        if self.stride > 1:
            q_att = stride(q_att, self.stride)
            q_pe = stride(pe, self.stride)
        else:
            q_pe = pe
 
        unfold_k = self.unfold(self.pad_att(k_att)).view(b * self.head, self.head_dim,
                                                         self.kernel_att * self.kernel_att, h_out,
                                                         w_out)  # b*head, head_dim, k_att^2, h_out, w_out
        unfold_rpe = self.unfold(self.pad_att(pe)).view(1, self.head_dim, self.kernel_att * self.kernel_att, h_out,
                                                        w_out)  # 1, head_dim, k_att^2, h_out, w_out
 
        att = (q_att.unsqueeze(2) * (unfold_k + q_pe.unsqueeze(2) - unfold_rpe)).sum(
            1)  # (b*head, head_dim, 1, h_out, w_out) * (b*head, head_dim, k_att^2, h_out, w_out) -> (b*head, k_att^2, h_out, w_out)
        att = self.softmax(att)
 
        out_att = self.unfold(self.pad_att(v_att)).view(b * self.head, self.head_dim, self.kernel_att * self.kernel_att,
                                                        h_out, w_out)
        out_att = (att.unsqueeze(1) * out_att).sum(2).view(b, self.out_planes, h_out, w_out)
 
        ## conv
        f_all = self.fc(torch.cat(
            [q.view(b, self.head, self.head_dim, h * w), k.view(b, self.head, self.head_dim, h * w),
             v.view(b, self.head, self.head_dim, h * w)], 1))
        f_conv = f_all.permute(0, 2, 1, 3).reshape(x.shape[0], -1, x.shape[-2], x.shape[-1])
 
        out_conv = self.dep_conv(f_conv)
 
        return self.rate1 * out_att + self.rate2 * out_conv
 
def autopad(k, p=None, d=1):  # kernel, padding, dilation
    # Pad to 'same' shape outputs
    if d > 1:
        k = d * (k - 1) + 1 if isinstance(k, int) else [d * (x - 1) + 1 for x in k]  # actual kernel-size
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-pad
    return p
 
 
class Conv(nn.Module):
    # Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)
    default_act = nn.SiLU()  # default activation
 
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
        super().__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
        self.bn = nn.BatchNorm2d(c2)
        self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()
 
    def forward(self, x):
        return self.act(self.bn(self.conv(x)))
 
    def forward_fuse(self, x):
        return self.act(self.conv(x))
 
 
class Bottleneck(nn.Module):
    # Standard bottleneck
    def __init__(self, c1, c2, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, shortcut, groups, expansion
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c_, c2, 3, 1, g=g)
        self.Attention = ACmix(c2, 11)
        self.add = shortcut and c1 == c2
 
    def forward(self, x):
        return x + self.Attention(self.cv2(self.cv1(x))) if self.add else self.Attention(self.cv2(self.cv1(x)))
 
class C3_ACmix(nn.Module):
    # CSP Bottleneck with 3 convolutions
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, number, shortcut, groups, expansion
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(2 * c_, c2, 1)  # optional act=FReLU(c2)
        self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)))
 
    def forward(self, x):
        return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))
 
 
 
if __name__ == "__main__":
 
    # Generating Sample image
    image_size = (1, 24, 224, 224)
    image = torch.rand(*image_size)
 
    # Model
    mobilenet_v1 = ACmix(24, 24)
 
    out = mobilenet_v1(image)
    print(out)

二、添加ACmix注意力机制

2.1STEP1

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

2.2STEP2

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

2.3STEP3

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

2.4STEP4

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

在这里插入图片描述

三、yaml文件与运行

3.1yaml文件

以下是添加ACmix注意力机制在大目标检测层中的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 GFLOPs
  s: [0.50, 0.50, 1024] # summary: 319 layers, 9458752 parameters, 9458736 gradients, 21.7 GFLOPs
  m: [0.50, 1.00, 512] # summary: 409 layers, 20114688 parameters, 20114672 gradients, 68.5 GFLOPs
  l: [1.00, 1.00, 512] # summary: 631 layers, 25372160 parameters, 25372144 gradients, 87.6 GFLOPs
  x: [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, nn.Upsample, [None, 2, "nearest"]]
  - [[-1, 6], 1, Concat, [1]] # cat backbone P4
  - [-1, 2, C3k2, [512, False]] # 13

  - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  - [[-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)
  - [-1, 1, ACmix,[]]

  - [[16, 19, 23], 1, Detect, [nc]] # Detect(P3, P4, P5)

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

3.2运行成功截图

在这里插入图片描述

OK 以上就是添加ACmix注意力机制的全部过程了,后续将持续更新尽情期待,同时将针对这个模块进行二次开发改进,请大家实时关注

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2187868.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis: 集群测试和集群原理

集群测试 1 ) SET/GET 命令 测试 set 和 get 因为其他命令也基本相似,我们在 101 节点上尝试连接 103 $ /usr/local/redis/bin/redis-cli -c -a 123456 -h 192.168.10.103 -p 6376我们在插入或读取一个 key的时候,会对这个key做一个hash运算&#xff0c…

判断有向图是否为单连通图的算法

判断有向图是否为单连通图的算法 算法描述伪代码C语言实现解释在图论中,单连通图(singly connected graph)是指对于图中的任意两个顶点 m 和 v,如果存在从 m 到 v 的路径,则该路径是唯一的。为了判断一个有向图是否为单连通图,我们需要确保从任意顶点出发,到任意其他顶点…

开发能够抵御ICS对抗性攻击的边缘弹性机器学习集成

论文标题:《Development of an Edge Resilient ML Ensemble to Tolerate ICS Adversarial Attacks》 作者信息: Likai Yao, NSF Center for Cloud and Autonomic Computing, University of Arizona, Tucson, AZ 85721 USAQinxuan Shi, School of Elect…

【数据库差异研究】别名与表字段冲突,不同数据库在where中的处理行为

目录 ⚛️总结 ☪️1 问题描述 ☪️2 测试用例 ♋2.1 测试单层查询 ♏2.1.1 SQLITE数据库 ♐2.1.2 ORACLE数据库 ♑2.1.3 PG数据库 ♋2.2 测试嵌套查询 ♉2.2.1 SQLITE数据库 ♈2.2.2 ORACLE数据库 🔯2.2.3 PG数据库 ⚛️总结 单层查询 数据库类型别名…

字节终面问 Transformer,太难了。。。

最近已有不少大厂都在秋招宣讲了,也有一些在 Offer 发放阶段。 节前,我们邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对新手如何入门算法岗、该如何准备面试攻略、面试常考点、大模型技术趋势、算法项目落地经验分享等热门话题进行了…

厦门网站设计的用户体验优化策略

厦门网站设计的用户体验优化策略 在信息化快速发展的今天,网站作为企业与用户沟通的重要桥梁,用户体验(UX)的优化显得尤为重要。尤其是在交通便利、旅游资源丰富的厦门,吸引了大量企业进驻。在这样竞争激烈的环境中&am…

后端向页面传数据(内容管理系统)

一、登录 首先&#xff0c;做一个登录页面。 在这里&#xff0c;注意 内容框里的提示信息用placeholder <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthd…

基于J2EE技术的高校社团综合服务系统

目录 毕设制作流程功能和技术介绍系统实现截图开发核心技术介绍&#xff1a;使用说明开发步骤编译运行代码执行流程核心代码部分展示可行性分析软件测试详细视频演示源码获取 毕设制作流程 &#xff08;1&#xff09;与指导老师确定系统主要功能&#xff1b; &#xff08;2&am…

Visual Studio AI插件推荐

声明&#xff1a;个人喜好&#xff0c;仅供参考。 1、AI插件 Fitten Code&#xff08;免费&#xff09; Fitten Code 是由非十大模型驱动的AI编程助手&#xff0c;支持多种编程语言&#xff0c;支持主流几乎所有的IDE开发工具。包括VS Code、Visual Studio、JetBrains系列I…

Visual Studio 小技巧记录

1、将行距设置成1.15跟舒服一些。 2、括号进行颜色对比。 效果&#xff1a; 3、显示参数内联提示。 效果&#xff1a; 4、保存时规范化代码。 配置文件&#xff1a; 5、将滚动条修改为缩略图 效果&#xff1a;

MongoDB 数据库服务搭建(单机)

下载地址 下载测试数据 作者&#xff1a;程序那点事儿 日期&#xff1a;2023/02/15 02:16 进入下载页&#xff0c;选择版本后&#xff0c;右键Download复制连接地址 下载安装包 ​ wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-5.0.14.tgz​ …

开放式耳机哪个品牌好?好用且高性价比的开放式蓝牙耳机推荐

相信很多经常运动的朋友都不是很喜欢佩戴入耳式耳机&#xff0c;因为入耳式耳机真的有很多缺点。 安全方面&#xff1a;在安全上就很容易存在隐患&#xff0c;戴上后难以听到周围环境声音&#xff0c;像汽车鸣笛、行人呼喊等&#xff0c;容易在运动中发生意外。 健康方面&…

智慧管控平台技术解决方案

1. 智慧管控平台概述 智慧管控平台采用先进的AI技术&#xff0c;围绕一个中心和四大应用构建&#xff0c;旨在打造一个智能、共享、高效的智慧运营管理环境&#xff0c;实现绿色节能和业务创新。 2. 平台架构设计 系统整体架构设计包括统一门户管理、IOT平台、大数据、视频云…

螺蛳壳里做道场:老破机搭建的私人数据中心---Centos下docker学习02(yum源切换及docker安装配置)

2 前期工作 2.1 切换yum源并更新 删除/etc/yum.repos.d/原有repo文件&#xff0c;将Centos-7.repo库文件拷贝到该目录下。 然后清楚原有缓存yum clean all 生成新的缓存yum makecache 更新yum update –y 然后再确认/etc/yum.repos.d/不会有其他库文件&#xff0c;只留下…

第十四章 I/O系统

一、I/O系统的分类 1.输入流&#xff1a;程序从输入流读取数据 输出流&#xff1a;程序向输出流写入数据 2.字节流&#xff1a;数据流中的最小的数据单元是字节 字符流&#xff1a;数据流中的最小单元是字符 3.节点流、处理流 二、I/O系统的四个抽象类 1.Java中提供的流类…

MATLAB - 机械臂手眼标定(眼在手外) - 估算固定相机相对于机器人基座的姿态

系列文章目录 前言 在拾取和放置任务中&#xff0c;例如垃圾桶拾取&#xff0c;通常会在环境中的固定位置安装摄像头&#xff0c;以便机器人操纵器检测工作区中的物体。基本感知管道使用该摄像头来估计目标物体相对于摄像头坐标系的姿态。然后将该姿态转换到机器人的基准坐标系…

360浏览器时不时打不开csdn

从百度或者csdn的搜索中打开&#xff0c;会发现打不开网页&#xff0c;以前也出现过&#xff0c;只是以为这篇文章被删了&#xff0c;昨天接连多个文章打不开&#xff0c;怀疑的浏览器的问题&#xff0c;复制网址到edge浏览器就打开了 刚刚又出现了&#xff0c;怀疑360会拦截某…

探索TOGAF理论的实践应用:企业数字化转型的深度指南

数字化转型的迫切性与路径选择 随着全球化进程和技术革命的加速&#xff0c;企业正面临前所未有的挑战和机遇。数字化转型已成为企业保持竞争力、创新业务模式、优化客户体验的核心手段。然而&#xff0c;企业在实施数字化转型时&#xff0c;往往面临路径不清、技术与业务脱节…

高性能防静电主轴4033 AC-ESD 在线路板切割中的非凡表现

随着电子产品的日益小型化/集成化&#xff0c;线路板的制造也面临着更高的挑战。线路板分板作为电子制造流程中的关键环节&#xff0c;其效率和精度直接影响到最终产品的质量和市场竞争力。因此专用的高性能防静电主轴SycoTec 4033 AC-ESD凭借其卓越的性能&#xff0c;成为众多…

多系统萎缩患者必知的营养补充指南

亲爱的朋友们&#xff0c;今天我们要聊的是一个较为少见但影响深远的疾病——多系统萎缩&#xff08;Multiple System Atrophy, MSA&#xff09;。这是一种成年期发病的神经系统退行性疾病&#xff0c;给患者的日常生活带来了诸多不便。但别担心&#xff0c;通过合理的营养补充…