目标检测算法改进系列之添加SCConv空间和通道重构卷积

2023-12-05

SCConv-空间和通道重构卷积

SCConv(空间和通道重构卷积)的高效卷积模块,以减少卷积神经网络(CNN)中的空间和通道冗余。SCConv旨在通过优化特征提取过程,减少计算资源消耗并提高网络性能。该模块包括两个单元:
1.空间重构单元(SRU):SRU通过分离和重构方法来减少空间冗余。
2.通道重构单元(CRU):CRU采用分割-变换-融合策略来减少通道冗余。

论文地址: SCConv: Spatial and Channel Reconstruction Convolution for Feature Redundancy

SCConv结构

YOLOv8添加SCConv卷积

SCConv代码实现

import torch
import torch.nn.functional as F
import torch.nn as nn
 
 
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_num
        self.group_num = group_num
        self.weight = nn.Parameter(torch.randn(c_num, 1, 1))
        self.bias = nn.Parameter(torch.zeros(c_num, 1, 1))
        self.eps = eps
 
    def 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.bias
 
 
class 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_treshold
        self.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)
        # Gate
        w1 = 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 * x
        x_2 = w2 * x
        y = self.reconstruct(x_1, x_2)
        return y
 
    def 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_channel
        self.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)
        # up
        self.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)
        # low
        self.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):
        # Split
        up, low = torch.split(x, [self.up_channel, self.low_channel], dim=1)
        up, low = self.squeeze1(up), self.squeeze2(low)
        # Transform
        Y1 = self.GWC(up) + self.PWC1(up)
        Y2 = torch.cat([self.PWC2(low), low], dim=1)
        # Fuse
        out = torch.cat([Y1, Y2], dim=1)
        out = F.softmax(self.advavg(out), dim=1) * out
        out1, out2 = torch.split(out, out.size(1) // 2, dim=1)
        return out1 + out2
 
 
class 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
 
 
if __name__ == '__main__':
    x = torch.randn(1, 32, 16, 16)
    model = ScConv(32)
    print(model(x).shape)

SCConv嵌入时额外添加调用函数

YOLOv8中直接嵌入会报错而且参数对不上,所以需要额外定义一个函数作为中转

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 x

将SCConv嵌入C2f与Bottleneck模块

class 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, and
        expansion.
        """
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, k[0], 1)
        self.cv2 = SCConv_yolov8(c_, c2, k[1], 1, g=g)
        self.add = shortcut and c1 == c2
 
    def 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 channels
        self.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))

参考案例

# 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 GFLOPs
  s: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPs
  m: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPs
  l: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
  x: [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)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

目标检测算法改进系列之添加SCConv空间和通道重构卷积 的相关文章

随机推荐

  • CnosDB 科技春晚暨CnosDB 2.4.0 Milky Way发布会|我们程序员也有自己的节目啦

    CnosDB即将举办科技春晚 也是CnosDB 2 4 0版本发布会啦 举办地点就由各位爱码士选在电影院 在此也感谢大家的支持和参与 01 场地剧透 本次发布会正式选择电影院为春晚主办地的现在 就让我们先来一场Venue Tour吧 以上是
  • MX6ULL学习笔记 (七) 中断实验

    前言 本章我们就来学习一 下如何在 Linux 下使用中断 在linux内核里面使用中断 不同于我们以往在别的裸机开发一样 需要进行各种寄存器的配置 中断使能之类的 而在Linux 内核中 提供了完善的中断框架 我们只需要申请中断 然后注
  • 【UE5】使用场系统炸毁一堵墙

    效果 步骤 1 新建一个空白项目 2 新建一个Basic关卡 然后添加一个第三人称游戏和初学者内容包到内容浏览器 3 在场景中添加一堵墙 4 选项模式选择 破裂 点击新建 新建一个文件夹用于存储几何体集 点击 统一 最小和最大Voronoi
  • activemq启动成功但web管理页面却无法访问

    前提 在linux启动activemq成功 本地能ping通linux 处理方案 确定防火墙是否关闭 有两种处理方案 第一种 关闭防火墙 第二种 暴漏8161和61616两个端口 netstat lnpt 查看8161和61616端口 注意
  • 时间序列数据压缩算法简述

    本文简单介绍了时间序列压缩任务的来源 压缩算法的分类 并对常见压缩算法的优缺点进行了简介 爱码士们快来一探究竟呀 引言 时间序列数据是在许多应用程序和领域中生成的一种基本数据类型 例如金融 医疗保健 交通和智慧城市 1 时间序列分析对于各种
  • Docker容器状态显示

    个人笔记 努力奋斗 文章目录 docker ps docker stats 总结 docker ps Docker中 你可以使用以下命令来查看容器的状态 docker ps 这个命令用于列出正在运行的容器 默认情况下 它只显示正在运行的容器
  • 企业ERP软件定制开发对企业的优势|app小程序搭建

    企业ERP软件定制开发对企业的优势 app小程序搭建 ERP Enterprise Resource Planning 软件定制开发是根据企业的具体需求和业务流程特点 定制开发的一种软件解决方案 相比于通用的ERP软件 定制开发可以更好地满
  • 常用的jQuery事件有几种?

    jQuery提供了多种事件处理方法 常用的jQuery事件包括以下几种 click事件 当元素被点击时触发 button click function 点击事件处理逻辑 hover事件 当鼠标悬停在元素上时触发 div hover func
  • 算法与数据结构(二十五)TopK问题:基于快排的Python模板

    首先 先写partition模板 def partition nums left right pivot nums left 初始化一个待比较数据 i j left right while i lt j while i
  • easyrecovery2024绿色版中文语言电脑数据恢复工具

    平时很多人都会把自己工作时 或者生活中的数据存储在我们的电脑上 很多时候 由于我们的误操作或者是其它某些问题 很容易就会误删除一些文件数据了 尤其是一些电脑出现故障 总是会导致数据丢失 这让人非常烦恼 需要重装系统的时候 往往一些文件就无法
  • 2、Linux_远程操作

    远程操作 1 配置ifconfig 1 1输入 ifconfig 查看 ip 的命令 ifconfig 1 2搜索 ifconfig 命令 yum search ifconfig 1 3配置网卡 进入如下目录配置网卡 cd etc sysc
  • 2024不收费的数据恢复软件EasyRecovery16

    EasyRecovery2024是一款操作安全 用户可自主操作的数据恢复方案 它支持从各种各样的存储介质恢复删除或者丢失的文件 其支持的媒体介质包括 硬盘驱动器 光驱 闪存 硬盘 光盘 U盘 移动硬盘 数码相机 手机以及其它多媒体移动设备
  • matplotlib多子图

    matplotlib画图中一个轴占据多个子图 知乎 import matplotlib pyplot as plt fig plt figure gs fig add gridspec 2 4 ax1 fig add subplot gs
  • 目标检测算法改进系列之添加变核卷积AKConv模块

    AKConv变核卷积 KConv的主要思想 AKConv 可变核卷积 主要提供一种灵活的卷积机制 允许卷积核具有任意数量的参数和采样形状 这种方法突破了传统卷积局限于固定局部窗口和固定采样形状的限制 从而使得卷积操作能够更加精准地适应不同数
  • 【LeetCode:1038. 从二叉搜索树到更大和树 | BST+DFS+中序遍历】

    算法题 算法刷题专栏 面试必备算法 面试高频算法 越难的东西 越要努力坚持 因为它具有很高的价值 算法就是这样 作者简介 硕风和炜 CSDN Java领域新星创作者 保研 国家奖学金 高中学习JAVA 大学完善JAVA开发技术栈 面试刷题
  • 【日常踩坑】Debug 从入门到入土

    文章目录 分类 事后 addr2line objdump 反汇编 计算偏移量 优化
  • [原创]C++98升级到C++20的复习旅途-从汇编及逆向角度去分析“constexpr“关键字

    简介 常用网名 猪头三 出生日期 1981 XX XX QQ 643439947 个人网站 80x86汇编小站 https www x86asm org 编程生涯 2001年 至今 共22年 职业生涯 20年 开发语言 C C 80x86A
  • 为什么阿里巴巴修正了HashMap关于1024个元素扩容的次数?

    来源 juejin cn post 7302724955699789863 引言 第一次put调用resize 调用resize 的次数 总结 引言 最近在翻看 阿里巴巴开发手册 嵩山版 即最新版时 发现其修正了关于 HashMap关于10
  • 关于svn如何上传一个完整的项目

    注意 请一定要按照该步骤进行操作 请上传新项目时将项目名称进行规范命名 例如原始文件是arrange v2 将此项目需要注入新的医院 则命名为 arrange 某医院名称 门诊或者医技或者药房 v2 重新命名文件夹名称快捷键 F12 一 先
  • 目标检测算法改进系列之添加SCConv空间和通道重构卷积

    SCConv 空间和通道重构卷积 SCConv 空间和通道重构卷积 的高效卷积模块 以减少卷积神经网络 CNN 中的空间和通道冗余 SCConv旨在通过优化特征提取过程 减少计算资源消耗并提高网络性能 该模块包括两个单元 1 空间重构单元