YOLOv8改进之C2f模块融合CVPR2023 SCConv

简介: 卷积在各种计算机视觉任务中表现出色,但是由于卷积层提取冗余特征,其计算资源需求巨大。虽然过去用于改善网络效率的各种模型压缩策略和网络设计,包括网络剪枝、权重量化、低秩分解和知识蒸馏等。然而,这些方法都被视为后处理步骤,因此它们的性能通常受到给定初始模型的上限约束。而网络设计另辟蹊径,试图减少密集模型参数中的固有冗余,进一步开发轻量级网络模型。

1. SCConv


卷积在各种计算机视觉任务中表现出色,但是由于卷积层提取冗余特征,其计算资源需求巨大。虽然过去用于改善网络效率的各种模型压缩策略和网络设计,包括网络剪枝、权重量化、低秩分解和知识蒸馏等。然而,这些方法都被视为后处理步骤,因此它们的性能通常受到给定初始模型的上限约束。而网络设计另辟蹊径,试图减少密集模型参数中的固有冗余,进一步开发轻量级网络模型。


SCConv模块的设计

为了解决上述问题,论文(SCConv: Spatial and Channel Reconstruction Convolution for Feature Redundancy (thecvf.com))提出了一个新的卷积模块,名为SCConv,这个模块利用了两个组件:空间重建单元(SRU)和通道重建单元(CRU)。


SRU 通过一种分离-重建的方法抑制空间冗余

CRU 则采用一种分割-转换-融合的策略减少通道冗余

此外,SCConv 是一个即插即用的架构单元,可以直接替换各种卷积神经网络中的标准卷积。


SCConv模块的性能

SCConv 模块旨在有效地限制特征冗余,不仅减少了模型参数和FLOPs的数量,而且增强了特征表示的能力。实际上,SCConv 模块提供了一种新的视角来看待CNNs的特征提取过程,提出了一种更有效地利用空间和通道冗余的方法,从而在减少冗余特征的同时提高模型性能。实验结果显示,嵌入了 SCConv 模块的模型能够通过显著降低复杂性和计算成本,减少冗余特征,从而达到更好的性能。



SRU



CRU



2. YOLOv8 C2f融合SCConv模块


加入融合ScConv的C2f模块,在ultralytics包中的nn包的modules中的block.py文件中添加改进模块。代码如下:

class SRU(nn.Module):
    def __init__(self,
                 oup_channels: int,
                 group_num: int = 16,
                 gate_treshold: float = 0.5
                 ):
        super().__init__()
        self.gn = GroupBatchnorm2d(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.gamma / sum(self.gn.gamma)
        reweigts = self.sigomid(gn_x * w_gamma)
        # Gate
        info_mask = reweigts >= self.gate_treshold
        noninfo_mask = reweigts < 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)
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):
    # https://github.com/cheng-haha/ScConv/blob/main/ScConv.py
    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)
        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 Bottleneck_ScConv(Bottleneck):
    def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5):
        super().__init__(c1, c2, shortcut, g, k, e)
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, k[0], 1)
        self.cv2 = ScConv(c2)
class C2f_ScConv(C2f):
    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):
        super().__init__(c1, c2, n, shortcut, g, e)
        self.m = nn.ModuleList(Bottleneck_ScConv(self.c, self.c, shortcut, g, k=(3, 3), e=1.0) for _ in range(n))


对融合ScConv的C2f模块的进行注册和引用,注册方式参考YOLOv8改进算法之添加CA注意力机制-CSDN博客


在tasks.py中的parse_model中添加C2f_ScConv:



新建相应的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 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_ScConv, [128, True]]
  - [-1, 1, Conv, [256, 3, 2]]  # 3-P3/8
  - [-1, 6, C2f_ScConv, [256, True]]
  - [-1, 1, Conv, [512, 3, 2]]  # 5-P4/16
  - [-1, 6, C2f_ScConv, [512, True]]
  - [-1, 1, Conv, [1024, 3, 2]]  # 7-P5/32
  - [-1, 3, C2f_ScConv, [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, [256]]  # 15 (P3/8-small)
  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 12], 1, Concat, [1]]  # cat head P4
  - [-1, 3, C2f, [512]]  # 18 (P4/16-medium)
  - [-1, 1, Conv, [512, 3, 2]]
  - [[-1, 9], 1, Concat, [1]]  # cat head P5
  - [-1, 3, C2f, [1024]]  # 21 (P5/32-large)
  - [[15, 18, 21], 1, Detect, [nc]]  # Detect(P3, P4, P5)


相关文章
|
2月前
|
机器学习/深度学习 算法 Python
【DYConv】CVPR2020 | 即插即用的动态卷积模块助力你涨点
【DYConv】CVPR2020 | 即插即用的动态卷积模块助力你涨点
297 1
【DYConv】CVPR2020 | 即插即用的动态卷积模块助力你涨点
|
2月前
|
机器学习/深度学习 编解码 文件存储
YOLOv5改进 | 融合改进篇 | BiFPN+ RepViT(教你如何融合改进机制)
YOLOv5改进 | 融合改进篇 | BiFPN+ RepViT(教你如何融合改进机制)
588 1
|
2月前
|
机器学习/深度学习 编解码 文件存储
YOLOv8改进 | 融合改进篇 | BiFPN+ RepViT(教你如何融合改进机制)
YOLOv8改进 | 融合改进篇 | BiFPN+ RepViT(教你如何融合改进机制)
506 1
|
2月前
|
算法 测试技术 vr&ar
【论文速递】CVPR2022 : 用于目标跟踪的统一transformer跟踪器
【论文速递】CVPR2022 : 用于目标跟踪的统一transformer跟踪器
|
2月前
YOLOv5改进 | Neck篇 | 2024.1最新MFDS-DETR的HS-FPN改进特征融合层(轻量化Neck、全网独家首发)
YOLOv5改进 | Neck篇 | 2024.1最新MFDS-DETR的HS-FPN改进特征融合层(轻量化Neck、全网独家首发)
326 4
|
2月前
|
机器学习/深度学习 测试技术 决策智能
【论文速递】CVPR2022 - 全局跟踪Transformers
【论文速递】CVPR2022 - 全局跟踪Transformers
|
2月前
|
机器学习/深度学习 自动驾驶 计算机视觉
YOLOv8改进 | Neck篇 | Slim-Neck替换特征融合层实现超级涨点 (又轻量又超级涨点)
YOLOv8改进 | Neck篇 | Slim-Neck替换特征融合层实现超级涨点 (又轻量又超级涨点)
403 2
|
2月前
|
机器学习/深度学习 自动驾驶 计算机视觉
YOLOv5改进 | Neck篇 | Slim-Neck替换特征融合层实现超级涨点 (又轻量又超级涨点)
YOLOv5改进 | Neck篇 | Slim-Neck替换特征融合层实现超级涨点 (又轻量又超级涨点)
255 0
YOLOv5改进 | Neck篇 | Slim-Neck替换特征融合层实现超级涨点 (又轻量又超级涨点)
|
2月前
|
机器学习/深度学习 监控 算法
【论文速递】CVPR2021 - 通过解耦特征的目标检测知识蒸馏
【论文速递】CVPR2021 - 通过解耦特征的目标检测知识蒸馏
|
机器学习/深度学习 Go 计算机视觉
全新FPN开源 | CFPNet即插即用,助力检测涨点,YOLOX/YOLOv5均有效(二)
全新FPN开源 | CFPNet即插即用,助力检测涨点,YOLOX/YOLOv5均有效(二)
850 0

热门文章

最新文章