注意力机制添加方法

 

要将注意力机制模块添加到YoloV5工程项目中的yolo.py中,可参考以下四种情况。

以下4个elif代码来自https://yolov5.blog.csdn.net/article/details/129108082

elif m in [SimAM, ECA, SpatialGroupEnhance,TripletAttention]:args = [*args[:]]elif m in [CoordAtt, GAMAttention]:c1, c2 = ch[f], args[0]if c2 != no:c2 = make_divisible(c2 * gw, 8)args = [c1, c2, *args[1:]]elif m in [SE, ShuffleAttention, CBAM, SKAttention, DoubleAttention, CoTAttention, EffectiveSEModule,GlobalContext, GatherExcite, MHSA]:c1 = ch[f]args = [c1, *args[0:]]elif m in [S2Attention, NAMAttention, CrissCrossAttention, SequentialPolarizedSelfAttention,ParallelPolarizedSelfAttention, ParNetAttention]:c1 = ch[f]args = [c1]

 

根据这4种情况,我们在yaml文件中,填写args时(比如下图中RefConv的[1024,3,1]以及SE中的[1024]),需要填入的参数个数是不同的

# 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]],  #2[-1, 1, Conv, [256, 3, 2]],  # 3-P3/8[-1, 6, C3, [256]],  #4[-1, 1, Conv, [512, 3, 2]],  # 5-P4/16[-1, 9, C3, [512]],  #6[-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32[-1, 3, C3, [1024]],  # 8[-1,1,SE,[1024]],  #9[[-1, 1, SimAM, [1e-4]],  # 10[-1, 1, SPPF, [1024, 5]],  # 11[-1, 1, RefConv, [1024, 3, 1]],  # 12]

具体来说,是要将elif模块添加到yolo.py文件中的parse_model函数里。在编写elif模块代码时,我们需要关注的是,你的注意力机制模块代码(在common.py)中的__init__里面的参数,是否设置了“输入通道数”和“输出通道数”,这两个参数。

 

一、先上结论

情况1:_init_中不包含“输入通道数”和“输出通道数”,但含有其它参数

以下这些模块:SimAM,ECA,SpatialGroupEnhance,TripletAttention 全都满足情况1

elif m in [SimAM, ECA, SpatialGroupEnhance,TripletAttention]:args = [*args[:]]

以下是SimAM,ECA,SpatialGroupEnhance,TripletAttention 的__init__

class SimAM(torch.nn.Module):def __init__(self, e_lambda=1e-4):class ECA(nn.Module):def __init__(self, k_size=3):class SpatialAttention(nn.Module):def __init__(self, kernel_size=7):class SpatialGroupEnhance(nn.Module):def __init__(self, groups=8):class TripletAttention(nn.Module):def __init__(self, no_spatial=False):

这里解释一下args = [*args[:]]是什么意思

在Python中,*args 是一个特殊的语法,用于在函数定义中处理不确定数量的位置参数。args 是一个元组,包含了所有传递给函数的位置参数。

args[:] 是一个切片操作,它会创建一个 args 的浅拷贝。这意味着如果你修改了 args[:] 的内容,原始的 args 不会被改变。

[*args[:]] 则是将 args[:] 中的元素解包(unpack)成一个列表。这样做的目的通常是为了创建一个新的列表,而不是修改原始的 args。

例如:

args = [1, 2, 3, 4]
new_args = [*args[:]]
print(new_args) #输出为[1,2,3,4]

情况2:_init_中同时包含“输入通道数”和“输出通道数”,且含有其它参数

以下这些模块:CoordAtt, GAMAttention 全都满足情况2

elif m in [CoordAtt, GAMAttention]:c1, c2 = ch[f], args[0]if c2 != no:c2 = make_divisible(c2 * gw, 8)args = [c1, c2, *args[1:]]

以下是CoordAtt, GAMAttention 的__init__

class CoordAtt(nn.Module):def __init__(self, inp, oup, reduction=32):class GAMAttention(nn.Module):def __init__(self, c1, c2, group=True, rate=4):

情况3:_init_中只包含“输入通道数”,不包含“输出通道数”,且含有其它参数

以下这些模块:SE, ShuffleAttention, CBAM, SKAttention, DoubleAttention, CoTAttention, EffectiveSEModule,GlobalContext, GatherExcite, MHSA全都满足情况3

elif m in [SE, ShuffleAttention, CBAM, SKAttention, DoubleAttention, CoTAttention, EffectiveSEModule,GlobalContext, GatherExcite, MHSA]:c1 = ch[f]args = [c1, *args[0:]]

以下是SE, ShuffleAttention, CBAM, SKAttention, DoubleAttention, CoTAttention, EffectiveSEModule,GlobalContext, GatherExcite, MHSA的__init__

#SE机制它的输入通道和输出通道是一样的,所以在实现上可以只传入输入通道c1,但如果也给出输出通道c2的参数也是可以的。下面这两种都是在迪菲赫尔曼博客中实现过的SE模块
class SE(nn.Module):def __init__(self, c1, ratio=16):
class SE(nn.Module):def __init__(self, c1, c2, ratio=16):class ShuffleAttention(nn.Module):def __init__(self, channel=512, G=8):class CBAM(nn.Module):def __init__(self, c1, ratio=16, kernel_size=7):class SKAttention(nn.Module):def __init__(self, channel=512, kernels=[1, 3, 5, 7], reduction=16, group=1, L=32):class DoubleAttention(nn.Module):def __init__(self, in_channels, reconstruct=True):class CoTAttention(nn.Module):def __init__(self, dim=512, kernel_size=3):class EffectiveSEModule(nn.Module):def __init__(self, channels, add_maxpool=False, gate_layer='hard_sigmoid'):class GlobalContext(nn.Module):def __init__(self, channels, use_attn=True, fuse_add=False, fuse_scale=True, init_last_zero=False,rd_ratio=1. / 8, rd_channels=None, rd_divisor=1, act_layer=nn.ReLU, gate_layer='sigmoid'):
class GatherExcite(nn.Module):def __init__(self, channels, feat_size=None, extra_params=False, extent=0, use_mlp=True,rd_ratio=1. / 16, rd_channels=None, rd_divisor=1, add_maxpool=False,act_layer=nn.ReLU, norm_layer=nn.BatchNorm2d, gate_layer='sigmoid'):class MHSA(nn.Module):def __init__(self, n_dims, width=14, height=14, heads=4, pos_emb=False):    

情况4:_init_中只包含“输入通道数”,不包含“输出通道数”,且不含有其他参数(注意对比情况3)

以下这些模块:S2Attention, NAMAttention, CrissCrossAttention, SequentialPolarizedSelfAttention,ParallelPolarizedSelfAttention, ParNetAttention全都满足情况4

elif m in [S2Attention, NAMAttention, CrissCrossAttention, SequentialPolarizedSelfAttention,ParallelPolarizedSelfAttention, ParNetAttention]:c1 = ch[f]args = [c1]

以下是S2Attention, NAMAttention, CrissCrossAttention, SequentialPolarizedSelfAttention,ParallelPolarizedSelfAttention, ParNetAttention的__init__

class S2Attention(nn.Module):def __init__(self, channels=512):class NAMAttention(nn.Module):def __init__(self, channels):class CrissCrossAttention(nn.Module):def __init__(self, in_dim):class SequentialPolarizedSelfAttention(nn.Module):def __init__(self, channel=512):class ParallelPolarizedSelfAttention(nn.Module):def __init__(self, channel=512):class ParNetAttention(nn.Module):def __init__(self, channel=512):

 

二、解释代码

在理解代码前,我们需要知道,在parse_model函数中,args列表的前两个位置被设计为存放输入通道数(c1)和输出通道数(c2)。这是因为在创建这些模块时,我们通常会按照这个顺序传递参数。例如,对于nn.Conv2d,其构造函数的签名为Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True),其中in_channels和out_channels就对应于我们的c1和c2。因此,当我们在parse_model函数中创建这些模块时,我们需要先获取c1和c2,然后将它们放在args的前两个位置,以确保它们能被正确地传递给模块的构造函数。

情况1

'''
这段代码的目的是为了处理SimAM模块的参数。elif m in [SimAM]:
这行代码检查当前的模块m是否是SimAM模块。如果是,那么就执行下一行代码。args = [*args[:]]:
这行代码创建了args的一个浅拷贝。在Python中,args[:]会创建一个新的列表,这个新列表包含了args中的所有元素。*操作符会将这个新列表解包,然后我们再用[]将解包后的元素重新组装成一个新的列表。所以,[*args[:]]就等于args[:],它们都会创建args的一个浅拷贝。综上,这段代码使args列表保持不变,因为SimAM模块不需要修改输入和输出通道数。
'''elif m in [SimAM, ECA, SpatialGroupEnhance,TripletAttention]:args = [*args[:]]

 

情况2

'''
这段代码的目的是为了处理CoordAtt和GAMAttention模块的参数。elif m in [CoordAtt, GAMAttention]:
这行代码检查当前的模块m是否是CoordAtt模块或GAMAttention模块。如果是,那么就执行下面的代码。c1, c2 = ch[f], args[0]:
这行代码从ch和args两个列表中获取了两个值c1和c2。ch是一个列表,它保存了模型中每一层的输出通道数。f是一个索引,它指向ch中的某个元素,这个元素表示当前层的输入通道数。所以ch[f]就是当前层的输入通道数。args也是一个列表,它保存了当前层的参数。在模型配置文件中,每一层的参数都被保存在一个列表中,例如[64, 6, 2, 2]。这个列表的第一个元素通常是当前层的输出通道数。所以args[0]就是当前层的输出通道数。if c2 != no:
这行代码检查当前层的输出通道数c2是否不等于no。no是模型的总输出通道数。c2 = make_divisible(c2 * gw, 8):
如果c2不等于no,那么就重新计算c2的值。gw是模型的宽度倍数,make_divisible(c2 * gw, 8)会将c2 * gw调整为最接近的8的倍数。这是因为某些硬件(如GPU)在处理通道数为8的倍数的数据时,可以获得更好的性能。args = [c1, c2, *args[1:]]:
这行代码创建了一个新的参数列表args。新的args列表的第一个元素是c1,第二个元素是c2,剩下的元素是原始args列表的第二个元素及其后面的所有元素。*args[1:]是Python的解包(unpack)操作,它可以将列表args[1:]中的所有元素解包出来。所以,[c1, c2, *args[1:]]就等于[c1, c2]和args[1:]两个列表的连接。
'''elif m in [CoordAtt, GAMAttention]:c1, c2 = ch[f], args[0]if c2 != no:c2 = make_divisible(c2 * gw, 8)args = [c1, c2, *args[1:]] 

情况3

'''
这段代码的目的是为了处理SE, ShuffleAttention等模块的参数。elif m in [SE, ShuffleAttention, CBAM, SKAttention, DoubleAttention, CoTAttention, EffectiveSEModule,GlobalContext, GatherExcite, MHSA]:
这行代码检查当前的模块m是否是SE, ShuffleAttention等模块中的一个。如果是,那么就执行下面的代码。c1 = ch[f]:
这行代码从ch列表中获取了一个值c1。ch是一个列表,它保存了模型中每一层的输出通道数。f是一个索引,它指向ch中的某个元素,这个元素表示当前层的输入通道数。所以ch[f]就是当前层的输入通道数。args = [c1, *args[0:]]:
这行代码创建了一个新的参数列表args。新的args列表的第一个元素是c1,剩下的元素是原始args列表的第一个元素及其后面的所有元素。*args[0:]是Python的解包(unpack)操作,它可以将列表args[0:]中的所有元素解包出来。所以,[c1, *args[0:]]就等于[c1]和args[0:]两个列表的连接。综上,这段代码将当前层的输入通道数c1添加到参数列表args的开始位置,因为这些模块的初始化函数通常需要输入通道数作为第一个参数。'''elif m in [SE, ShuffleAttention, CBAM, SKAttention, DoubleAttention, CoTAttention, EffectiveSEModule,GlobalContext, GatherExcite, MHSA]:c1 = ch[f]args = [c1, *args[0:]]

 

情况4

'''
这段代码的目的是为了处理S2Attention, NAMAttention等模块的参数。elif m in [S2Attention, NAMAttention, CrissCrossAttention, SequentialPolarizedSelfAttention,ParallelPolarizedSelfAttention, ParNetAttention]:
这行代码检查当前的模块m是否是S2Attention, NAMAttention等模块中的一个。如果是,那么就执行下面的代码。c1 = ch[f]:
这行代码从ch列表中获取了一个值c1。ch是一个列表,它保存了模型中每一层的输出通道数。f是一个索引,它指向ch中的某个元素,这个元素表示当前层的输入通道数。所以ch[f]就是当前层的输入通道数。args = [c1]:这行代码创建了一个新的参数列表args。新的args列表只有一个元素,就是c1。综上,这段代码将当前层的输入通道数c1作为唯一的参数传递给这些模块,因为这些模块的初始化函数通常只需要输入通道数作为参数。
'''elif m in [S2Attention, NAMAttention, CrissCrossAttention, SequentialPolarizedSelfAttention,ParallelPolarizedSelfAttention, ParNetAttention]:c1 = ch[f]args = [c1]

 

 

 

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

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

相关文章

【1day】致远系统A6版本operaFileActionController.jsp接口任意文件读取漏洞学习

注:该文章来自作者日常学习笔记,请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与作者无关。 目录 一、漏洞描述 二、影响版本 三、资产测绘 四、漏洞复现

基于ResNet模型的908种超大规模中草药图像识别系统

中草药药材图像识别相关的实践在前文中已有对应的实践了,感兴趣的话可以自行移步阅读即可: 《python基于轻量级GhostNet模型开发构建23种常见中草药图像识别系统》 《基于轻量级MnasNet模型开发构建40种常见中草药图像识别系统》 在上一篇文章中&…

RocketMQ-RocketMQ高性能核心原理(流程图)

1.NamesrvStartup 2.BrokerStartup 3. DefualtMQProducer 4.DefaultMQPushConsumer

maven工程的pom.xml文件中增加了依赖,但偶尔没有下载到本地仓库

maven工程pom.xml文件中的个别依赖没有下载到本地maven仓库。以前没有遇到这种情况,今天就遇到了这个问题,把解决过程记录下来。 我在eclipse中编辑maven工程的pom.xml文件,增加对mybatis的依赖,但保存文件后,依赖的j…

Java--1v1双向通信-控制台版

文章目录 前言客户端服务器端输出线程端End 前言 TCP(Transmission Control Protocol)是一种面向连接的、可靠的网络传输协议,它提供了端到端的数据传输和可靠性保证。 本程序就是基于tcp协议编写而成的。 利用 TCP 协议进行通信的两个应用…

HarmonyOS(鸿蒙操作系统)与Android系统 各自特点 架构对比 各自优势

综合对比 HarmonyOS(鸿蒙操作系统)是由华为开发的操作系统,旨在跨多种设备和平台使用。HarmonyOS的架构与谷歌开发的广泛使用的Android操作系统有显著不同。以下是两者之间的一些主要比较点: 设计理念和使用案例: Harm…

go语言 grpc 拦截器

文章目录 拦截器服务端拦截器一元拦截器流拦截器 客户端拦截器一元拦截器流拦截 多个拦截器 代码仓库 拦截器 gRPC拦截器(interceptor)是一种函数,它可以在gRPC调用之前和之后执行一些逻辑,例如认证、授权、日志记录、监控和统计…

iOS app切换后台时添加模糊遮罩层

仿 支付宝 退出后台后,App整个 增加模糊遮罩层 此处只介绍 在iOS13后 SceneDelegate 下的操作 原理就是 在 App 进入后台后 在 主window上添加一个 UIVisualEffectView 在进入前台后移除 直接上代码: 先声明: //先声明 /* blurView */ property (strong, nonatomic) UI…

逆波兰表达式求解计算器

利用逆波兰表达式求解计算器有以下几个步骤: 1. 去掉字符串中的空格 s s.replaceAll(" ", "")2. 讲字符串转换为中序表达式数组 def string_to_infixlist(s):ans []keep_num ""for i in range(len(s)):if s[i].isdigit():if i < len(s)…

docker学习(四、修改容器创建新的镜像推送到云上)

镜像是只读的&#xff0c;容器是可编辑的。Docker镜像是分层的&#xff0c;支持通过扩展镜像&#xff0c;创建新的镜像。 学到这里感觉docker跟git很想~~ 通过docker commit将修改的容器做成新的镜像 # 将容器做成新的镜像 docker commit -m"提交备注" -a"作…

【1day】泛微e-office OA系统sms_page.php接口SQL 注入漏洞学习

注:该文章来自作者日常学习笔记,请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与作者无关。 目录 一、漏洞描述 二、影响版本 三、资产测绘 四、漏洞复现

大创项目推荐 交通目标检测-行人车辆检测流量计数 - 大创项目推荐

文章目录 0 前言1\. 目标检测概况1.1 什么是目标检测&#xff1f;1.2 发展阶段 2\. 行人检测2.1 行人检测简介2.2 行人检测技术难点2.3 行人检测实现效果2.4 关键代码-训练过程 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 毕业设计…

什么是Nginx反向代理?Nginx反向代理配置指南

Nginx反向代理是一种常见的服务器架构模式&#xff0c;它可以将客户端请求转发到多个后端服务器上&#xff0c;从而实现负载均衡、高可用性和安全性。本文将介绍Nginx反向代理的基本概念和配置方法。 什么是Nginx反向代理&#xff1f; 在传统的Web服务器架构中&#xff0c;客户…

解决selenium使用.get()报错:unknown error: unsupported protocol

解决方法 将原来的&#xff1a; url "https://www.baidu.com" browser.get(url)替换为&#xff1a; url "https://www.baidu.com" browser.execute_script(f"window.location.replace({url});") # 直接平替 .get()问题解析 之前运行都是正…

【后端学前端学习记录】学习计划

1、个人背景 写了足够久的后端了&#xff0c;常用的语言基本上都接触过&#xff0c;没有在工作中写过前端 一直想做一些前端的工作&#xff0c;但是前端技能不足加上自己审美不行&#xff0c;写出的界面总是很丑 所以一直对前端做不好&#xff0c;也没有真正下手。 2、动机 种…

Navicat 技术指引 | 连接 GaussDB 分布式

Navicat Premium&#xff08;16.3.3 Windows 版或以上&#xff09;正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结…

SLAM ORB-SLAM2(11)单目初始化

SLAM ORB-SLAM2(11)单目初始化 1. 初始化工作1.1. 单应矩阵(Homography Matrix)1.2. 基础矩阵(Fundamental Matrix)1.3. 本质矩阵(Essential Matrix)1.4. 初始化过程2. 业务流程2.1. 创建单目初始化器2.2. 判断连续帧的特征点数目2.3. 在两帧中找匹配的特征点对2.4. 估…

软件兼容性测试:保障多样化用户体验的重要功能

随着移动设备和操作系统的快速发展&#xff0c;软件兼容性测试变得越发重要。这项测试确保软件在不同平台、设备和环境下都能够正常运行&#xff0c;提供一致而稳定的用户体验。下面是软件兼容性测试中的一些关键功能&#xff1a; 1. 跨平台兼容性测试 在不同操作系统上运行的软…

【flink番外篇】1、flink的23种常用算子介绍及详细示例(3)-window、distinct、join等

Flink 系列文章 一、Flink 专栏 Flink 专栏系统介绍某一知识点&#xff0c;并辅以具体的示例进行说明。 1、Flink 部署系列 本部分介绍Flink的部署、配置相关基础内容。 2、Flink基础系列 本部分介绍Flink 的基础部分&#xff0c;比如术语、架构、编程模型、编程指南、基本的…

macOS Big Sur/Mac电脑安装vscode显示您没有权限来打开应用程序‘Visual Studio Code‘ 请联系您的电脑或网络管理员问题修复

错误方法 首先我以为我的权限不足。&#xff0c;需要去用户群组里设置。结果根本不是这个的问题。 1.在系统偏好设置->用户与群组检查了一下我的用户是不是管理员 结果发现是管理员 2.根据苹果提示&#xff0c;右键我的文件夹->显示简介->最下面的共享与权限 解锁&…