YOLOv8改进 | 主干篇 | 利用MobileNetV1替换Backbone(轻量化网络结构)

news2024/9/22 17:28:41

一、本文介绍

本文给大家带来的改进机制是MobileNetV1,其是专为移动和嵌入式视觉应用设计的轻量化网络结构。这些模型基于简化的架构,并利用深度可分离卷积构建轻量级深度神经网络,其引入了两个简单的全局超参数,用于在延迟和准确性之间进行有效的权衡。实验表明,MobileNets在资源和准确性的权衡方面表现出色,并在多种应用(如对象检测、细粒度分类、面部属性识别和大规模地理定位)中展现了其有效性,这个模型非常适合轻量化的读者来使用

适用检测目标:轻量化网络结构适合轻量化的读者

推荐指数:⭐⭐⭐

  专栏回顾:YOLOv8改进系列专栏——本专栏持续复习各种顶会内容——科研必备 

效果回顾展示->

MobileNetV2地址:

MobileNetV3地址:

目录

一、本文介绍

二、MobileNetV1的框架原理

三、MobileNetV1的核心代码

 四、手把手教你添加MobileNetV1网络结构

修改一

修改二

修改三 

修改四

修改五 

修改六 

修改七

修改八

五、MobileNetV1的yaml文件

六、成功运行记录 

七、本文总结


二、MobileNetV1的框架原理

官方论文地址: 论文地址点击即可跳转

官方代码地址: 官方代码地址


MobileNetV1的论文《MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications》介绍了一种高效的模型集合,专为移动和嵌入式视觉应用设计。这些模型基于简化的架构,并利用深度可分离卷积构建轻量级深度神经网络,从而适应移动和嵌入式设备的计算和存储限制。这种架构包含两个步骤:深度卷积(Depthwise Convolution)用于单独处理每个输入通道,然后是逐点卷积(Pointwise Convolution),用于整合深度卷积的输出。通过这种分解,MobileNet显著减少了模型的大小和计算复杂度,同时保持了良好的性能。论文还引入了两个全局超参数,允许在网络大小、速度和准确性之间进行灵活的权衡。

MobileNet的主要创新点包括:

1. 深度可分离卷积:该网络架构使用深度可分离卷积代替标准卷积,显著减少模型参数和计算量。
2. 宽度乘数:提供了一个超参数来调节网络的宽度,从而使得模型可以根据需要进行缩放,适应不同的性能和资源要求。
3. 分辨率乘数:
允许调整输入图像的分辨率,进一步减少计算量。
其中第二点和第三点,在代码中很清楚的就能看到如下图红框的所示,分别对应第二点和第三点。

深度可分离卷积如下图所示 

这张图片描绘了深度可分离卷积的概念,其中标准的卷积滤波器(a)被分解为两个独立的层:深度卷积(b)和逐点卷积(c)。在深度卷积中,每个输入通道独立应用一个滤波器,而逐点卷积则使用1x1的卷积核来组合深度卷积的输出。这种分解方法显著减少了计算量,因为它将卷积操作分为两个更简单的步骤:一个是应用于每个通道的滤波(深度卷积),另一个是这些滤波输出的组合(逐点卷积)。 


三、MobileNetV1的核心代码

下面的代码是整个MobileNetV1的核心代码,大家如果想学习可以和上面的框架原理对比着看一看估计会有一定的收获,使用方式看章节四。

"""A from-scratch implementation of original MobileNet paper ( for educational purposes ).

Paper
    MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications - https://arxiv.org/abs/1704.04861

author : shubham.aiengineer@gmail.com
"""

import torch
from torch import nn



class DepthwiseSepConvBlock(nn.Module):
    def __init__(
        self,
        in_channels: int,
        out_channels: int,
        stride: int = 1,
        use_relu6: bool = True,
    ):
        """Constructs Depthwise seperable with pointwise convolution with relu and batchnorm respectively.

        Args:
            in_channels (int): input channels for depthwise convolution
            out_channels (int): output channels for pointwise convolution
            stride (int, optional): stride paramemeter for depthwise convolution. Defaults to 1.
            use_relu6 (bool, optional): whether to use standard ReLU or ReLU6 for depthwise separable convolution block. Defaults to True.
        """

        super().__init__()

        # Depthwise conv
        self.depthwise_conv = nn.Conv2d(
            in_channels,
            in_channels,
            (3, 3),
            stride=stride,
            padding=1,
            groups=in_channels,
        )
        self.bn1 = nn.BatchNorm2d(in_channels)

        self.relu1 = nn.ReLU6() if use_relu6 else nn.ReLU()

        # Pointwise conv
        self.pointwise_conv = nn.Conv2d(in_channels, out_channels, (1, 1))
        self.bn2 = nn.BatchNorm2d(out_channels)

        self.relu2 = nn.ReLU6() if use_relu6 else nn.ReLU()

    def forward(self, x):
        """Perform forward pass."""

        x = self.depthwise_conv(x)
        x = self.bn1(x)
        x = self.relu1(x)
        x = self.pointwise_conv(x)
        x = self.bn2(x)
        x = self.relu2(x)

        return x


class MobileNetV1(nn.Module):
    def __init__(
        self,
        input_channel: int = 3,
        depth_multiplier: float = 1.0,
        use_relu6: bool = True,
    ):
        """Constructs MobileNetV1 architecture

        Args:
            n_classes (int, optional): count of output neuron in last layer. Defaults to 1000.
            input_channel (int, optional): input channels in first conv layer. Defaults to 3.
            depth_multiplier (float, optional): network width multiplier ( width scaling ). Suggested Values - 0.25, 0.5, 0.75, 1.. Defaults to 1.0.
            use_relu6 (bool, optional): whether to use standard ReLU or ReLU6 for depthwise separable convolution block. Defaults to True.
        """

        super().__init__()

        # The configuration of MobileNetV1
        # input channels, output channels, stride
        config = (
            (32, 64, 1),
            (64, 128, 2),
            (128, 128, 1),
            (128, 256, 2),
            (256, 256, 1),
            (256, 512, 2),
            (512, 512, 1),
            (512, 512, 1),
            (512, 512, 1),
            (512, 512, 1),
            (512, 512, 1),
            (512, 1024, 2),
            (1024, 1024, 1),
        )

        self.model = nn.Sequential(
            nn.Conv2d(
                input_channel, int(32 * depth_multiplier), (3, 3), stride=2, padding=1
            )
        )

        # Adding depthwise block in the model from the config
        for in_channels, out_channels, stride in config:
            self.model.append(
                DepthwiseSepConvBlock(
                    int(in_channels * depth_multiplier),  # input channels
                    int(out_channels * depth_multiplier),  # output channels
                    stride,
                    use_relu6=use_relu6,
                )
            )
        self.index = [128, 256, 512, 1024]
        self.width_list = [i.size(1) for i in self.forward(torch.randn(1, 3, 640, 640))]

    def forward(self, x):
        """Perform forward pass."""
        results = [None, None, None, None]

        for model in self.model:
            x = model(x)
            if x.size(1) in self.index:
                position = self.index.index(x.size(1))  # Find the position in the index list
                results[position] = x
        return results


if __name__ == "__main__":

    # Generating Sample image
    image_size = (1, 3, 224, 224)
    image = torch.rand(*image_size)

    # Model
    mobilenet_v1 = MobileNetV1(depth_multiplier=1)

    out = mobilenet_v1(image)
    print(out)

 四、手把手教你添加MobileNetV1网络结构

这个主干的网络结构添加起来算是所有的改进机制里最麻烦的了,因为有一些网略结构可以用yaml文件搭建出来,有一些网络结构其中的一些细节根本没有办法用yaml文件去搭建,用yaml文件去搭建会损失一些细节部分(而且一个网络结构设计很多细节的结构修改方式都不一样,一个一个去修改大家难免会出错),所以这里让网络直接返回整个网络,然后修改部分 yolo代码以后就都以这种形式添加了,以后我提出的网络模型基本上都会通过这种方式修改,我也会进行一些模型细节改进。创新出新的网络结构大家直接拿来用就可以的。下面开始添加教程->

(同时每一个后面都有代码,大家拿来复制粘贴替换即可,但是要看好了不要复制粘贴替换多了)


修改一

我们复制网络结构代码到“ultralytics/nn/modules”目录下创建一个py文件复制粘贴进去 ,我这里起的名字是MobileNetV1。


修改二

找到如下的文件"ultralytics/nn/tasks.py" 在开始的部分导入我们的模型如下图。

from .modules.MobileNetV1 import MobileNetV1


修改三 

添加如下两行代码!!!


修改四

找到七百多行大概把具体看图片,按照图片来修改就行,添加红框内的部分,注意没有()只是函数名。

        elif m in {自行添加对应的模型即可,下面都是一样的}:
            m = m()
            c2 = m.width_list  # 返回通道列表
            backbone = True


修改五 

下面的两个红框内都是需要改动的。 

        if isinstance(c2, list):
            m_ = m
            m_.backbone = True
        else:
            m_ = nn.Sequential(*(m(*args) for _ in range(n))) if n > 1 else m(*args)  # module
            t = str(m)[8:-2].replace('__main__.', '')  # module type


        m.np = sum(x.numel() for x in m_.parameters())  # number params
        m_.i, m_.f, m_.type = i + 4 if backbone else i, f, t  # attach index, 'from' index, type


修改六 

如下的也需要修改,全部按照我的来。

代码如下把原先的代码替换了即可。 

        if verbose:
            LOGGER.info(f'{i:>3}{str(f):>20}{n_:>3}{m.np:10.0f}  {t:<45}{str(args):<30}')  # print

        save.extend(x % (i + 4 if backbone else i) for x in ([f] if isinstance(f, int) else f) if x != -1)  # append to savelist
        layers.append(m_)
        if i == 0:
            ch = []
        if isinstance(c2, list):
            ch.extend(c2)
            if len(c2) != 5:
                ch.insert(0, 0)
        else:
            ch.append(c2)


修改七

修改七和前面的都不太一样,需要修改前向传播中的一个部分, 已经离开了parse_model方法了。

可以在图片中开代码行数,没有离开task.py文件都是同一个文件。 同时这个部分有好几个前向传播都很相似,大家不要看错了,是70多行左右的!!!,同时我后面提供了代码,大家直接复制粘贴即可,有时间我针对这里会出一个视频。

代码如下->

    def _predict_once(self, x, profile=False, visualize=False):
        """
        Perform a forward pass through the network.

        Args:
            x (torch.Tensor): The input tensor to the model.
            profile (bool):  Print the computation time of each layer if True, defaults to False.
            visualize (bool): Save the feature maps of the model if True, defaults to False.

        Returns:
            (torch.Tensor): The last output of the model.
        """
        y, dt = [], []  # outputs
        for m in self.model:
            if m.f != -1:  # if not from previous layer
                x = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f]  # from earlier layers
            if profile:
                self._profile_one_layer(m, x, dt)
            if hasattr(m, 'backbone'):
                x = m(x)
                if len(x) != 5: # 0 - 5
                    x.insert(0, None)
                for index, i in enumerate(x):
                    if index in self.save:
                        y.append(i)
                    else:
                        y.append(None)
                x = x[-1] # 最后一个输出传给下一层
            else:
                x = m(x)  # run
                y.append(x if m.i in self.save else None)  # save output
            if visualize:
                feature_visualization(x, m.type, m.i, save_dir=visualize)
        return x

到这里就完成了修改部分,但是这里面细节很多,大家千万要注意不要替换多余的代码,导致报错,也不要拉下任何一部,都会导致运行失败,而且报错很难排查!!!很难排查!!! 


修改八

我们找到如下文件'ultralytics/utils/torch_utils.py'按照如下的图片进行修改。

五、MobileNetV1的yaml文件

复制如下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 GFLOP

# YOLOv8.0n backbone
backbone:
  # [from, repeats, module, args]
  - [-1, 1, MobileNetV1, []]  # 4
  - [-1, 1, SPPF, [1024, 5]]  # 5

# YOLOv8.0n head
head:
  - [-1, 1, nn.Upsample, [None, 2, 'nearest']] # 6
  - [[-1, 3], 1, Concat, [1]]  # 7 cat backbone P4
  - [-1, 3, C2f, [512]]  # 8

  - [-1, 1, nn.Upsample, [None, 2, 'nearest']] # 9
  - [[-1, 2], 1, Concat, [1]]  # 10 cat backbone P3
  - [-1, 3, C2f, [256]]  # 11 (P3/8-small)

  - [-1, 1, Conv, [256, 3, 2]] # 12
  - [[-1, 8], 1, Concat, [1]]  # 13 cat head P4
  - [-1, 3, C2f, [512]]  # 14 (P4/16-medium)

  - [-1, 1, Conv, [512, 3, 2]] # 15
  - [[-1, 5], 1, Concat, [1]]  # 16 cat head P5
  - [-1, 3, C2f, [1024]]  # 17 (P5/32-large)

  - [[11, 14, 17], 1, Detect, [nc]]  # Detect(P3, P4, P5)


六、成功运行记录 

下面是成功运行的截图,已经完成了有1个epochs的训练,图片太大截不全第2个epochs了。 


七、本文总结

到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv8改进有效涨点专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,目前本专栏免费阅读(暂时,大家尽早关注不迷路~),如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

专栏回顾:YOLOv8改进系列专栏——本专栏持续复习各种顶会内容——科研必备

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1325244.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java--包,访问修饰符,多态数组,==和equals,hashcode,toString

包 同一个包里面不能有重复的类&#xff0c;不同的包可以有相同的类&#xff0c;包和包之间互不干涉。一个包下面有很多的类。 包的命名规则&#xff1a; 只能包含数字&#xff0c;字母&#xff0c;下划线&#xff0c;小圆点&#xff0c;但不能用数字开头&#xff0c;不能是关…

什么是数据仪表板?数据可视化仪表盘怎么制作?

在数据经济时代&#xff0c;分析数据是每个企业做出最佳决策的关键。但是&#xff0c;手动分析和解释大量数据是不可行的。数据可视化对于分析数据中存在的各种有价值信息至关重要&#xff0c;包括可见趋势和隐藏趋势等。仪表盘显示可视化趋势和信息&#xff0c;例如 KPI、趋势…

【Hadoop】HDFS shell操作与管理工具

HDFS shell操作HDFS管理工具dfsadminfsck均衡器 HDFS shell操作 HDFS 是存取数据的分布式文件系统&#xff0c;对 HDFS 的操作就是文件系统的基本操作&#xff0c;如文件的创建、修改、删除、修改权限&#xff0c;目录的创建、删除、重命名等。对 HDFS 的操作命令类似于 Linux…

Cesium 3DTiles数据格式详解

目录 0 引言1 3DTiles1.1 起源1.2 后缀类型及特点1.2.1 b3dm1.2.2 i3dm1.2.3 pnts1.2.4 cmpt1.2.5 json1.2.6 总结 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;CesiumforUnreal专栏&#x1f4a5; 标题&#xff1a;Cesium 3DTiles数据格式详解❣…

26 在Vue3中使用计算属性

概述 计算属性在真实的开发中也经常被用到。 比如在我最近在研发的一个学生管理系统中&#xff0c;学生有“所属省份”和“所属城市”两个独立属性&#xff0c;比如所属省份是四川&#xff0c;所属城市是成都&#xff0c;但是我们显示的时候要显示为“四川/成都”&#xff0c…

鸿蒙 - arkTs:渲染(循环 - ForEach,判断 - if)

ForEach循环渲染&#xff1a; 参数&#xff1a; 要循环遍历的数组&#xff0c;Array类型遍历的回调方法&#xff0c;Function类型为每一项生成唯一标识符的方法&#xff0c;有默认生成方法&#xff0c;非必传 使用示例&#xff1a; interface Item {name: String,price: N…

无人机支持的空中无蜂窝大规模MIMO系统中上行链路分布式检测

无人机支持的空中无蜂窝大规模MIMO系统中上行链路分布式检测 无人机支持的空中无蜂窝大规模MIMO系统中上行链路分布式检测介绍题目一. 背景&#xff08;解决的问题&#xff09;二. 系统模型2.1 信道模型2.1.1 信道系数2.1.2 进行标准化 2.2 信道估计 和 数据传输2.2.1 信道估计…

【️如何理解Java中的多态】

✅如何理解Java中的多态&#xff1f; ✅理解Java中的多态 ✅ 扩展知识仓✅方法的重载✅方法的重写✅重载和重写的区别区分 ✅理解Java中的多态 多态的概念比较简单&#xff0c;就是同一操作作用于不同的对象&#xff0c;可以有不同的解释&#xff0c;产生不同的执行结果。 如果…

MT6785|MTK6785安卓核心板功能规格介绍_Helio G95核心板

MT6785安卓核心板是一款功能强大的工业级4G智能模块&#xff0c;它采用了Android 9.0操作系统。该核心板内置了蓝牙、FM、WLAN和GPS模块&#xff0c;具有高度集成的基带平台&#xff0c;结合了调制解调器和应用处理子系统&#xff0c;以支持LTE/LTE-A和C2K智能终端应用。 MTK67…

11.2 设备树下的 LED 驱动

一、修改设备树文件 首先进入该目录下 /linux/atk-mpl/linux/my_linux/linux-5.4.31/arch/arm/boot/dts 打开 stm32mp157d-atk.dts 文件&#xff0c;在根节点 "/" 最后输入以下内容&#xff1a; stm32mp1_led {compatible "atkstm32mp1-led"; // 设置…

Gobuster工具详解

目录 Gobuster工具介绍 主要特性 支持模式及全局参数列举 安装 使用 Dir模式 DNS模式 Vhost模式 fuzz模式 TFTP模式 S3、gcs模式 字典 docker运行gobuster Gobuster工具介绍 Gobuster 是一款用于在Web应用程序中进行目录和文件爆破的开源工具。它通过尝试在目标网…

【超详细】基于单片机控制的十字道路口交通灯控制

目录 最终效果 一、设计任务 二、设计报告 1 设计说明 1.1功能分析 1.1.1整体系统功能分析 1.1.2显示状态功能分析 1.1.3设置状态功能分析 1.1.4紧急状态功能分析 1.2方案比选 1.2.1车辆LED数码管倒计时显示板块 1.2.2车辆信号灯显示板块 1.2.3行人信号灯显示板块 …

JavaWeb笔记之前端开发CSS

一 、引言 1.1 CSS概念 层叠样式表(英文全称&#xff1a;Cascading Style Sheets)是一种用来表现HTML&#xff08;标准通用标记语言的一个应用&#xff09;或XML&#xff08;标准通用标记语言的一个子集&#xff09;等文件样式的计算机语言。CSS不仅可以静态地修饰网页&…

Open5GSUeRANSim2:对安装在同一个VM上的OPEN5GS和UERANSIM进行配置和抓取wireshark报文

参考链接&#xff1a; Configuring SCTP & NGAP with UERANSIM and Open5GS on a Single VM for the Open5GS & UERANSIM Series https://www.youtube.com/watch?vINgEX5L5fkE&listPLZqpS76PykwIoqMdUt6noAor7eJw83bbp&index5 Configuring RRC with UERANSI…

YOLOv5性能评估指标->mAP、Precision、Recall、FPS、Confienc (讲解论文关注的主要指标)

简介 这篇博客&#xff0c;主要给大家讲解我们在训练yolov5时生成的结果文件中各个图片及其中指标的含义&#xff0c;帮助大家更深入的理解&#xff0c;以及我们在评估模型时和发表论文时主要关注的参数有那些。本文通过举例训练过程中的某一时间的结果来帮助大家理解&#xf…

LeetCode:162. 寻找峰值、1901. 寻找峰值 II(二分 C++)

目录 162. 寻找峰值 题目描述&#xff1a; 实现代码与解析&#xff1a; 二分 原理思路&#xff1a; 1901. 寻找峰值 II 题目描述&#xff1a; 实现代码与解析&#xff1a; 二分 原理思路&#xff1a; 162. 寻找峰值 题目描述&#xff1a; 峰值元素是指其值严格大于左…

持续集成交付CICD:HELM 自动化完成前端项目应用发布与回滚

目录 一、实验 1.环境 2. GitLab 共享库新建HELM CI流水线 3.Jenkins新建HELM CI流水线 5.Jenkins构建前端项目 6.GitLab 共享库新建HELM CD流水线 7.Jenkins新建HELM CD流水线 8.HELM完成前端项目应用发布与回滚 9.Jenkins再次构建前端项目 10.HELM再次完成前端项目…

在灾难推文分析场景上比较用 LoRA 微调 Roberta、Llama 2 和 Mistral 的过程及表现

引言 自然语言处理 (NLP) 领域的进展日新月异&#xff0c;你方唱罢我登场。因此&#xff0c;在实际场景中&#xff0c;针对特定的任务&#xff0c;我们经常需要对不同的语言模型进行比较&#xff0c;以寻找最适合的模型。本文主要比较 3 个模型: RoBERTa、Mistral-7B 及 Llama-…

HP服务器idrac设置以及系统安装

HP服务器idrac设置以及系统安装 一、设置管理口的地址和密码1、HP服务器重新界面选择"F9"进入BIOS&#xff0c;设置iLo5(idrac)的IP和用户名密码。2、选择"系统配置"。3、选择"iLO 4"配置程序。4、网络选项是设置idrac管理口的地址&#xff0c;设…

使用C语言实现文件的拷贝——底层内存分析

使用C语言实现文件的拷贝 本文主要涉及sprintf&#xff08;&#xff09;函数的讲解以及系统IO与标准IO的区别和一个实例使用C语言实现文件的拷贝&#xff0c;在最后还深度刨析了文件拷贝的底层原理。 文章目录 使用C语言实现文件的拷贝一、 sprintf()函数1.1 sprintf ()函数的参…