爆改YOLOv8|利用SCConv改进yolov8-即轻量又涨点

1,本文介绍

SCConv(空间和通道重构卷积)是一种高效的卷积模块,旨在优化卷积神经网络(CNN)的性能,通过减少空间和通道的冗余来降低计算资源的消耗。该模块由两个核心组件构成:

  1. 空间重构单元(SRU):通过分离和重构的方式,SRU 有效减少空间冗余。

  2. 通道重构单元(CRU):利用分割-变换-融合策略,CRU 旨在降低通道冗余

关于SCConv的详细介绍可以看论文:SCConv: Spatial and Channel Reconstruction Convolution for Feature Redundancy (thecvf.com)

本文将讲解如何将SCConv融合进yolov8

话不多说,上代码!

2, 将SCConv融合进yolov8

2.1 步骤一

找到如下的目录'ultralytics/nn/modules',然后在这个目录下创建一个SCConv.py文件,文件名字可以根据你自己的习惯起,然后将SCConv的核心代码复制进去.

import torch
import torch.nn.functional as F
import torch.nn as nn
from .conv import Conv__all__ = ['C2f_SCConv']class GroupBatchnorm2d(nn.Module):def __init__(self, c_num: int,group_num: int = 16,eps: float = 1e-10):super(GroupBatchnorm2d, self).__init__()assert c_num >= group_numself.group_num = group_numself.weight = nn.Parameter(torch.randn(c_num, 1, 1))self.bias = nn.Parameter(torch.zeros(c_num, 1, 1))self.eps = epsdef forward(self, x):N, C, H, W = x.size()x = x.view(N, self.group_num, -1)mean = x.mean(dim=2, keepdim=True)std = x.std(dim=2, keepdim=True)x = (x - mean) / (std + self.eps)x = x.view(N, C, H, W)return x * self.weight + self.biasclass SRU(nn.Module):def __init__(self,oup_channels: int,group_num: int = 16,gate_treshold: float = 0.5,torch_gn: bool = True):super().__init__()self.gn = nn.GroupNorm(num_channels=oup_channels, num_groups=group_num) if torch_gn else GroupBatchnorm2d(c_num=oup_channels, group_num=group_num)self.gate_treshold = gate_tresholdself.sigomid = nn.Sigmoid()def forward(self, x):gn_x = self.gn(x)w_gamma = self.gn.weight / sum(self.gn.weight)w_gamma = w_gamma.view(1, -1, 1, 1)reweigts = self.sigomid(gn_x * w_gamma)# Gatew1 = torch.where(reweigts > self.gate_treshold, torch.ones_like(reweigts), reweigts)  # 大于门限值的设为1,否则保留原值w2 = torch.where(reweigts > self.gate_treshold, torch.zeros_like(reweigts), reweigts)  # 大于门限值的设为0,否则保留原值x_1 = w1 * xx_2 = w2 * xy = self.reconstruct(x_1, x_2)return ydef reconstruct(self, x_1, x_2):x_11, x_12 = torch.split(x_1, x_1.size(1) // 2, dim=1)x_21, x_22 = torch.split(x_2, x_2.size(1) // 2, dim=1)return torch.cat([x_11 + x_22, x_12 + x_21], dim=1)class CRU(nn.Module):'''alpha: 0<alpha<1'''def __init__(self,op_channel: int,alpha: float = 1 / 2,squeeze_radio: int = 2,group_size: int = 2,group_kernel_size: int = 3,):super().__init__()self.up_channel = up_channel = int(alpha * op_channel)self.low_channel = low_channel = op_channel - up_channelself.squeeze1 = nn.Conv2d(up_channel, up_channel // squeeze_radio, kernel_size=1, bias=False)self.squeeze2 = nn.Conv2d(low_channel, low_channel // squeeze_radio, kernel_size=1, bias=False)# upself.GWC = nn.Conv2d(up_channel // squeeze_radio, op_channel, kernel_size=group_kernel_size, stride=1,padding=group_kernel_size // 2, groups=group_size)self.PWC1 = nn.Conv2d(up_channel // squeeze_radio, op_channel, kernel_size=1, bias=False)# lowself.PWC2 = nn.Conv2d(low_channel // squeeze_radio, op_channel - low_channel // squeeze_radio, kernel_size=1,bias=False)self.advavg = nn.AdaptiveAvgPool2d(1)def forward(self, x):# Splitup, low = torch.split(x, [self.up_channel, self.low_channel], dim=1)up, low = self.squeeze1(up), self.squeeze2(low)# TransformY1 = self.GWC(up) + self.PWC1(up)Y2 = torch.cat([self.PWC2(low), low], dim=1)# Fuseout = torch.cat([Y1, Y2], dim=1)out = F.softmax(self.advavg(out), dim=1) * outout1, out2 = torch.split(out, out.size(1) // 2, dim=1)return out1 + out2class ScConv(nn.Module):def __init__(self,op_channel: int,group_num: int = 4,gate_treshold: float = 0.5,alpha: float = 1 / 2,squeeze_radio: int = 2,group_size: int = 2,group_kernel_size: int = 3,):super().__init__()self.SRU = SRU(op_channel,group_num=group_num,gate_treshold=gate_treshold)self.CRU = CRU(op_channel,alpha=alpha,squeeze_radio=squeeze_radio,group_size=group_size,group_kernel_size=group_kernel_size)def forward(self, x):x = self.SRU(x)x = self.CRU(x)return x
class SCConv_yolov8(nn.Module):def __init__(self, in_channels, out_channels, kernel_size=1, stride=1, g=1, dilation=1):super().__init__()self.conv = Conv(in_channels, out_channels, k=1)self.RFAConv = ScConv(out_channels)self.bn = nn.BatchNorm2d(out_channels)self.gelu = nn.GELU()def forward(self, x):x = self.conv(x)x = self.RFAConv(x)x = self.gelu(self.bn(x))return xclass Bottleneck_SCConv(nn.Module):"""Standard bottleneck."""def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5):"""Initializes a bottleneck module with given input/output channels, shortcut option, group, kernels, andexpansion."""super().__init__()c_ = int(c2 * e)  # hidden channelsself.cv1 = Conv(c1, c_, k[0], 1)self.cv2 = SCConv_yolov8(c_, c2, k[1], 1, g=g)self.add = shortcut and c1 == c2def forward(self, x):"""'forward()' applies the YOLO FPN to input data."""return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))class C2f_SCConv(nn.Module):"""Faster Implementation of CSP Bottleneck with 2 convolutions."""def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):"""Initialize CSP bottleneck layer with two convolutions with arguments ch_in, ch_out, number, shortcut, groups,expansion."""super().__init__()self.c = int(c2 * e)  # hidden channelsself.cv1 = Conv(c1, 2 * self.c, 1, 1)self.cv2 = Conv((2 + n) * self.c, c2, 1)  # optional act=FReLU(c2)self.m = nn.ModuleList(Bottleneck_SCConv(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))def forward(self, x):"""Forward pass through C2f layer."""x = self.cv1(x)x = x.chunk(2, 1)y = list(x)# y = list(self.cv1(x).chunk(2, 1))y.extend(m(y[-1]) for m in self.m)return self.cv2(torch.cat(y, 1))def forward_split(self, x):"""Forward pass using split() instead of chunk()."""y = list(self.cv1(x).split((self.c, self.c), 1))y.extend(m(y[-1]) for m in self.m)return self.cv2(torch.cat(y, 1))

2.2 步骤二

在task.py导入我们的模块

from .modules.SCConv import C2f_SCConv

2.3 步骤三

在task.py的parse_model方法里面注册我们的模块

这里需要注意在两个位置进行添加,不要漏了

到此注册成功,复制后面的yaml文件直接运行即可

yaml文件

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 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=yolov8n.yaml' will call yolov8.yaml with scale 'n'# [depth, width, max_channels]n: [0.33, 0.25, 1024]  # YOLOv8n summary: 225 layers,  3157200 parameters,  3157184 gradients,   8.9 GFLOPss: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPsm: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPsl: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPsx: [1.00, 1.25, 512]   # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs# YOLOv8.0n 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, 3, C2f, [128, True]]- [-1, 1, Conv, [256, 3, 2]]  # 3-P3/8- [-1, 6, C2f, [256, True]]- [-1, 1, Conv, [512, 3, 2]]  # 5-P4/16- [-1, 6, C2f, [512, True]]- [-1, 1, Conv, [1024, 3, 2]]  # 7-P5/32- [-1, 3, C2f, [1024, True]]- [-1, 1, SPPF, [1024, 5]]  # 9# YOLOv8.0n head
head:- [-1, 1, nn.Upsample, [None, 2, 'nearest']]- [[-1, 6], 1, Concat, [1]]  # cat backbone P4- [-1, 3, C2f, [512]]  # 12- [-1, 1, nn.Upsample, [None, 2, 'nearest']]- [[-1, 4], 1, Concat, [1]]  # cat backbone P3- [-1, 3, C2f_SCConv, [256]]  # 15 (P3/8-small)- [-1, 1, Conv, [256, 3, 2]]- [[-1, 12], 1, Concat, [1]]  # cat head P4- [-1, 3, C2f_SCConv, [512]]  # 18 (P4/16-medium)- [-1, 1, Conv, [512, 3, 2]]- [[-1, 9], 1, Concat, [1]]  # cat head P5- [-1, 3, C2f_SCConv, [1024]]  # 21 (P5/32-large)- [[15, 18, 21], 1, Detect, [nc]]  # Detect(P3, P4, P5)

# 关于SCConv的使用,可以直接做卷积使用,也可以放在c2f或者bottleneck中做融合

不知不觉已经看完了哦,动动小手留个点赞吧--_--

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

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

相关文章

ELK在Linux上部署教程

Docker Compose搭建ELK Elasticsearch默认使用mmapfs目录来存储索引。操作系统默认的mmap计数太低可能导致内存不足&#xff0c;我们可以使用下面这条命令来增加内存 sysctl -w vm.max_map_count262144创建Elasticsearch数据挂载路径 mkdir -p /echola/elasticsearch/data对…

【截图服务 +打包】pkg打包 puppeteer

目录 最后结论 windows打包成服务 定制executablePath 用程序来查找chrome.exe 代替上面的写配置文件 服务遇到的问题 使用java开一个线程启动 遇到的问题与解决 版本匹配问题 打出包后的运行报错问题 linux下的安装 安装n 库缺少 程序运行后的报错 制作 运行报…

IT前端好用的工具集

在线抠图网站 https://www.remove.bg/ 将iconfont转成css显示 https://transfonter.org/ 免费的在线图片压缩 https://tinypng.com/ JSON在线格式化工具 https://www.sojson.com/ 国内人工智能kimi.moonshot工具 https://kimi.moonshot.cn/chat/crft7a6sdv14grouufs0 自动…

当人工智能聊天机器人出现问题时

在快速发展的人工智能领域&#xff0c;出现了一项新的挑战。“人工智能私语者”正在通过说服行为良好的聊天机器人打破自己制定的规则来探索人工智能伦理的界限。 这些漏洞被称为即时注入或“越狱”&#xff0c;它们暴露了人工智能系统的漏洞&#xff0c;引发了人们对其安全性…

基于SpringBoot+Vue+MySQL的教学资源共享平台

系统展示 用户前台界面 管理员后台界面 系统背景 随着信息技术的迅猛发展&#xff0c;教育领域对高效、便捷的教学资源需求日益增长。传统教学模式已难以满足当前教育的多样化需求&#xff0c;特别是在资源共享与利用方面存在明显不足。因此&#xff0c;构建一个基于SpringBoot…

OPENAIGC开发者大赛企业组AI黑马奖 | 包你面-AI面试助手

在第二届拯救者杯OPENAIGC开发者大赛中&#xff0c;涌现出一批技术突出、创意卓越的作品。为了让这些优秀项目被更多人看到&#xff0c;我们特意开设了优秀作品报道专栏&#xff0c;旨在展示其独特之处和开发者的精彩故事。 无论您是技术专家还是爱好者&#xff0c;希望能带给您…

HashTable哈希表

概念 散列表(Hash Table)&#xff0c;又称哈希表。是一种数据结构&#xff0c;特点是:数据元素的关键字与其存储地址直接相关 在顺序结构以及树型结构中&#xff0c;数据元素的关键字与其存储位置没有对应的关系&#xff0c;因此在查找一个元素时&#xff0c;必须要经过关键码…

【Python篇】PyQt5 超详细教程——由入门到精通(序篇)

文章目录 PyQt5 超详细入门级教程前言序篇&#xff1a;1-3部分&#xff1a;PyQt5基础与常用控件第1部分&#xff1a;初识 PyQt5 和安装1.1 什么是 PyQt5&#xff1f;1.2 在 PyCharm 中安装 PyQt51.3 在 PyCharm 中编写第一个 PyQt5 应用程序1.4 代码详细解释1.5 在 PyCharm 中运…

《论面向服务架构设计及其应用》写作框架,软考高级系统架构设计师

论文真题 面向服务架构(Service-Oriented Architecture, SOA) 是一种应用框架,将日常的业务应用划分为单独的业务功能服务和流程,通过采用良好定义的接口和标准协议将这些服务关联起来。通过实施基于SOA的系统架构,用户可以构建、部署和整合服务,无需依赖应用程序及其运…

计算机毕业设计选题推荐-在线拍卖系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

CCDO|数据跃动未来:首席数据官如何引领构建活数据引擎

在数字化浪潮汹涌澎湃的今天&#xff0c;数据已成为企业最宝贵的资产之一&#xff0c;它不仅记录着过去&#xff0c;更预示着未来的方向。随着大数据、人工智能、云计算等技术的飞速发展&#xff0c;数据的潜力被前所未有地激发&#xff0c;而首席数据官&#xff08;CDO&#x…

opencv之图像梯度

图像梯度 图像梯度计算的是图像变化的速度。对于图像的边缘部分&#xff0c;其灰度值变化较大&#xff0c;梯度值也较大&#xff1b;相反&#xff0c;对于图像中比较平滑的部分&#xff0c;其灰度值变化较小&#xff0c;相应的梯度值也较小。一般情况下&#xff0c;图像梯度计…

string类--C++

文章目录 一、标准库中的string类1、string类2、auto和范围for2.1、auto关键字2.2、范围for 二、string类的常用接口说明1、string类对象的常见构造2、string类对象的容量操作3、string类对象的访问及遍历操作4、string类对象的修改操作5、string类非成员函数6、vs和g下string结…

004: VTK读入数据---vtkImageData详细说明

VTK医学图像处理---vtkImageData类 目录 VTK医学图像处理---vtkImageData类 简介&#xff1a; 1 Mricro软件的安装和使用 (1) Mricro安装 (2) Mricro转换DICOM为裸数据 2 从硬盘读取数据到vtkImageData 3 vtkImageData转RGB或RGBA格式 4 练习 总结 简介&#xff1a;…

堆的概念与实现

目录 一、堆的介绍 1.堆的概念 2.堆的性质&#xff1a; 3.堆的结构 二、堆的实现 1.堆的定义 2.接口函数 三、堆的实现 1.堆的初始化 2.堆的销毁 3.获取堆顶数据 4.判断堆是否为空 5. 堆的插入 向上调整算法&#xff08;重点&#xff09; 向下调整算法(重点) 6.删除…

【unity小技巧】unity 把window项目打包成只有一个exe的运行文件

文章目录 前言一、unity游戏打包window二、下载安装WinRAR压缩包打包工具三、添加压缩文件1、选择全部6个&#xff08;5个也可以&#xff0c;这个64.exe文件可以省略&#xff09;文件&#xff0c;右键点击添加到压缩文件2、修改压缩文件名&#xff0c;后缀改成.exe3、选择高级–…

【MySQL】索引和事物

索引和事物 索引索引是什么索引的基本操作索引部分原理数据结构讨论B-树B树 MySQL的索引实现 事物事物的概念事物的使用事物的四大特性(ACID)事物并发问题事物的隔离级别 索引 索引是什么 在正常情况下, 数据库去搜索数据, 都是通过一行行的遍历, 然后找到符合要求的行并且筛…

sql中索引查看是否生效

在pg数据库中有多种索引存在&#xff0c;在一般情况下我们取使用普通索引 以下是一些常见导致索引未命中的原因和优化策略 1.如果查询中的条件与索引字段的顺序不匹配&#xff0c;或者索引字段没有完全包含在查询条件中&#xff0c;索引可能不会被使用。 2.在查询中使用函数…

golang学习笔记05——golang协程池,怎么实现协程池?

推荐学习文档 golang应用级os框架&#xff0c;欢迎stargolang实战大纲golang优秀开发常用开源库汇总golang学习笔记01——基本数据类型golang学习笔记02——gin框架及基本原理golang学习笔记03——gin框架的核心数据结构golang学习笔记04——如何真正写好Golang代码&#xff1f…

从卫星和飞机等不同传感器方面由QGIS 遥感分析

在地理信息科学 (GIS) 中,遥感是指从远处获取有关地球表面特征信息的行为。遥感数据是从许多不同的平台获取而来,包括卫星、飞机和具有许多不同传感器的固定仪器,包括光谱图像(相机)和激光雷达。最常见的遥感数据形式是卫星和航空图像。 为了充分实现这些照片的价值,需要…