YOLOv5算法改进(6)— 添加SOCA注意力机制

news2025/1/16 14:09:20

前言:Hello大家好,我是小哥谈。SOCA(self-organizing competitive attention)是一种注意力机制,它模拟了人类视觉系统中的竞争性注意力机制。在视觉场景中,我们通常只关注某些特定的区域,而忽略其他无关的信息。SOCA的目标就是通过自组织竞争的方式,选择出最具有显著性的特征并进行处理。SOCA的实现思路是将输入特征分成多个子特征,并为每个子特征分配一个竞争机制。这些竞争机制可以通过计算竞争得分来决定哪些特征更具有显著性。竞争得分高的特征将被保留下来,而竞争得分低的特征则会被抑制或忽略。🌈 

前期回顾:

           YOLOv5算法改进(1)— 如何去改进YOLOv5算法

           YOLOv5算法改进(2)— 添加SE注意力机制

           YOLOv5算法改进(3)— 添加CBAM注意力机制

           YOLOv5算法改进(4)— 添加CA注意力机制

           YOLOv5算法改进(5)— 添加ECA注意力机制 

           目录

🚀1.论文

🚀2.SAN网络

🚀3.添加SOCA注意力机制的方法

💥💥步骤1:在common.py中添加SOCA模块

​💥💥步骤2:在yolo.py文件中加入类名

​💥💥步骤3:创建自定义yaml文件

​💥💥步骤4:修改yolov5s_SOCA.yaml文件

​💥💥步骤5:验证是否加入成功 

💥💥步骤6:修改train.py中的'--cfg'默认参数

🚀4.在C3后面添加SOCA注意力机制的方法

💥💥步骤1:修改yaml文件

💥💥步骤2:验证是否加入成功

🚀1.论文

近年来,深度卷积神经网络(CNN)在单图像超分辨率(SISR)中得到了广泛的研究,并取得了显著的性能。然而,大多数现有的基于CNN的 SISR 方法主要侧重于更广泛或者更深入的架构设计,而忽略了中间层的特征相关性,因此阻碍了CNN的代表能力。基于此,本文提出了二阶注意力机制(SOCA)更好的学习特征之间的联系,此模块通过利用二阶特征的分布自适应的学习特征的内部依赖关系,使网络能够专注于更有益的信息且能够提高判别学习的能力。此外,本文提出了一种非局部加强残差组结构能够进一步结合非局部操作来提取长程的空间上下文信息。🌴

总体上该论文贡献主要有以下三点:

(1)提出了用于图像超分辨的深度二阶注意力网络。

(2)提出了二阶注意力机制通过利用高阶的特征自适应的调整特征,另外利用了协方差归一化的方法来加速网络的训练。

(3)提出了非局部加强残差组NLRG结构构建网络,进一步结合非局部操作来提取空间上的上下文信息,并共享残差结构来学习深度特征,另外通过跳跃链接来过滤低频信息且简化了深层网络的训练。

论文题目:《Second-order Attention Network for Single Image Super-Resolution》

论文地址:  Second-order Attention Network for Single Image Super-Resolution

代码实现:   https://github.com/daitao/SAN

🚀2.SAN网络

由下图中可以看出,SAN网络主要由四部分组成:

(1)浅层特征提取(shallow feature extraction)即第一个卷积

(2)非局部增强残差组(NLRG)提取深度特征(deep feature,DF)

(3)上采样模块(upscale module)

(4)重建模块(reconstruction part)即最后一个卷积


🚀3.添加SOCA注意力机制的方法

💥💥步骤1:在common.py中添加SOCA模块

将下面的SOCA模块的代码复制粘贴到common.py文件的末尾。

# SOCA moudle 单幅图像超分辨率
from torch.autograd import Function
 
class Covpool(Function):
     @staticmethod
     def forward(ctx, input):
         x = input
         batchSize = x.data.shape[0]
         dim = x.data.shape[1]
         h = x.data.shape[2]
         w = x.data.shape[3]
         M = h*w
         x = x.reshape(batchSize,dim,M)
         I_hat = (-1./M/M)*torch.ones(M,M,device = x.device) + (1./M)*torch.eye(M,M,device = x.device)
         I_hat = I_hat.view(1,M,M).repeat(batchSize,1,1).type(x.dtype)
         y = x.bmm(I_hat).bmm(x.transpose(1,2))
         ctx.save_for_backward(input,I_hat)
         return y
     @staticmethod
     def backward(ctx, grad_output):
         input,I_hat = ctx.saved_tensors
         x = input
         batchSize = x.data.shape[0]
         dim = x.data.shape[1]
         h = x.data.shape[2]
         w = x.data.shape[3]
         M = h*w
         x = x.reshape(batchSize,dim,M)
         grad_input = grad_output + grad_output.transpose(1,2)
         grad_input = grad_input.bmm(x).bmm(I_hat)
         grad_input = grad_input.reshape(batchSize,dim,h,w)
         return grad_input
 
class Sqrtm(Function):
     @staticmethod
     def forward(ctx, input, iterN):
         x = input
         batchSize = x.data.shape[0]
         dim = x.data.shape[1]
         dtype = x.dtype
         I3 = 3.0*torch.eye(dim,dim,device = x.device).view(1, dim, dim).repeat(batchSize,1,1).type(dtype)
         normA = (1.0/3.0)*x.mul(I3).sum(dim=1).sum(dim=1)
         A = x.div(normA.view(batchSize,1,1).expand_as(x))
         Y = torch.zeros(batchSize, iterN, dim, dim, requires_grad = False, device = x.device)
         Z = torch.eye(dim,dim,device = x.device).view(1,dim,dim).repeat(batchSize,iterN,1,1)
         if iterN < 2:
            ZY = 0.5*(I3 - A)
            Y[:,0,:,:] = A.bmm(ZY)
         else:
            ZY = 0.5*(I3 - A)
            Y[:,0,:,:] = A.bmm(ZY)
            Z[:,0,:,:] = ZY
            for i in range(1, iterN-1):
               ZY = 0.5*(I3 - Z[:,i-1,:,:].bmm(Y[:,i-1,:,:]))
               Y[:,i,:,:] = Y[:,i-1,:,:].bmm(ZY)
               Z[:,i,:,:] = ZY.bmm(Z[:,i-1,:,:])
            ZY = 0.5*Y[:,iterN-2,:,:].bmm(I3 - Z[:,iterN-2,:,:].bmm(Y[:,iterN-2,:,:]))
         y = ZY*torch.sqrt(normA).view(batchSize, 1, 1).expand_as(x)
         ctx.save_for_backward(input, A, ZY, normA, Y, Z)
         ctx.iterN = iterN
         return y
     @staticmethod
     def backward(ctx, grad_output, der_sacleTrace=None):
         input, A, ZY, normA, Y, Z = ctx.saved_tensors
         iterN = ctx.iterN
         x = input
         batchSize = x.data.shape[0]
         dim = x.data.shape[1]
         dtype = x.dtype
         der_postCom = grad_output*torch.sqrt(normA).view(batchSize, 1, 1).expand_as(x)
         der_postComAux = (grad_output*ZY).sum(dim=1).sum(dim=1).div(2*torch.sqrt(normA))
         I3 = 3.0*torch.eye(dim,dim,device = x.device).view(1, dim, dim).repeat(batchSize,1,1).type(dtype)
         if iterN < 2:
            der_NSiter = 0.5*(der_postCom.bmm(I3 - A) - A.bmm(der_sacleTrace))
         else:
            dldY = 0.5*(der_postCom.bmm(I3 - Y[:,iterN-2,:,:].bmm(Z[:,iterN-2,:,:])) -
                          Z[:,iterN-2,:,:].bmm(Y[:,iterN-2,:,:]).bmm(der_postCom))
            dldZ = -0.5*Y[:,iterN-2,:,:].bmm(der_postCom).bmm(Y[:,iterN-2,:,:])
            for i in range(iterN-3, -1, -1):
               YZ = I3 - Y[:,i,:,:].bmm(Z[:,i,:,:])
               ZY = Z[:,i,:,:].bmm(Y[:,i,:,:])
               dldY_ = 0.5*(dldY.bmm(YZ) -
                         Z[:,i,:,:].bmm(dldZ).bmm(Z[:,i,:,:]) -
                             ZY.bmm(dldY))
               dldZ_ = 0.5*(YZ.bmm(dldZ) -
                         Y[:,i,:,:].bmm(dldY).bmm(Y[:,i,:,:]) -
                            dldZ.bmm(ZY))
               dldY = dldY_
               dldZ = dldZ_
            der_NSiter = 0.5*(dldY.bmm(I3 - A) - dldZ - A.bmm(dldY))
         grad_input = der_NSiter.div(normA.view(batchSize,1,1).expand_as(x))
         grad_aux = der_NSiter.mul(x).sum(dim=1).sum(dim=1)
         for i in range(batchSize):
             grad_input[i,:,:] += (der_postComAux[i] \
                                   - grad_aux[i] / (normA[i] * normA[i])) \
                                   *torch.ones(dim,device = x.device).diag()
         return grad_input, None
 
def CovpoolLayer(var):
    return Covpool.apply(var)
 
def SqrtmLayer(var, iterN):
    return Sqrtm.apply(var, iterN)
 
class SOCA(nn.Module):
    # second-order Channel attention
    def __init__(self, channel, reduction=8):
        super(SOCA, self).__init__()
        self.max_pool = nn.MaxPool2d(kernel_size=2)
 
        self.conv_du = nn.Sequential(
            nn.Conv2d(channel, channel // reduction, 1, padding=0, bias=True),
            nn.ReLU(inplace=True),
            nn.Conv2d(channel // reduction, channel, 1, padding=0, bias=True),
            nn.Sigmoid()
        )
 
    def forward(self, x):
        batch_size, C, h, w = x.shape  # x: NxCxHxW
        N = int(h * w)
        min_h = min(h, w)
        h1 = 1000
        w1 = 1000
        if h < h1 and w < w1:
            x_sub = x
        elif h < h1 and w > w1:
            W = (w - w1) // 2
            x_sub = x[:, :, :, W:(W + w1)]
        elif w < w1 and h > h1:
            H = (h - h1) // 2
            x_sub = x[:, :, H:H + h1, :]
        else:
            H = (h - h1) // 2
            W = (w - w1) // 2
            x_sub = x[:, :, H:(H + h1), W:(W + w1)]
        cov_mat = CovpoolLayer(x_sub) # Global Covariance pooling layer
        cov_mat_sqrt = SqrtmLayer(cov_mat,5) # Matrix square root layer( including pre-norm,Newton-Schulz iter. and post-com. with 5 iteration)
        cov_mat_sum = torch.mean(cov_mat_sqrt,1)
        cov_mat_sum = cov_mat_sum.view(batch_size,C,1,1)
        y_cov = self.conv_du(cov_mat_sum)
        return y_cov*x
具体如下图所示:

​💥💥步骤2:在yolo.py文件中加入类名

首先在yolo.py文件中找到parse_model函数,然后将 SOCA 添加到这个注册表里。

​💥💥步骤3:创建自定义yaml文件

models文件夹中复制yolov5s.yaml,粘贴并命名为yolov5s_SOCA.yaml

​💥💥步骤4:修改yolov5s_SOCA.yaml文件

本步骤是修改yolov5s_SOCA.yaml,将SOCA模块添加到我们想添加的位置。

这里我先介绍第一种,第一种是将SOCA模块放在Backbone部分的最末端,这样可以使注意力机制看到整个Backbone部分的特征图,将具有全局视野,类似一个小transformer结构

在这里,我将[-1,1,SOCA,[1024]]添加到SPPF的下一层,即下图中所示位置。👇

同样的,下面的head也要修改。原本Detect指定的是[17,20,23]层,所以,我们在添加了SOCA模块之后,也要对这里进行修改,即原来的17层,变成18层,原来的20层,变成21层,原来的23层,变成24层;所以这里需要改为[18,21,24]。同样的,Concat的系数也要修改,这样才能保持原来的网络结构不会发生特别大的改变,这里我们把后面两个Concat的系数分别由[-1,14][-1,10]改为[-1,15][-1,11]🌻

具体如下图所示:

​💥💥步骤5:验证是否加入成功 

yolo.py文件里,将配置改为我们刚才自定义的yolov5s_SOCA.yaml

​ 然后运行yolo.py,得到结果。

​找到了SOCA模块,说明我们添加成功了。🎉🎉🎉 

💥💥步骤6:修改train.py中的'--cfg'默认参数

train.py文件中找到 parse_opt函数,然后将第二行'--cfg'的default改为 'models/yolov5s_SOCA.yaml',然后就可以开始进行训练了。🎈🎈🎈


🚀4.在C3后面添加SOCA注意力机制的方法

第二种是将SOCA放在Backbone部分每个C3模块的后面,这样可以使注意力机制看到局部的特征,每层进行一次注意力,可以分担学习压力。

步骤和方法1相同,区别在于yaml文件不同,所以只需修改yaml文件即可。

💥💥步骤1:修改yaml文件

将SOCA模块放在每个C3模块的后面,要注意通道的变化。

具体如下图所示:

​同样的,下面的head也要做同样的修改。

​第二种方法yaml文件的完整代码:

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license

# Parameters
nc: 80  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple
anchors:
  - [10,13, 16,30, 33,23]  # P3/8
  - [30,61, 62,45, 59,119]  # P4/16
  - [116,90, 156,198, 373,326]  # P5/32

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 3, SOCA, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 3, SOCA, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 3, SOCA, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 3, SOCA, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
  ]

# YOLOv5 v6.0 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 9], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3, [512, False]],  # 13

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, C3, [256, False]],  # 17 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 18], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 20 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 23 (P5/32-large)

   [[21, 24, 27], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

💥💥步骤2:验证是否加入成功

运行yolo.py,具体结果如下所示:

​由上图可知,我们添加成功了!🎉🎉🎉


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

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

相关文章

浏览器开发者工具平台js代码开启展开收起

1、如下js左侧可以展开和收起段落&#xff0c;需要打开右上角的设置 2、Preferences这里勾选Code folding 即可像上面那张图展开和收起js段落代码 3、然后重新打开开发者工具&#xff0c;随意打开一个js文件&#xff0c;这里就有缩放了

5G R17R18技术解读

欢迎关注微信公众号“我想我思”

Hystrix: Dashboard流监控

接上两张服务熔断 开始搭建Dashboard流监控 pom依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocat…

codeforce 894

A. Gift Carpet &#xff08;模拟&#xff09; 题意&#xff1a; 给出n*m的矩阵&#xff0c;从左到右每列最多取一个字母&#xff0c;问能否取出"vika" 思路&#xff1a; 直接模拟。 const int N1e610; char g[25][25]; void solve(){int n,m; cin>>n>>…

Vue2向Vue3过度核心技术路由

目录 1 路由介绍1.思考2.路由的介绍3.总结 2 路由的基本使用1.目标2.作用3.说明4.官网5.VueRouter的使用&#xff08;52&#xff09;6.代码示例7.两个核心步骤8.总结 3 组件的存放目录问题1.组件分类2.存放目录3.总结 4 路由的封装抽离5 Vue路由-重定向1.问题2.解决方案3.语法4…

openGauss学习笔记-51 openGauss 高级特性-列存储

文章目录 openGauss学习笔记-51 openGauss 高级特性-列存储51.1 语法格式51.2 参数说明51.3 示例 openGauss学习笔记-51 openGauss 高级特性-列存储 openGauss支持行列混合存储。行存储是指将表按行存储到硬盘分区上&#xff0c;列存储是指将表按列存储到硬盘分区上。 行、列…

最新本地大模型进展#Chinese-LLaMA-2支持16k长上下文

‍‍ Hi&#xff0c;今天为大家介绍最新的本地中文语言模型进展。 [2023/08/25] Chinese-LLaMA-2发布了新的更新&#xff1a; 长上下文模型Chinese-LLaMA-2-7B-16K和Chinese-LLaMA-2-13B-16K&#xff0c;支持16K上下文&#xff0c;并可通过NTK方法进一步扩展至24K。 这意味着在…

Lazada商品详情接口 获取Lazada商品详情数据 Lazada商品价格接

一、引言 随着电子商务的迅速发展和普及&#xff0c;电商平台之间的竞争也日趋激烈。为了提供更好的用户体验和更高效的后端管理&#xff0c;Lazada作为东南亚最大的电商平台之一&#xff0c;开发了一种商品详情接口&#xff08;Product Detail API&#xff09;。该接口允许第…

【附安装包】Vred2023安装教程

软件下载 软件&#xff1a;Vred版本&#xff1a;2023语言&#xff1a;简体中文大小&#xff1a;2.39G安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.0GHz 内存4G(或更高&#xff09;下载通道①百度网盘丨64位下载链接&#xff1a;https://pan.baidu.com…

Leetcode78. 子集

给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 回溯法 class Solution {public List<List<Integer>> subsets(int[] nums) {List…

记录帖子-开发过程中遇到的问题和感悟记录

记录帖子1:2023年08月25日结束开发 前端规范 1.关于计算属性 计算属性关联的变量不可以过多&#xff0c;同时要保证关联的变量在代码中的变换次数不可过多 例如这段代码的this.options内部数据变化过多&#xff0c;导致计算属性调用次数过多导致页面卡顿 2.关于自定义v-mod…

空时自适应处理用于机载雷达——机载阵列雷达信号环境(Matla代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【【萌新的STM32学习-17 中断的基本概念2】】

萌新的STM32学习-17 中断的基本概念2 STM32中断优先级的基本概念 抢占优先级&#xff1a; 高抢占优先级可以打断正在执行的低抢占优先级中断 响应优先级&#xff1a; 这个也叫子优先级 抢占优先级相同&#xff0c;响应优先级高的中断不能打断响应优先级低的中断。还有一种情况…

Linux常用命令——dhclient命令

在线Linux命令查询工具 dhclient 动态获取或释放IP地址 补充说明 dhclient命令使用动态主机配置协议动态的配置网络接口的网络参数。 语法 dhclient(选项)(参数)选项 0&#xff1a;指定dhcp客户端监听的端口号&#xff1b; -d&#xff1a;总是以前台方式运行程序&#x…

TCP拥塞控制详解 | 7. 超越TCP

网络传输问题本质上是对网络资源的共享和复用问题&#xff0c;因此拥塞控制是网络工程领域的核心问题之一&#xff0c;并且随着互联网和数据中心流量的爆炸式增长&#xff0c;相关算法和机制出现了很多创新&#xff0c;本系列是免费电子书《TCP Congestion Control: A Systems …

【附安装包】Jade 6.5​安装教程

软件下载 软件&#xff1a;Jade版本&#xff1a;6.5语言&#xff1a;英文大小&#xff1a;185.95M安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.0GHz 内存4G(或更高&#xff09;下载通道①百度网盘丨下载链接&#xff1a;https://pan.baidu.com/s/1kbD…

配置Linux内核支持make menuconfig

新环境从0配置Linux内核支持make menuconfig hudahuahudahua-virtual-machine:~/workspace/tools/linux-5.15.13$ make menuconfigCommand ‘make’ not found, but can be installed with sudo apt install make # version 4.2.1-1.2, or sudo apt install make-guile # vers…

开始MySQL之路——MySQL的DataGrip图形化界面

下载DataGrip 下载地址&#xff1a;Download DataGrip: Cross-Platform IDE for Databases & SQL 安装DataGrip 准备好一个文件夹&#xff0c;不要中文和空格 C:\Develop\DataGrip 激活DataGrip 激活码&#xff1a; VPQ9LWBJ0Z-eyJsaWNlbnNlSWQiOiJWUFE5TFdCSjBaIiwibGl…

乐高虚拟搭建软件Studio 2.0怎么导入缺少的零件库文件

Studio 2.0是目前非常流行的乐高虚拟拼搭软件&#xff0c;功能也很强大。我们在利用Studio 2.0进行虚拟拼搭的时候&#xff0c;经常会遇到软件自带的零件库不全的问题。像一些电机、线性执行器、传感器等比较稀有的零件&#xff0c;在软件自带的零件库里是没有的。 导入方法&a…

【Go 基础篇】Go语言日期与时间函数详解:时间的掌控与转化

Go语言是一种快速、简洁且高效的编程语言&#xff0c;它在处理日期与时间方面提供了丰富的标准库函数。本文将详细介绍Go语言中处理日期与时间的函数&#xff0c;涵盖常用的日期时间操作、格式化、时区转换等内容&#xff0c;并介绍time.Time结构体中的相关方法。 时间的表示与…