即插即用模块详解SCConv:用于特征冗余的空间和通道重构卷积

目录

一、摘要

二、创新点说明

2.1 Methodology

 2.2SRU for Spatial Redundancy​编辑

2.3CRU for Channel Redundancy

三、实验

3.1基于CIFAR的图像分类

3.2基于ImageNet的图像分类

3.3对象检测

四、代码详解

五、总结


论文:https://openaccess.thecvf.com/content/CVPR2023/papers/Li_SCConv_Spatial_and_Channel_Reconstruction_Convolution_for_Feature_Redundancy_CVPR_2023_paper.pdf

代码:GitHub - cheng-haha/ScConv: SCConv: Spatial and Channel Reconstruction Convolution for Feature Redundancy

一、摘要

卷积神经网络(cnn)在各种计算机视觉任务中取得了显著的性能,但这是以巨大的计算资源为代价的,部分原因是卷积层提取冗余特征。最近的作品要么压缩训练有素的大型模型,要么探索设计良好的轻量级模型。在本文中,我们尝试利用特征之间的空间和通道冗余来进行CNN压缩,并提出了一种高效的卷积模块,称为SCConv (spatial and channel reconstruction convolution),以减少冗余计算并促进代表性特征的学习。提出的SCConv由空间重构单元(SRU)和信道重构单元(CRU)两个单元组成。SRU采用分离重构的方法来抑制空间冗余,CRU采用分离变换融合的策略来减少信道冗余。此外,SCConv是一种即插即用的架构单元,可直接用于替代各种卷积神经网络中的标准卷积。实验结果表明,SCConv嵌入模型能够通过减少冗余特征来获得更好的性能,并且显著降低了复杂度和计算成本。

论文贡献总结:

       1. 提出了一种空间重构单元SRU,该单元根据权重分离冗余特征并进行重构,以抑制空间维度上的冗余,增强特征的表征能力。
       2. 我们提出了一种信道重构单元,称为CRU,它利用分裂变换和融合策略来减少信道维度的冗余以及计算成本和存储。
        3.我们设计了一种名为SCConv的即插即用操作,将SRU和CRU以顺序的方式组合在一起,以取代标准卷积,用于在各种骨干cnn上操作。结果表明,SCConv可以大大节省计算负荷,同时提高模型在挑战性任务上的性能。

二、创新点说明

2.1 Methodology

SCConv,它由两个单元组成,空间重建单元(SRU)和通道重建单元(CRU),以顺序的方式放置。具体而言,对于瓶颈残差块中的中间输入特征X,我们首先通过SRU运算获得空间细化特征Xw,然后利用CRU运算获得信道细化特征Y。我们在SCConv模块中利用了特征之间的空间冗余和通道冗余,可以无缝集成到任何CNN架构中,以减少中间特征映射之间的冗余并增强CNN的特征表示。

 2.2SRU for Spatial Redundancy

为了利用特征的空间冗余,我们引入了空间重构单元(SRU),如图2所示,它利用了分离和重构操作。分离操作的目的是将信息丰富的特征图与空间内容对应的信息较少的特征图分离开来。

2.3CRU for Channel Redundancy

为了利用特征的信道冗余,我们引入了信道重构单元(CRU),如图3所示,它利用了分裂-转换-融合策略。

三、实验

3.1基于CIFAR的图像分类

3.2基于ImageNet的图像分类

3.3对象检测

四、代码详解

import torch  # 导入 PyTorch 库
import torch.nn.functional as F  # 导入 PyTorch 的函数库
import torch.nn as nn  # 导入 PyTorch 的神经网络模块

# 自定义 GroupBatchnorm2d 类,实现分组批量归一化
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  # 断言 c_num 大于等于 group_num
        self.group_num  = group_num  # 设置分组数量
        self.gamma      = nn.Parameter(torch.randn(c_num, 1, 1))  # 创建可训练参数 gamma
        self.beta       = nn.Parameter(torch.zeros(c_num, 1, 1))  # 创建可训练参数 beta
        self.eps        = 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.gamma + self.beta  # 返回归一化后的张量

# 自定义 SRU(Spatial and Reconstruct Unit)类
class SRU(nn.Module):
    def __init__(self,
                 oup_channels:int,  # 输出通道数
                 group_num:int = 16,  # 分组数,默认为16
                 gate_treshold:float = 0.5,  # 门控阈值,默认为0.5
                 torch_gn:bool = False  # 是否使用PyTorch内置的GroupNorm,默认为False
                 ):
        super().__init__()  # 调用父类构造函数

         # 初始化 GroupNorm 层或自定义 GroupBatchnorm2d 层
        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()  # 创建 sigmoid 激活函数

    def forward(self, x):
        gn_x        = self.gn(x)  # 应用分组批量归一化
        w_gamma     = self.gn.gamma / sum(self.gn.gamma)  # 计算 gamma 权重
        reweights   = self.sigomid(gn_x * w_gamma)  # 计算重要性权重

        # 门控机制
        info_mask    = reweights >= self.gate_treshold  # 计算信息门控掩码
        noninfo_mask = reweights < self.gate_treshold  # 计算非信息门控掩码
        x_1          = info_mask * x  # 使用信息门控掩码
        x_2          = noninfo_mask * x  # 使用非信息门控掩码
        x            = self.reconstruct(x_1, x_2)  # 重构特征
        return x

    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)  # 重构特征并连接

# 自定义 CRU(Channel Reduction Unit)类
class CRU(nn.Module):
    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)  # 创建卷积层

        # 上层特征转换
        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)  # 创建卷积层

        # 下层特征转换
        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):
        # 分割输入特征
        up, low = torch.split(x, [self.up_channel, self.low_channel], dim=1)
        up, low = self.squeeze1(up), self.squeeze2(low)

        # 上层特征转换
        Y1 = self.GWC(up) + self.PWC1(up)

        # 下层特征转换
        Y2 = torch.cat([self.PWC2(low), low], dim=1)

        # 特征融合
        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

# 自定义 ScConv(Squeeze and Channel Reduction Convolution)模型
class ScConv(nn.Module):
    def __init__(self, op_channel:int, group_num:int = 16, 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)  # 创建 SRU 层
        self.CRU = CRU(op_channel, alpha=alpha, squeeze_radio=squeeze_radio, group_size=group_size, group_kernel_size=group_kernel_size)  # 创建 CRU 层

    def forward(self, x):
        x = self.SRU(x)  # 应用 SRU 层
        x = self.CRU(x)  # 应用 CRU 层
        return x

if __name__ == '__main__':
    x       = torch.randn(1, 32, 16, 16)  # 创建随机输入张量
    model   = ScConv(32)  # 创建 ScConv 模型
    print(model(x).shape)  # 打印模型输出的形状

五、总结

在本文中,我们提出了一种新的空间和信道重构模块(SCConv),这是一种有效的架构单元,可以降低计算成本和模型存储,同时通过减少标准卷积中广泛存在的空间和信道冗余来提高CNN模型的性能。我们使用两个不同的模块SRU和CRU来减少特征映射中的冗余,在减少大量计算负载的同时实现了相当大的性能改进。此外,SCConv是一个即插即用的模块,可以替代标准的卷积,不需要任何模型架构的调整。此外,各种SOTA方法在图像分类和目标检测方面的大量实验表明,scconvn嵌入模型在性能和模型效率之间取得了更好的平衡。最后,我们希望所提出的方法可以启发研究更有效的建筑设计。

参考:大佬

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

kafka的概念以及Zookeeper集群 + Kafka集群 +elfk集群

目录 zookeeper同步过程 分布式通知和协调 zookeeper同步过程 分布式通知和协调 准备 3 台服务器做 Zookeeper 集群 192.168.68.5 192.168.68.6 192.168.68.7 安装前准备 //关闭防火墙 systemctl stop firewalld systemctl disable firewalld setenforce 0 node1服务器&a…

Linux进阶篇:性能监控工具:socket 统计信息

Linux性能监控工具&#xff1a;socket 统计信息 1 ss命令介绍 ss 是 Socket Statistics 的缩写。ss 命令可以用来获取 socket 统计信息&#xff0c;它显示的内容和 netstat 类似。但 ss 的优势在于它能够显示更多更详细的有关 TCP 和连接状态的信息&#xff0c;而且比 netsta…

ssm052游戏攻略网站的设计与实现+vue

游戏攻略网站设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本游戏攻略网站就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处…

使用avx2 指令集加速向量算法运算

使用cpu-z 查看cpu指令集 2 向量加&#xff0c;乘法&#xff0c;除法 我们使用向量加&#xff0c;为什么函数是0 到 8 的计算&#xff0c;因为avx2 寄存器为256位&#xff0c;同时设置启动增强指令集 #include <immintrin.h> // 引入包含AVX2指令集的头文件void vecto…

2024认证杯数学建模A题保暖纤维保暖能力原创论文讲解(含完整python代码)

大家好呀&#xff0c;从发布赛题一直到现在&#xff0c;总算完成了认证杯数学中国数学建模网络挑战赛第一阶段A题目保暖纤维的保暖能力完整的成品论文。 本论文可以保证原创&#xff0c;保证高质量。绝不是随便引用一大堆模型和代码复制粘贴进来完全没有应用糊弄人的垃圾半成品…

【Conda基础命令】使用conda创建、查看、删除虚拟环境及可能的报错处理

文章目录 前言&#xff08;1&#xff09; 在默认路径下创建一个新的虚拟环境&#xff08;2&#xff09; 查看已有的虚拟环境&#xff08;3&#xff09; 删除已有的虚拟环境&#xff08;谨慎操作&#xff09;&#xff08;4&#xff09;激活虚拟环境&#xff08;5&#xff09;退出…

社区养老服务系统|基于springboot社区养老服务系统设计与实现(源码+数据库+文档)

社区养老服务系统目录 目录 基于springboot社区养老服务系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员部分功能 &#xff08;1&#xff09; 用户管理 &#xff08;2&#xff09;服务种类管理 &#xff08;3&#xff09;社区服务管理 &#xff08…

STM32F103ZE-中断

文章目录 122.12.22.32.42.52.62.6.12.6.2 33.13.23.34.14.3 56788.18.2 NVIC 管理所有中断EXTI 外部中断事件控制器 针对外部 可以看成NVIC 下属 1 中断和 中止&#xff08;不回去了&#xff09;不一样 搁一段时间就如果不用中断 用while&#xff08;&#xff09; 可能夹半天…

中伟视界:智慧矿山智能化预警平台功能详解

矿山智能预警平台是一种高度集成化的安全监控系统&#xff0c;它能够提供实时的监控和报警功能&#xff0c;帮助企业和机构有效预防和响应潜在的安全威胁。以下是矿山智能预警平台的一些关键特性介绍&#xff1a; 报警短视频生成&#xff1a; 平台能够在检测到报警时自动生成短…

记录一次内存溢出

1、查看catalina相关日志&#xff0c;确定关键字相关行号 文件&#xff1a;catalina.out命令1&#xff1a;cat -n catalina.out |grep -a OutOfMemoryError与内存溢出相关的如上&#xff0c;每一个行号其实都对应到具体时间点。可以发现&#xff0c;这个范围相符合&#xff1…

Harbor安装手册

安装Docker yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager \ --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sed -i -e /mirrors.cloud.aliyuncs.com/d -e /mirrors.aliyuncs.com/d \ /etc/yum.repos.d/…

【御控物联】Java JSON结构转换(3):对象To对象——多层属性重组

文章目录 一、JSON结构转换是什么&#xff1f;二、案例之《JSON对象 To JSON对象》三、代码实现四、在线转换工具五、技术资料 一、JSON结构转换是什么&#xff1f; JSON结构转换指的是将一个JSON对象或JSON数组按照一定规则进行重组、筛选、映射或转换&#xff0c;生成新的JS…

Centos Steam 8安装MariaDB报错

1&#xff1a;按照MariaDB的官网配置安装文件. 2 &#xff1a;使用安装命令安装出现下面错误。说“所有的匹配结果均已经被参数的模块化过滤条件除” 3&#xff1a;这个只需要禁用系统的安装模块即可。 yum module disable mariadb 4&#xff1a;再次安装就不会报错了。

C语言——内存函数的实现和模拟实现

1. memcpy 使用和模拟实现 void * memcpy ( void * destination, const void * source, size_t num ); 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。 这个函数在遇到 \0 的时候并不会停下来。 如果source和destination有任何的重叠&am…

2024“点点点”测试员如何上岸测试开发岗?附完整学习路线!

有很多人员会不断问自己&#xff0c;自己到底要不要学测试&#xff0c;或者要不要坚持做测试&#xff0c;测试的职业发展到底怎么样&#xff1f;如果你还在迷茫&#xff0c;在到处找各种大牛问类似的问题&#xff0c;我希望这篇文章&#xff0c;你看完能够结束你的这个烦恼&…

bugku-web-点login咋没反应

在页面源码中看到一个css文件 并看到构建的表是post请求 访问后看到一个注释&#xff0c;叫尝试?17026 在页面尝试 得到源码 这里让在cookie中添加参数BUGKU&#xff0c;并使参数为字符串类型ctf.bugku.com 这里有反序列化函数&#xff0c;先得到字符串ctf.bugku.com的序列号…

深度学习知识点:卷积神经网络(CNN)

深度学习知识点&#xff1a;卷积神经网络&#xff08;CNN&#xff09; 前言卷积神经网络&#xff08;CNN&#xff09;卷积神经网络的结构Keras搭建CNN经典网络分类LeNetAlexNetAlexNet 对比LeNet 的优势&#xff1f; VGGVGG使用2个33卷积的优势在哪里&#xff1f;每层卷积是否只…

Java开发从入门到精通(九):Java的面向对象OOP:成员变量,局部变量,实体类的案例

Java大数据开发和安全开发 &#xff08;一)Java的变量1.1 成员变量和局部变量的区别1.2 成员变量1.3 局部变量1.4 实体类的案例 &#xff08;一)Java的变量 1.1 成员变量和局部变量的区别 1、类中位置不同:成员变量(类中&#xff0c;方法外)、局部变量(常见于方法中)2、初始化…

多模态AnyGPT——整合图像、语音和文本多模态大规模语言模型算法原理与实践

概述 大规模语言模型在理解和生成人类语言方面具有非凡的能力&#xff0c;但迄今为止&#xff0c;它们的能力主要局限于文本处理。然而&#xff0c;现实世界是一个多模式的环境&#xff0c;信息通过视觉、听觉和触觉等多种感官进行交换。融入这种多样性是开发下一代系统的主要…

高效求解最长回文子序列:动态规划方法与C语言实现

高效求解最长回文子序列&#xff1a;动态规划方法与C语言实现 问题描述解决方案伪代码C代码示例算法分析进一步讨论 在计算机科学中&#xff0c;回文是一种有趣的字符串&#xff0c;它在正序和逆序下是相同的。例如&#xff0c;“civic”、"racecar"和"aibohpho…
最新文章