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

前言: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 Functionclass Covpool(Function):@staticmethoddef forward(ctx, input):x = inputbatchSize = x.data.shape[0]dim = x.data.shape[1]h = x.data.shape[2]w = x.data.shape[3]M = h*wx = 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@staticmethoddef backward(ctx, grad_output):input,I_hat = ctx.saved_tensorsx = inputbatchSize = x.data.shape[0]dim = x.data.shape[1]h = x.data.shape[2]w = x.data.shape[3]M = h*wx = 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_inputclass Sqrtm(Function):@staticmethoddef forward(ctx, input, iterN):x = inputbatchSize = x.data.shape[0]dim = x.data.shape[1]dtype = x.dtypeI3 = 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,:,:] = ZYfor 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 = iterNreturn y@staticmethoddef backward(ctx, grad_output, der_sacleTrace=None):input, A, ZY, normA, Y, Z = ctx.saved_tensorsiterN = ctx.iterNx = inputbatchSize = x.data.shape[0]dim = x.data.shape[1]dtype = x.dtypeder_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, Nonedef CovpoolLayer(var):return Covpool.apply(var)def SqrtmLayer(var, iterN):return Sqrtm.apply(var, iterN)class SOCA(nn.Module):# second-order Channel attentiondef __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: NxCxHxWN = int(h * w)min_h = min(h, w)h1 = 1000w1 = 1000if h < h1 and w < w1:x_sub = xelif h < h1 and w > w1:W = (w - w1) // 2x_sub = x[:, :, :, W:(W + w1)]elif w < w1 and h > h1:H = (h - h1) // 2x_sub = x[:, :, H:H + h1, :]else:H = (h - h1) // 2W = (w - w1) // 2x_sub = x[:, :, H:(H + h1), W:(W + w1)]cov_mat = CovpoolLayer(x_sub) # Global Covariance pooling layercov_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.hqwc.cn/news/83456.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

五、多表查询-5.自连接

一、语法 二、演示-自连接&#xff08;内连接&#xff09; 【例】查询员工 及其 所属领导的名字&#xff08;managerid&#xff0c;领导也是员工表emp1表中的数据&#xff09; &#xff01;&#xff01;必须起别名&#xff01;&#xff01; ——内连接只查询交集部分的数据 …

Linux操作系统--常用指令(用户管理操作类)

用户的管理需要使用超级管理员(root)来进行操作 (1).useradd添加新用户 功能:给当前的操作系统添加新的用户 语法: useradd 用户名 (2).passwd设置用户新密码 功能:给当前的用户设置密码 语法: passwd用户名 (3).i

探索AIGC人工智能(Midjourney篇)(一)

文章目录 案例图片 Midjourney注册 创建Discord账号 下载客户端 添加Midjourney到自己的服务器 用Midjourney画一只会飞的鸭子 Midjourney绘画指令 Midjourney绘画指令_激发Midjourney的创造力 Midjourney绘画指令_Seed指令 Midjourney光线关键词&#xff0c;打造震撼…

SPI2外设驱动-W25Q64 SPI接口初始化

前言 &#xff08;1&#xff09;本系列是基于STM32的项目笔记&#xff0c;内容涵盖了STM32各种外设的使用&#xff0c;由浅入深。 &#xff08;2&#xff09;小编使用的单片机是STM32F105RCT6&#xff0c;项目笔记基于小编的实际项目&#xff0c;但是博客中的内容适用于各种单片…

上传镜像到阿里云的ACR

1、开通阿里云ACR 2、在ACR 中创建命名空间 3、本地安装docker 4、登录到 开通ACR&#xff0c;需要配置访问凭证 [rootmaster ~]# docker login --username***lb registry.cn-beijing.aliyuncs.com Password: 5、给镜像打标签 [rootmaster ~]# docker images REPOSITORY …

leetcode496. 下一个更大元素 I 【单调栈】

【简单题】&#xff08;暴力遍历法很简单&#xff09;但是时间复杂度很高&#xff0c;n的立方级别了。。。 代码&#xff1a; class Solution { public:vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {vector<int&g…

【网络安全】防火墙知识点全面图解(三)

本系列文章包含&#xff1a; 【网络安全】防火墙知识点全面图解&#xff08;一&#xff09;【网络安全】防火墙知识点全面图解&#xff08;二&#xff09;【网络安全】防火墙知识点全面图解&#xff08;三&#xff09; 防火墙知识点全面图解&#xff08;三&#xff09; 39、什…

猜数游戏-Rust版

cargo new guessing_game 创建项目 输入任意内容&#xff0c;并打印出来 main.rs: use std::io; // 像String这些类型都在预先导入的prelude里&#xff0c;如果要使用的不在prelude里&#xff0c;则需要显式导入fn main() { println!("猜数"); println!("…

Rust常用加密算法

哈希运算(以Sha256为例) main.rs: use crypto::digest::Digest;use crypto::sha2::Sha256;fn main() { let input "dashen"; let mut sha Sha256::new(); sha.input_str(input); println!("{}", sha.result_str());} Cargo.toml: [package]n…

uniapp,使用canvas制作一个签名版

先看效果图 我把这个做成了页面&#xff0c;没有做成组件&#xff0c;因为之前我是配合uview-plus的popup弹出层使用的&#xff0c;这种组件好像是没有生命周期的&#xff0c;第一次打开弹出层可以正常写字&#xff0c;但是关闭之后再打开就不会显示绘制的线条了&#xff0c;还…

波奇学C++:stl的list模拟实现

list是双向带头链表。所以迭代器end()相当于哨兵卫的头。 list不支持和[]重载&#xff0c;原因在于list空间不是连续的&#xff0c;和[]的代价比较大。 访问第n个节点&#xff0c;只能用for循环&#xff0c;来实现 list<int> l; l.push_back(0); l.push_back(1); l.pu…

C++信息学奥赛1130:找第一个只出现一次的字符

这段代码的功能是找出输入字符串中第一个重复出现的字符&#xff0c;并输出该字符。 解析注释后的代码如下&#xff1a; #include<bits/stdc.h> using namespace std; int main() {string arr;getline(cin, arr); int a0;for(int i0;i<arr.length();i){for(int j0;j…