SCConve 卷积模块

1、作用

旨在通过空间和通道重构来减少卷积层中的冗余特征,从而降低计算成本并提高特征表达的代表性。SCConv包含两个单元:空间重构单元(SRU)和通道重构单元(CRU)。SRU通过分离和重建方法来抑制空间冗余,而CRU采用分割-转换-融合策略来减少通道冗余。此外,SCConv是一个即插即用的架构单元,可以直接替换各种卷积神经网络中的标准卷积。实验结果表明,嵌入SCConv的模型能够在显著降低复杂度和计算成本的同时,实现更好的性能。

2、机制

1、空间重构单元(SRU):通过分离操作将输入特征图分为信息丰富和信息较少的两部分,然后通过重建操作将这两部分的特征图结合起来,以增强特征表达并抑制空间维度上的冗余。

2、通道重构单元(CRU):采用分割-转换-融合策略,首先将特征图在通道维度上分割成两部分,一部分通过高效的卷积操作进行特征提取,另一部分则直接利用,最后将两部分的特征图通过自适应融合策略合并,以减少通道维度上的冗余并提升特征的代表性。

3、独特优势

1、即插即用

SCConv可以作为一个模块直接嵌入到现有的卷积神经网络中,替换标准的卷积层,无需调整模型架构。

2、减少冗余

通过空间和通道重构有效减少了特征图中的冗余信息,降低了计算成本和模型参数量。

3、提高性能

实验表明,SCConv不仅减少了模型的复杂度和计算量,还在多个任务上取得了比原始模型更好的性能。

4、代码

import torch
import torch.nn.functional as F
import torch.nn as nn

# 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  # 确保通道数大于等于分组数
        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)  # 根据分组数重新排列x的形状
        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)  # 恢复x的原始形状
        return x * self.weight + self.bias  # 应用权重和偏置

# SRU模块用于抑制空间冗余。它通过分组归一化和一个门控机制实现。
class SRU(nn.Module):
    def __init__(self,
                 oup_channels: int,
                 group_num: int = 16,
                 gate_treshold: float = 0.5,
                 torch_gn: bool = False
                 ):
        super().__init__()
        # 选择使用torch自带的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):
        # 实现SRU的前向传播
        gn_x = self.gn(x)  # 应用分组归一化
        w_gamma = self.gn.weight / torch.sum(self.gn.weight)  # 根据归一化权重计算重要性权重
        w_gamma = w_gamma.view(1, -1, 1, 1)
        reweigts = self.sigomid(gn_x * w_gamma)  # 计算重构权重
        # 根据门控阈值,将特征图分为信息丰富和信息较少的两部分
        info_mask = reweigts >= self.gate_treshold
        noninfo_mask = reweigts < self.gate_treshold
        x_1 = info_mask * gn_x
        x_2 = noninfo_mask * gn_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模块用于处理通道冗余。它通过一个压缩-卷积-扩展策略来增强特征的代表性。
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):
        # 实现CRU的前向传播
        # 将输入特征图分为上下两部分
        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)
        # 合并上下分支的特征图,并应用自适应平均池化和softmax函数
        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模块结合了SRU和CRU两个子模块,用于同时处理空间和通道冗余。
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)  # 通过SRU处理空间冗余
        x = self.CRU(x)  # 通过CRU处理通道冗余
        return x  # 返回处理后的特征图

# 测试ScConv模块
if __name__ == '__main__':
    x = torch.randn(1, 32, 16, 16)  # 创建一个随机的输入张量
    model = ScConv(32)  # 创建一个ScConv模块实例
    print(model(x).shape)  # 打印ScConv处理后的输出张量形状

论文《SCConv: Spatial and Channel Reconstruction Convolution for Feature Redundancy》
论文链接

### 卷积模块深度学习中的实现与应用 #### 环境准备与基础构建 为了成功实现卷积模块,首先需要完成必要的准备工作。这通常涉及配置开发环境以及安装所需的依赖库[^1]。例如,在 Python 中可以利用 TensorFlow 或 PyTorch 这样的框架来简化卷积操作的定义。 以下是基于 TensorFlow 的简单卷积层实现示例: ```python import tensorflow as tf # 定义输入张量 (batch_size, height, width, channels) input_tensor = tf.keras.Input(shape=(28, 28, 3)) # 添加一个标准卷积层 conv_layer = tf.keras.layers.Conv2D(filters=32, kernel_size=(3, 3), activation='relu')(input_tensor) model = tf.keras.Model(inputs=input_tensor, outputs=conv_layer) model.summary() ``` 上述代码展示了如何创建一个具有 32 个滤波器的标准二维卷积层,并设置其核大小为 \(3 \times 3\) 和激活函数 ReLU。 #### 深度可分卷积的应用 除了传统的卷积外,现代架构还广泛采用了一种称为 **深度可分卷积** 的技术。这种优化方法通过减少计算复杂性和参数数量显著提高了效率。具体来说,它分为两个阶段:首先是逐通道的空间卷积(depthwise convolution),接着是一个用于扩展特征图维度的 \(1 \times 1\) 卷积(pointwise convolution)。最终输出的深度由目标层数决定,即 \(D_{\text{out}}\) 表示输出深度[^2]。 下面是使用 Keras 实现的一个深度可分卷积的例子: ```python # 使用 Depthwise Convolution 层 depthwise_conv = tf.keras.layers.DepthwiseConv2D(kernel_size=(3, 3))(input_tensor) # 后续接 Pointwise Convolution 来调整输出深度 pointwise_conv = tf.keras.layers.Conv2D(filters=64, kernel_size=(1, 1))(depthwise_conv) model = tf.keras.Model(inputs=input_tensor, outputs=pointwise_conv) model.summary() ``` 此代码片段说明了如何先执行逐通道卷积再进行 \(1 \times 1\) 卷积的操作序列。 #### 总结 卷积模块作为深度学习的核心组成部分之一,不仅能够提取数据空间上的局部特性,还能有效降低模型训练所需资源开销。无论是常规卷积还是改进型结构如深度可分卷积,它们都在实际项目中有广泛应用价值。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值