YOLOv5改进 | 主干网络 | 将backbone替换为MobileNetV3【小白必备教程+附完整代码】

简介: 本文介绍了将YOLOv5的backbone替换为MobileNetV3以提升目标检测性能的教程。MobileNetV3采用倒残差结构、Squeeze-and-Excitation模块和Hard-Swish激活函数,实现更高性能和更低计算成本。文中提供了详细的代码实现,包括MobileNetV3的关键组件和YOLOv5的配置修改,便于读者实践。此外,还分享了完整代码链接和进一步的进阶策略,适合深度学习初学者和进阶者学习YOLO系列。
💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡

尽管Ultralytics 推出了最新版本的 YOLOv8 模型。但YOLOv5作为一个anchor base的目标检测的算法,YOLOv5可能比YOLOv8的效果更好。注意力机制是提高模型性能最热门的方法之一,本文给大家带来的教程是将YOLOv5的backbone替换为MobileNetV3结构来提取特征。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。

专栏地址:YOLOv5改进+入门——持续更新各种有效涨点方法

1.原理

MobileNetV3 是 Google 提出的一种轻量级神经网络结构,旨在在移动设备上实现高效的图像识别和分类任务。与之前的 MobileNet 系列相比,MobileNetV3 在模型结构和性能上都有所改进。

MobileNetV3 的结构主要包括以下几个关键组件:

  1. 基础模块(Base Module):MobileNetV3 使用了一种称为“倒残差”(Inverted Residuals)的基础模块结构。该结构采用了深度可分离卷积和线性瓶颈,以减少参数数量和计算复杂度,并且保持了模型的有效性。

  2. Squeeze-and-Excitation 模块:MobileNetV3 引入了 Squeeze-and-Excitation 模块,通过学习通道之间的相互关系,动态地调整通道权重,以增强模型的表征能力。这有助于提高模型对关键特征的感知能力,从而提高分类性能。

  3. Hard-Swish 激活函数:MobileNetV3 使用了一种称为 Hard-Swish 的激活函数。与传统的 ReLU 激活函数相比,Hard-Swish 具有更快的计算速度和更好的性能。

  4. 网络架构优化:MobileNetV3 在网络结构上进行了优化,包括通过网络宽度和分辨率的动态调整,以适应不同的计算资源和任务需求。

总体而言,MobileNetV3 通过这些创新设计和优化,实现了更高的性能和更低的计算成本,使其成为移动设备上图像识别任务的理想选择之一。

精简原理参考:百面算法工程师 | 分类网络总结-CSDN博客

2.MobileNetv3代码实现

2.1 将MobileNetv3代码添加到YOLOv5中

image.png
class h_sigmoid(nn.Module):
    def __init__(self, inplace=True):
        super(h_sigmoid, self).__init__()
        self.relu = nn.ReLU6(inplace=inplace)

    def forward(self, x):
        return self.relu(x + 3) / 6


class h_swish(nn.Module):
    def __init__(self, inplace=True):
        super(h_swish, self).__init__()
        self.sigmoid = h_sigmoid(inplace=inplace)

    def forward(self, x):
        y = self.sigmoid(x)
        return x * y


class SELayer(nn.Module):
    def __init__(self, channel, reduction=4):
        super(SELayer, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.fc = nn.Sequential(
                nn.Linear(channel, channel // reduction),
                nn.ReLU(inplace=True),
                nn.Linear(channel // reduction, channel),
                h_sigmoid()
        )

    def forward(self, x):
        b, c, _, _ = x.size()
        y = self.avg_pool(x)
        y = y.view(b, c)
        y = self.fc(y).view(b, c, 1, 1)
        return x * y

class Conv3BN(nn.Module):

    def __init__(self, inp, oup, stride):
        super(Conv3BN, self).__init__()
        self.conv = nn.Conv2d(inp, oup, 3, stride, 1, bias=False)
        self.bn = nn.BatchNorm2d(oup)
        self.act = h_swish()

    def forward(self, x):
        return self.act(self.bn(self.conv(x)))

    def fuseforward(self, x):
        return self.act(self.conv(x))

class MobileNetv3(nn.Module):
    def __init__(self, inp, oup, hidden_dim, kernel_size, stride, use_se, use_hs):
        super(MobileNetv3, self).__init__()
        assert stride in [1, 2]

        self.identity = stride == 1 and inp == oup

        if inp == hidden_dim:
            self.conv = nn.Sequential(
                # dw
                nn.Conv2d(hidden_dim, hidden_dim, kernel_size, stride, (kernel_size - 1) // 2, groups=hidden_dim, bias=False),
                nn.BatchNorm2d(hidden_dim),
                h_swish() if use_hs else nn.ReLU(inplace=True),
                # Squeeze-and-Excite
                SELayer(hidden_dim) if use_se else nn.Sequential(),
                # pw-linear
                nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
                nn.BatchNorm2d(oup),
            )
        else:
            self.conv = nn.Sequential(
                # pw
                nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),
                nn.BatchNorm2d(hidden_dim),
                h_swish() if use_hs else nn.ReLU(inplace=True),
                # dw
                nn.Conv2d(hidden_dim, hidden_dim, kernel_size, stride, (kernel_size - 1) // 2, groups=hidden_dim, bias=False),
                nn.BatchNorm2d(hidden_dim),
                # Squeeze-and-Excite
                SELayer(hidden_dim) if use_se else nn.Sequential(),
                h_swish() if use_hs else nn.ReLU(inplace=True),
                # pw-linear
                nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
                nn.BatchNorm2d(oup),
            )

    def forward(self, x):
        y = self.conv(x)
        if self.identity:
            return x + y
        else:
            return y

MobileNetV3 的主要处理流程如下:

  1. 输入处理:输入图像首先经过预处理步骤,例如归一化和大小调整,以使其适应网络的输入要求。

  2. 特征提取:经过输入处理后,图像通过一系列基础模块(Base Module)进行特征提取。每个基础模块通常包含深度可分离卷积、激活函数(如 Hard-Swish)和通道注意力(如 Squeeze-and-Excitation)模块。

  3. 特征增强:在特征提取的过程中,通过 Squeeze-and-Excitation 模块对提取的特征图进行增强,以加强对重要特征的感知能力。

  4. 全局平均池化:在特征提取的最后阶段,通过全局平均池化操作将特征图的空间维度降低到一个固定大小。

  5. 分类器:全局平均池化后的特征图输入到分类器中,进行分类或其他任务的预测。分类器通常由一个或多个全连接层组成,最后输出预测结果。

整个流程通过堆叠和连接这些组件来完成。MobileNetV3 的设计旨在保持模型的轻量化和高效性能,以适应移动设备上的图像识别和分类任务。

image.png

2.2新增yaml文件

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license

# parameters
nc: 2  # number of classes
depth_multiple: 1.0  # dont change this otherwise InvertedResidual will be affected
width_multiple: 1.0  # dont change this otherwise InvertedResidual will be affected

# anchors
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 backbone
backbone:
  # MobileNetV3-large
  # [from, number, module, args]
  [[-1, 1, Conv3BN, [16, 2]],                          # 0-p1/2
   [-1, 1, MobileNetv3, [ 16,  16, 3, 1, 0, 0]],  # 1-p1/2
   [-1, 1, MobileNetv3, [ 24,  64, 3, 2, 0, 0]],  # 2-p2/4
   [-1, 1, MobileNetv3, [ 24,  72, 3, 1, 0, 0]],  # 3-p2/4
   [-1, 1, MobileNetv3, [ 40,  72, 5, 2, 1, 0]],  # 4-p3/8
   [-1, 1, MobileNetv3, [ 40, 120, 5, 1, 1, 0]],  # 5-p3/8
   [-1, 1, MobileNetv3, [ 40, 120, 5, 1, 1, 0]],  # 6-p3/8
   [-1, 1, MobileNetv3, [ 80, 240, 3, 2, 0, 1]],  # 7-p4/16
   [-1, 1, MobileNetv3, [ 80, 200, 3, 1, 0, 1]],  # 8-p4/16
   [-1, 1, MobileNetv3, [ 80, 184, 3, 1, 0, 1]],  # 9-p4/16
   [-1, 1, MobileNetv3, [ 80, 184, 3, 1, 0, 1]],  # 10-p4/16
   [-1, 1, MobileNetv3, [112, 480, 3, 1, 1, 1]],  # 11-p4/16
   [-1, 1, MobileNetv3, [112, 672, 3, 1, 1, 1]],  # 12-p4/16
   [-1, 1, MobileNetv3, [160, 672, 5, 1, 1, 1]],  # 13-p4/16
   [-1, 1, MobileNetv3, [160, 672, 5, 2, 1, 1]],  # 14-p5/32
   [-1, 1, MobileNetv3, [160, 960, 5, 1, 1, 1]],  # 15-p5/32
  ]

# YOLOv5 head
head:
  [[-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 13], 1, Concat, [1]],  # cat backbone P4
   [-1, 1, C3, [256, False]],  # 19

   [-1, 1, Conv, [128, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P3
   [-1, 1, C3, [128, False]],  # 23 (P3/8-small)

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

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 16], 1, Concat, [1]],  # cat head P5
   [-1, 1, C3, [512, False]],  # 29 (P5/32-large)

   [[23, 26, 29], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

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

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 注册模块

image.png

2.4 执行程序

在train.py中,将cfg的参数路径设置为yolov5_mobilemetv3.yaml的路径,如下图所示

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

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

image.png

3.完整代码分享

YOLOv5改进 | 主干网络 | 将backbone替换为MobileNetV3【小白必备教程+附完整代码】

👆是我修改后的完整,提取码unah

4.总结

MobileNetV3 是一种轻量级神经网络结构,通过倒残差基础模块、Squeeze-and-Excitation 模块和Hard-Swish 激活函数等创新技术,实现了在移动设备等资源受限环境下高效的图像识别和分类任务。其处理流程包括输入处理、特征提取、特征增强、全局平均池化和分类器预测,通过优化网络结构和设计,MobileNetV3 在保持性能的同时减少了计算负载,适用于移动设备上的应用场景。

5. 进阶

在backbone中单独添加一层或者是替换一个C3模块,也是可行的策略,这里直接放上改进后的代码。提示:也可以尝试替换其他啊部位的C3模块。

YOLOv5改进 | 主干网络 | 将backbone替换为MobileNetV3【小白必备教程+附完整代码】
👆是我修改后的完整,提取码: 6wpu

可能在实验过程可能会遇到问题,如果你不能解决,欢迎评论区提问

相关文章
|
11天前
|
机器学习/深度学习 编解码 算法
YOLOv5改进 | 主干网络 | 用EfficientNet卷积替换backbone【教程+代码 】
在YOLOv5的GFLOPs计算量中,卷积占了其中大多数的比列,为了减少计算量,研究人员提出了用EfficientNet代替backbone。本文给大家带来的教程是**将原来的主干网络替换为EfficientNet。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。
|
13天前
|
机器学习/深度学习 编解码 边缘计算
YOLOv5改进 | 卷积模块 | 用ShuffleNetV2卷积替换Conv【轻量化网络】
本文介绍了如何在YOLOv5中用ShuffleNetV2替换卷积以减少计算量。ShuffleNetV2是一个轻量级网络,采用深度可分离卷积、通道重组和多尺度特征融合技术。文中提供了一个逐步教程,包括ShuffleNetV2模块的代码实现和在YOLOv5配置文件中的添加方法。此外,还分享了完整的代码链接和GFLOPs的比较,显示了GFLOPs的显著减少。该教程适合初学者实践,以提升深度学习目标检测技能。
YOLOv5改进 | 卷积模块 | 用ShuffleNetV2卷积替换Conv【轻量化网络】
|
2天前
|
机器学习/深度学习 计算机视觉 知识图谱
【YOLOv8改进】MobileViT 更换主干网络: 轻量级、通用且适合移动设备的视觉变压器 (论文笔记+引入代码)
MobileViT是针对移动设备的轻量级视觉Transformer网络,结合CNN的局部特征、Transformer的全局注意力和ViT的表示学习。在ImageNet-1k上,它以600万参数实现78.4%的top-1准确率,超越MobileNetv3和DeiT。MobileViT不仅适用于图像分类,还在目标检测等任务中表现出色,且优化简单,代码已开源。YOLOv8引入了MobileViT块,整合卷积和Transformer结构,提升模型性能。更多详情可参考相关专栏和链接。
|
4天前
|
存储 人工智能 搜索推荐
社区供稿 | YuanChat全面升级:知识库、网络检索、适配CPU,手把手个人主机部署使用教程
在当下大语言模型飞速发展的背景下,以大模型为核心的AI助手成为了广大企业和个人用户最急切需求的AI产品。然而在复杂的现实办公场景下,简单的对话功能并不能满足用户的全部办公需求,为此我们发布了最新版的YuanChat应用
|
9天前
|
机器学习/深度学习 编解码 算法
YOLOv8改进 | 主干网络 | 增加网络结构增强小目标检测能力【独家创新——附结构图】
YOLOv8在小目标检测上存在挑战,因卷积导致信息丢失。本文教程将原网络结构替换为更适合小目标检测的backbone,并提供结构图。通过讲解原理和手把手教学,指导如何修改代码,提供完整代码实现,适合新手实践。文章探讨了大特征图对小目标检测的重要性,如细节保留、定位精度、特征丰富度和上下文信息,并介绍了FPN等方法。YOLOv8流程包括预处理、特征提取、融合和检测。修改后的网络结构增加了上采样和concatenate步骤,以利用更大特征图检测小目标。完整代码和修改后的结构图可在文中链接获取。
|
13天前
|
消息中间件 Java Linux
2024年最全BATJ真题突击:Java基础+JVM+分布式高并发+网络编程+Linux(1),2024年最新意外的惊喜
2024年最全BATJ真题突击:Java基础+JVM+分布式高并发+网络编程+Linux(1),2024年最新意外的惊喜
|
10天前
|
JSON 安全 网络协议
【Linux 网络】网络基础(二)(应用层协议:HTTP、HTTPS)-- 详解
【Linux 网络】网络基础(二)(应用层协议:HTTP、HTTPS)-- 详解
|
10天前
|
存储 网络协议 Unix
【Linux 网络】网络编程套接字 -- 详解
【Linux 网络】网络编程套接字 -- 详解
|
10天前
|
存储 网络协议 Linux
【Linux 网络】网络基础(一)(局域网、广域网、网络协议、TCP/IP结构模型、网络传输、封装和分用)-- 详解(下)
【Linux 网络】网络基础(一)(局域网、广域网、网络协议、TCP/IP结构模型、网络传输、封装和分用)-- 详解(下)
|
10天前
|
存储 网络协议 安全
【Linux 网络】网络基础(一)(局域网、广域网、网络协议、TCP/IP结构模型、网络传输、封装和分用)-- 详解(上)
【Linux 网络】网络基础(一)(局域网、广域网、网络协议、TCP/IP结构模型、网络传输、封装和分用)-- 详解(上)

热门文章

最新文章