YOLOv5 | 鬼魅(幽灵)卷积 | 改进Ghost卷积轻量化网络

目录

原理简介

代码实现

yaml文件实现

检查是否添加执行成功 

完整代码分享 

论文创新必备

启动命令


由于内存和计算资源有限,在嵌入式设备上部署卷积神经网络 (CNN) 很困难。特征图中的冗余是那些成功的 CNN 的一个重要特征,但在神经架构设计中很少被研究。一种新颖的 Ghost 模块,可以通过廉价的操作生成更多的特征图。基于一组内在特征图,以低廉的成本应用一系列线性变换来生成许多鬼特征图,这些特征图可以充分揭示内在特征背后的信息。Ghost 模块可以作为即插即用组件来升级现有的卷积神经网络。 Ghostbottleneck旨在堆叠Ghost模块,然后可以轻松建立轻量级的GhostNet。Ghost 模块是基线模型中卷积层的令人印象深刻的替代品,并且GhostNet 可以比 MobileNetV3 实现更高的识别性能,并且在 ImageNet ILSVRC2012 分类数据集上具有相似的计算成本。

 ⭐欢迎大家订阅我的专栏一起学习⭐

🚀🚀🚀订阅专栏,更新及时查看不迷路🚀🚀🚀

       YOLOv5涨点专栏:http://t.csdnimg.cn/CNQ32

YOLOv8涨点专栏:http://t.csdnimg.cn/tnoL5

YOLOv7专栏:http://t.csdnimg.cn/HsyvQ

💡魔改网络、复现论文、优化创新💡 

首先引入 Ghost 模块,利用一些小过滤器从原始卷积层生成更多特征图,然后开发一个具有极其高效架构和高性能的新 GhostNet。

原理简介
卷积层和建议的 Ghost 模块的图示,用于输出相同数量的特征图。 Φ 代表廉价操作

深度卷积神经网络通常由大量卷积组成,这会导致巨大的计算成本。尽管 MobileNet 和 ShuffleNet 等最近的工作引入了深度卷积或洗牌操作,以使用较小的卷积滤波器(浮点数操作)构建高效的 CNN,但剩余的 1 × 1 卷积层仍然会占用大量内存和失败。

其中*是卷积运算,b是偏置项,Y ∈ Rh′×w′×n是n个通道的输出特征图,f ∈ Rc×k×k×n是该层的卷积滤波器。另外,h′和w′分别是输出数据的高度和宽度,k×k分别是卷积滤波器f的内核大小。在这个卷积过程中,所需的 FLOP 数量可以计算为 n·h′·w′·c·k·k,由于滤波器数量 n 和通道数量 c 通常为数十万,因此该数量通常高达数十万。非常大(例如 256 或 512)。

利用 Ghost 模块的优点,我们引入了专为小型 CNN 设计的 Ghost 瓶颈(G-bneck)。如图 3 所示,Ghost 瓶颈似乎类似于 ResNet [16] 中的基本残差块,其中集成了多个卷积层和快捷方式。所提出的 Ghost 瓶颈主要由两个堆叠的 Ghost 模块组成。第一个 Ghost 模块充当扩展层,增加通道数量。我们将输出通道数与输入通道数之比称为扩展比。第二个 Ghost 模块减少了通道数量以匹配快捷路径。然后将快捷方式连接在这两个 Ghost 模块的输入和输出之间。批量标准化(BN)[25]和ReLU非线性在每一层之后应用,除了按照MobileNetV2的建议在第二个Ghost模块之后不使用ReLU。上述Ghost瓶颈是针对步长=1的情况。对于stride=2的情况,捷径由下采样层实现,并在两个Ghost模块之间插入stride=2的深度卷积。实际上,这里的 Ghost 模块中的主要卷积是逐点卷积,以提高其效率。 

代码实现
class C3Ghost(C3):
    """C3 module with GhostBottleneck()."""

    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
        """Initialize 'SPP' module with various pooling sizes for spatial pyramid pooling."""
        super().__init__(c1, c2, n, shortcut, g, e)
        c_ = int(c2 * e)  # hidden channels
        self.m = nn.Sequential(*(GhostBottleneck(c_, c_) for _ in range(n)))


class GhostBottleneck(nn.Module):
    """Ghost Bottleneck https://github.com/huawei-noah/ghostnet."""

    def __init__(self, c1, c2, k=3, s=1):
        """Initializes GhostBottleneck module with arguments ch_in, ch_out, kernel, stride."""
        super().__init__()
        c_ = c2 // 2
        self.conv = nn.Sequential(
            GhostConv(c1, c_, 1, 1),  # pw
            DWConv(c_, c_, k, s, act=False) if s == 2 else nn.Identity(),  # dw
            GhostConv(c_, c2, 1, 1, act=False),  # pw-linear
        )
        self.shortcut = (
            nn.Sequential(DWConv(c1, c1, k, s, act=False), Conv(c1, c2, 1, 1, act=False)) if s == 2 else nn.Identity()
        )

    def forward(self, x):
        """Applies skip connection and concatenation to input tensor."""
        return self.conv(x) + self.shortcut(x)

ghost模型的整个结构照搬了mobilenetv3,只是把基本单元给替换掉了,将原本的一步卷积变为两步卷积,第一步首先进行常规卷积,但是减少了输出通道数,第二步在第一步的基础上进行深度可分离卷积(仅取第一步),这里深度可分离卷积跟常规深度可分离卷积有点区别,常规深度可分离卷积(仅取第一步)的输入输出通道数完全相等,卷积核数量也等于输入通道数,这里输出通道数可能是输入通道数的整数倍,卷积核数量等于输出通道数。此外,第二步卷积还有并行的一个连接分支,这个分支直接就是第一步卷积的输出。ghost卷积模块的输出通道数等于第一步卷积后的通道数c加上第二步卷积后的通道数n*c,所以最终通道数为(n+1)*c。此操作的依据是经过观察,发现大部分卷积操作后,输出的特征图很多通道之间存在很高的相似性,那我们就可以经过第一步卷积得到那些没有相似性的通道,然后经过第二步卷积得到剩余那些有相似性的通道

yaml文件实现
# YOLOv5 🚀 by Ultralytics, GPL-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, C3Ghost, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3Ghost, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3Ghost, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3Ghost, [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, C3Ghost, [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, C3Ghost, [256, False]],  # 17 (P3/8-small)

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

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

   [[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]
检查是否添加执行成功 

出现的网络结构变成C3变成C3ghost,则说明添加成功

完整代码分享 

链接: https://pan.baidu.com/s/1N3-7dEdVoMC-QuIGUFpASg?pwd=dwey 提取码: dwey 复制这段内容后打开百度网盘手机App,操作更方便哦

如果报错,请看

解决Yolov5的RuntimeError: result type Float can‘t be cast to the desired output type long int 问题_yolov5 runtimeerror: result type float can't be ca-CSDN博客

启动命令
python train.py model=/path/yolov5_ghost.yaml ...
论文创新必备

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-29 16:26:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-29 16:26:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-29 16:26:03       82 阅读
  4. Python语言-面向对象

    2024-03-29 16:26:03       91 阅读

热门阅读

  1. CentOS7.x 上安装并配置 MySQL 8.x

    2024-03-29 16:26:03       43 阅读
  2. 小程序配置服务器域名

    2024-03-29 16:26:03       53 阅读
  3. 构建docker环境下的thunder迅雷插件

    2024-03-29 16:26:03       49 阅读
  4. C#——系统学习(类与对象)

    2024-03-29 16:26:03       42 阅读
  5. 笔记82:关于 C++ 中的 swap 函数

    2024-03-29 16:26:03       40 阅读
  6. SQL中如何添加数据【保姆】

    2024-03-29 16:26:03       36 阅读
  7. sql server用nest typeorm实现索引的方式

    2024-03-29 16:26:03       38 阅读
  8. cesium NearFarScalar pixelOffsetScaleByDistance

    2024-03-29 16:26:03       40 阅读
  9. Compose UI 之 FloatingActionButton 按钮

    2024-03-29 16:26:03       40 阅读
  10. Docker 四种镜像制作方式

    2024-03-29 16:26:03       42 阅读