YOLOv5改进 | 融合改进 | C3融合重写星辰网络之Rewrite the Stars⭐【CVPR2024】

 秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转


💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡


专栏目录: 《YOLOv5入门 + 改进涨点》专栏介绍 & 专栏目录 |目前已有70+篇内容,内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进


最近的研究关注到了在网络设计中尚未充分挖掘的“星运算”(逐元素乘法)的潜力。尽管直观的解释有很多,但其应用的基础原理仍然在很大程度上未被探索。我们的研究试图揭示星运算的能力,它能够在不扩大网络的情况下,将输入映射到高维、非线性的特征空间中,类似于核技巧。我们进一步引入了StarNet,这是一个简单但强大的原型,它在紧凑的网络结构和高效的预算下展现了令人印象深刻的性能和低延迟就像天空中的星星一样,星运算看似不起眼,却蕴含着广阔的潜力宇宙。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。

专栏地址 YOLOv5改进+入门——持续更新各种有效涨点方法 点击即可跳转    

目录

1.原理 

2. 将C3_starNet添加到yolov8网络中

2.1 C3_starNet代码实现

2.2 新增yaml文件

2.3 注册模块

2.4 执行程序

3. 完整代码分享

4. GFLOPs

5. 进阶

6. 总结


1.原理 

论文地址:Rewrite the Stars⭐ ——点击即可跳转

官方代码:官方代码仓库——点击即可跳转

StarNet的主要原理可以总结如下:

StarNet的核心思想

  1. 星操作(Star Operation):

    • 星操作是指元素级乘法(element-wise multiplication),用于融合不同子空间的特征。

    • 这种操作能够将输入特征映射到高维非线性特征空间,类似于核技巧(kernel tricks),而不需要增加网络的宽度(通道数)。

  2. 高维非线性特征映射:

    • 星操作通过元素级乘法生成一个新的特征空间,这个特征空间具有大约((d\sqrt{2})^2)个线性独立的维度。

    • 这种操作与传统神经网络通过增加网络宽度来获得高维特征的方式不同,更像是多项式核函数(polynomial kernel functions)的操作。

  3. 高效的紧凑网络结构:

    • 通过堆叠多个星操作层,每一层都显著增加隐含的维度复杂度。

    • 即使在紧凑的特征空间中操作,星操作仍然能够利用隐含的高维特征。

  4. 性能和效率:

    • 星操作在性能和效率上表现出色,尤其是在网络宽度较小的情况下。

    • StarNet使用星操作设计了一个简单但高效的网络结构,证明了其在紧凑网络中的有效性。

StarNet的实现

网 络结构:

  • StarNet通过堆叠多层星操作层构建

  • 星操作层的基本形式为(W_1^TX + B_1) \ast (W_2^TX + B_2),即通过元素级乘法融合两个线性变换后的特征。

理 论分析和实验验证:

  • 通过理论分析证明了星操作能够在一个层内将输入特征映射到一个高维非线性特征空间,并且在多层堆叠下能够递归地显著增加隐含的特征维度。

  • 实验结果表明,StarNet在ImageNet-1K验证集上的表现优于许多精心设计的高效模型,并且在实际应用中具有较低的延迟和较高的运行效率。

 比较与优势:

  • 与现有的高效网络设计相比,StarNet没有复杂的设计和超参数调优,仅依赖于星操作的高效性。

  • StarNet的设计理念与传统方法(如卷积、线性层和非线性激活的结合)有明显的不同,强调利用隐含的高维特征来提升网络效率。

综上所述,StarNet通过星操作实现了在紧凑网络中的高效性和高性能,展示了元素级乘法在特征融合中的巨大潜力和应用前景。

2. 将C3_starNet添加到yolov8网络中

2.1 C3_starNet代码实现

关键步骤一:将下面的代码粘贴到\yolov5\models\common.py中

from timm.models.layers import DropPath

# CVPR2024 PKINet
class CAA(nn.Module):
    def __init__(self, ch, h_kernel_size = 11, v_kernel_size = 11) -> None:
        super().__init__()
        
        self.avg_pool = nn.AvgPool2d(7, 1, 3)
        self.conv1 = Conv(ch, ch)
        self.h_conv = nn.Conv2d(ch, ch, (1, h_kernel_size), 1, (0, h_kernel_size // 2), 1, ch)
        self.v_conv = nn.Conv2d(ch, ch, (v_kernel_size, 1), 1, (v_kernel_size // 2, 0), 1, ch)
        self.conv2 = Conv(ch, ch)
        self.act = nn.Sigmoid()
    
    def forward(self, x):
        attn_factor = self.act(self.conv2(self.v_conv(self.h_conv(self.conv1(self.avg_pool(x))))))
        return attn_factor * x


class Star_Block(nn.Module):
    def __init__(self, dim, mlp_ratio=3, drop_path=0.):
        super().__init__()
        self.dwconv = Conv(dim, dim, 7, g=dim, act=False)
        self.f1 = nn.Conv2d(dim, mlp_ratio * dim, 1)
        self.f2 = nn.Conv2d(dim, mlp_ratio * dim, 1)
        self.g = Conv(mlp_ratio * dim, dim, 1, act=False)
        self.dwconv2 = nn.Conv2d(dim, dim, 7, 1, (7 - 1) // 2, groups=dim)
        self.act = nn.ReLU6()
        self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()

    def forward(self, x):
        input = x
        x = self.dwconv(x)
        x1, x2 = self.f1(x), self.f2(x)
        x = self.act(x1) * x2
        x = self.dwconv2(self.g(x))
        x = input + self.drop_path(x)
        return x

class Star_Block_CAA(Star_Block):
    def __init__(self, dim, mlp_ratio=3, drop_path=0):
        super().__init__(dim, mlp_ratio, drop_path)
        
        self.attention = CAA(mlp_ratio * dim)
    
    def forward(self, x):
        input = x
        x = self.dwconv(x)
        x1, x2 = self.f1(x), self.f2(x)
        x = self.act(x1) * x2
        x = self.dwconv2(self.g(self.attention(x)))
        x = input + self.drop_path(x)
        return x

class C3_Star(C3):
    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):
        super().__init__(c1, c2, n, shortcut, g, e)
        c_ = int(c2 * e)  # hidden channels
        self.m = nn.Sequential(*(Star_Block(c_) for _ in range(n)))

class C3_Star_CAA(C3):
    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):
        super().__init__(c1, c2, n, shortcut, g, e)
        c_ = int(c2 * e)  # hidden channels
        self.m = nn.Sequential(*(Star_Block_CAA(c_) for _ in range(n)))

StarNet 处理图像的主要工作流程可以分为几个关键步骤,重点关注独特的星型运算及其在分层网络结构中的集成。以下是主要流程的概述:

1. 分层架构

  • StarNet 采用 4 阶段分层架构。每个阶段使用卷积层来降低分辨率,同时将通道数加倍。这种分层方法在现代神经网络设计中很常见,有助于逐步抽象多个级别的图像特征。

2. 星型运算

  • StarNet 的核心创新是星型运算,它在低维空间中计算但产生高维特征。此操作包括使用两组权重转换输入、执行元素乘法以及有选择地应用激活函数。

  • 具体来说,星型操作通常实现为act(W_1^T X) \cdot (W_2^T X),其中W_1W_2是权重矩阵,act  是应用于转换分支之一的激活函数。

3. 块设计和激活放置

  • StarNet 中的每个块都使用深度卷积、批量归一化和简化的激活函数 (ReLU6) 来提高效率。这些块设计简约,避免使用复杂的结构,以强调星型操作的有效性。

  • 激活的位置经过战略性放置,以平衡计算效率和模型性能。文档中的研究表明,与其他位置相比,仅激活一个分支可获得更好的准确性。

4. 通道扩展和网络宽度

  • 在整个网络中,通道扩展始终设置为 4 倍,网络宽度在每个阶段加倍。这种策略有助于管理计算负载,同时提高网络学习复杂特征的能力。

5. 训练和实施细节

  • StarNet 采用类似于 DeiT(数据高效图像变换器)的标准训练方案,以确保公平比较和高效训练。

  • 在推理过程中,批量规范化层融合以简化网络并减少延迟。

通过利用这些技术,StarNet 设法在简单性、计算效率和高性能之间取得平衡,使其成为图像处理任务的引人注目的方法。

2.2 新增yaml文件

关键步骤二在下/yolov5/models下新建文件 yolov5_C3_star.yaml并将下面代码复制进去

  • 目标检测yaml文件 
# Ultralytics YOLOv5 🚀, AGPL-3.0 license

# Parameters
nc: 80 # number of classes
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # layer channel multiple
anchors:
  - [10, 13, 16, 30, 33, 23] # P3/8
  - [30, 61, 62, 45, 59, 119] # P4/16
  - [116, 90, 156, 198, 373, 326] # P5/32

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [
    [-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
    [-1, 1, Conv, [128, 3, 2]], # 1-P2/4
    [-1, 3, C3_Star, [128]],
    [-1, 1, Conv, [256, 3, 2]], # 3-P3/8
    [-1, 6, C3_Star, [256]],
    [-1, 1, Conv, [512, 3, 2]], # 5-P4/16
    [-1, 9, C3_Star, [512]],
    [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
    [-1, 3, C3_Star, [1024]],
    [-1, 1, SPPF, [1024, 5]], # 9
  ]

# YOLOv5 v6.0 head
head: [
    [-1, 1, Conv, [512, 1, 1]],
    [-1, 1, nn.Upsample, [None, 2, "nearest"]],
    [[-1, 6], 1, Concat, [1]], # cat backbone P4
    [-1, 3, C3, [512, False]], # 13

    [-1, 1, Conv, [256, 1, 1]],
    [-1, 1, nn.Upsample, [None, 2, "nearest"]],
    [[-1, 4], 1, Concat, [1]], # cat backbone P3
    [-1, 3, C3, [256, False]], # 17 (P3/8-small)

    [-1, 1, Conv, [256, 3, 2]],
    [[-1, 14], 1, Concat, [1]], # cat head P4
    [-1, 3, C3, [512, False]], # 20 (P4/16-medium)

    [-1, 1, Conv, [512, 3, 2]],
    [[-1, 10], 1, Concat, [1]], # cat head P5
    [-1, 3, C3, [1024, False]], # 23 (P5/32-large)

    [[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
  ]
  • 语义分割yaml文件
# Ultralytics YOLOv5 🚀, AGPL-3.0 license

# Parameters
nc: 80 # number of classes
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # layer channel multiple
anchors:
  - [10, 13, 16, 30, 33, 23] # P3/8
  - [30, 61, 62, 45, 59, 119] # P4/16
  - [116, 90, 156, 198, 373, 326] # P5/32

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [
    [-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
    [-1, 1, Conv, [128, 3, 2]], # 1-P2/4
    [-1, 3, C3_Star, [128]],
    [-1, 1, Conv, [256, 3, 2]], # 3-P3/8
    [-1, 6, C3_Star, [256]],
    [-1, 1, Conv, [512, 3, 2]], # 5-P4/16
    [-1, 9, C3_Star, [512]],
    [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
    [-1, 3, C3_Star, [1024]],
    [-1, 1, SPPF, [1024, 5]], # 9
  ]

# YOLOv5 v6.0 head
head: [
    [-1, 1, Conv, [512, 1, 1]],
    [-1, 1, nn.Upsample, [None, 2, "nearest"]],
    [[-1, 6], 1, Concat, [1]], # cat backbone P4
    [-1, 3, C3, [512, False]], # 13

    [-1, 1, Conv, [256, 1, 1]],
    [-1, 1, nn.Upsample, [None, 2, "nearest"]],
    [[-1, 4], 1, Concat, [1]], # cat backbone P3
    [-1, 3, C3, [256, False]], # 17 (P3/8-small)

    [-1, 1, Conv, [256, 3, 2]],
    [[-1, 14], 1, Concat, [1]], # cat head P4
    [-1, 3, C3, [512, False]], # 20 (P4/16-medium)

    [-1, 1, Conv, [512, 3, 2]],
    [[-1, 10], 1, Concat, [1]], # cat head P5
    [-1, 3, C3, [1024, False]], # 23 (P5/32-large)

    [[17, 20, 23], 1, Segment, [nc, anchors, 32, 256]], # Detect(P3, P4, P5)
  ]

温馨提示:本文只是对yolov5基础上添加模块,如果要对yolov5n/l/m/x进行添加则只需要指定对应的depth_multiple 和 width_multiple。


# YOLOv5n
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.25  # layer channel multiple
 
# YOLOv5s
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple
 
# YOLOv5l 
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple
 
# YOLOv5m
depth_multiple: 0.67  # model depth multiple
width_multiple: 0.75  # layer channel multiple
 
# YOLOv5x
depth_multiple: 1.33  # model depth multiple
width_multiple: 1.25  # layer channel multiple

2.3 注册模块

关键步骤三在yolo.py的parse_model函数替换添加C3_star

2.4 执行程序

在train.py中,将cfg的参数路径设置为yolov5_C3_star.yaml的路径

建议大家写绝对路径,确保一定能找到 

🚀运行程序,如果出现下面的内容则说明添加成功🚀  

                 from  n    params  module                                  arguments
  0                -1  1      7040  models.common.Conv                      [3, 64, 6, 2, 2]
  1                -1  1     73984  models.common.Conv                      [64, 128, 3, 2]
  2                -1  3    164800  models.common.C3_Star                   [128, 128, 3]
  3                -1  1    295424  models.common.Conv                      [128, 256, 3, 2]
  4                -1  6   1100544  models.common.C3_Star                   [256, 256, 6]
  5                -1  1   1180672  models.common.Conv                      [256, 512, 3, 2]
  6                -1  9   6085888  models.common.C3_Star                   [512, 512, 9]
  7                -1  1   4720640  models.common.Conv                      [512, 1024, 3, 2]
  8                -1  3   9346560  models.common.C3_Star                   [1024, 1024, 3]
  9                -1  1   2624512  models.common.SPPF                      [1024, 1024, 5]
 10                -1  1    525312  models.common.Conv                      [1024, 512, 1, 1]
 11                -1  1         0  torch.nn.modules.upsampling.Upsample    [None, 2, 'nearest']
 12           [-1, 6]  1         0  models.common.Concat                    [1]
 13                -1  3   2757632  models.common.C3                        [1024, 512, 3, False]
 14                -1  1    131584  models.common.Conv                      [512, 256, 1, 1]
 15                -1  1         0  torch.nn.modules.upsampling.Upsample    [None, 2, 'nearest']
 16           [-1, 4]  1         0  models.common.Concat                    [1]
 17                -1  3    690688  models.common.C3                        [512, 256, 3, False]
 18                -1  1    590336  models.common.Conv                      [256, 256, 3, 2]
 19          [-1, 14]  1         0  models.common.Concat                    [1]
 20                -1  3   2495488  models.common.C3                        [512, 512, 3, False]
 21                -1  1   2360320  models.common.Conv                      [512, 512, 3, 2]
 22          [-1, 10]  1         0  models.common.Concat                    [1]
 23                -1  3   9971712  models.common.C3                        [1024, 1024, 3, False]        
 24      [17, 20, 23]  1    457725  Detect                                  [80, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [256, 512, 1024]]
YOLOv5_C3_Star summary: 515 layers, 45580861 parameters, 45580861 gradients, 108.0 GFLOPs

3. 完整代码分享

https://pan.baidu.com/s/1QfBkI75fcwfPK_srMspfzg?pwd=ivj4

提取码: ivj4 

4. GFLOPs

关于GFLOPs的计算方式可以查看百面算法工程师 | 卷积基础知识——Convolution

未改进的GFLOPs

img

改进后的GFLOPs

5. 进阶

可以结合损失函数或者卷积模块进行多重改进

YOLOv5改进 | 损失函数 | EIoU、SIoU、WIoU、DIoU、FocuSIoU等多种损失函数——点击即可跳转

6. 总结

StarNet通过引入一种称为星操作(Star Operation)的核心创新,实现了在紧凑网络中高效处理图像的目标。星操作通过两个线性变换后的特征进行元素级乘法,生成一个高维非线性特征空间,类似于多项式核函数的效果。StarNet采用一个四阶段的分层架构,每个阶段通过卷积层下采样分辨率并增加通道数,从而逐步抽象图像特征。每个网络块中使用深度卷积、批量归一化和ReLU6激活函数,简化设计以提高效率。通道扩展固定为4倍,网络宽度在每个阶段翻倍,以平衡计算负载和学习能力。通过标准的训练方法和推理时融合批量归一化层,StarNet在ImageNet-1K等基准测试中展示了其简单设计下的高效性能,表现出色。综上所述,StarNet通过巧妙的特征融合策略和高效的网络结构,在保持低计算复杂度的同时,实现了卓越的图像处理性能。

  • 15
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kay_545

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值