YOLOv10改进 | Conv篇 | 利用YOLO-MS的MSBlock轻量化网络结构(既轻量又长点)

news2024/9/20 10:41:01

一、本文介绍

本文给大家带来的改进机制是利用YOLO-MS提出的一种针对于实时目标检测的MSBlock模块(其其实不能算是Conv但是其应该是一整个模块),我们将其用于C2f中组合出一种新的结构,来替换我们网络中的模块可以达到一种轻量化的作用,我将其用于我的数据集上实验,包括多个类别的数据集,其在轻量网络结构的同时,却能够提高一定的mAP精度,所以这是一种十分高效的模块,该网络结构非常适合那些模型精度已经无法提到,想要从轻量化模型的角度入手的读者使用,同时该机制包含二次创新的机会欢迎大家订阅本专栏,本专栏每周更新3-5篇最新机制,更有包含我所有改进的文件和交流群提供给大家。

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

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


目录

一、本文介绍

二、MSBlock

2.1  MSBlock的基本原理

2.2 多尺度特征表示

2.3 层次化特征融合

2.4 异构卷积核选择

三、MSBlock的核心代码

四、MSBlock的添加方式 

4.1 修改一

4.2 修改二 

4.3 修改三 

4.4 修改四 

五、MSBlock的yaml文件和运行记录

5.1 MSBlock的yaml文件一

5.2 MSBlock的yaml文件二

5.3 训练代码 

5.4 MSBlock的训练过程截图 

五、本文总结


二、MSBlock

论文地址:论文官方地址

代码地址:官方代码地址


2.1  MSBlock的基本原理

MSBlock的基本原理在于提高实时目标检测器的多尺度特征表示能力。MSBlock通过采用层次化特征融合策略和异构卷积核选择协议,有效地在网络不同阶段处理不同尺度的特征。这种设计使得检测器能够更好地识别和处理不同尺寸的目标。MSBlock的核心思想是通过改进卷积核的大小和结构,以及优化特征融合方式,来增强模型在处理多尺度信息时的性能,从而提高整体的目标检测精度和效率。

MSBlock的基本原理可以分为以下几点:

1. 多尺度特征表示:MSBlock旨在增强实时目标检测器处理不同尺度目标的能力,通过有效地表示和融合不同尺度的特征。

2. 层次化特征融合:MSBlock采用层次化的方式来融合来自网络不同层次的特征,这有助于模型在处理细粒度和粗粒度信息时的表现。

3. 异构卷积核选择:MSBlock实施一种异构卷积核选择协议,即在网络的不同阶段使用不同大小的卷积核,以适应不同尺度的特征表示。

下面我们可以看到三种不同的网络构建模块,分别是CSP Block、ELAN Block和MS-Block。

MS-Block设计包含以下特点:

1. 输入被分割成多个分支,每个分支处理不同的特征子集。
2. 在分支内部,通过1x1卷积进行特征转换,然后应用了一个kxk的深度卷积(深度可分离卷积),再接一个1x1卷积,以增强特征并减少参数数量。
3. 最后,所有的分支再经过一个1x1卷积进行融合,以整合各个分支的特征。


2.2 多尺度特征表示

在本文中,多尺度特征表示是通过MSBlock实现的,它通过在网络的不同层使用不同大小的卷积核来捕捉不同尺度的图像特征。这使得模型能够在低层捕获细节和小尺寸目标的特征,同时在高层捕捉更大区域的特征,有助于识别大尺寸目标。


2.3 层次化特征融合

层次化特征融合是通过MSBlock实现的,该技术利用多个并行处理的子网络或分支来处理输入特征图。这些分支在处理不同尺度的特征后,再通过特定的结构(如1x1卷积)融合这些特征,这样的结构设计允许网络在多个层次上提取和整合特征,提高了对各种尺寸目标的检测性能。

在这张图片中,我们看到了HKS(异构Kernel选择)协议的示意图,这个协议是在YOLO-MS中提出来的。HKS协议通过在网络的不同阶段使用不同大小的卷积核,来优化多尺度特征的提取。在这个图中,从上到下,MS-Block在网络的四个阶段分别使用了9x9、7x7、5x5和3x3的卷积核大小,这种设计允许网络更有效地处理不同尺度的对象,而且每个阶段的输出特征图大小和通道数(C1, C2, C3, C4)也有所不同。最终,通过PAFPN模块将这些特征进一步融合,以增强网络对多尺度特征的捕获能力。


2.4 异构卷积核选择

异构卷积核选择是指在深度学习模型中,根据数据的不同层次和尺度选择不同大小的卷积核。在论文中,通过这种方式,网络可以根据特征图的分辨率调整卷积核的大小,使得在捕捉小目标特征时使用较小的卷积核,在捕捉大目标特征时使用较大的卷积核。这样的设计有助于模型更精细地捕捉不同尺度的图像特征,并提高了目标检测的准确性和效率。


三、MSBlock的核心代码

使用方式看章节四

import torch
import torch.nn as nn

__all__ = ['C2f_MSBlock']

def autopad(k, p=None, d=1):  # kernel, padding, dilation
    """Pad to 'same' shape outputs."""
    if d > 1:
        k = d * (k - 1) + 1 if isinstance(k, int) else [d * (x - 1) + 1 for x in k]  # actual kernel-size
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-pad
    return p


class Conv(nn.Module):
    """Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)."""
    default_act = nn.SiLU()  # default activation

    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
        """Initialize Conv layer with given arguments including activation."""
        super().__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
        self.bn = nn.BatchNorm2d(c2)
        self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()

    def forward(self, x):
        """Apply convolution, batch normalization and activation to input tensor."""
        return self.act(self.bn(self.conv(x)))

    def forward_fuse(self, x):
        """Perform transposed convolution of 2D data."""
        return self.act(self.conv(x))


class MSBlockLayer(nn.Module):
    def __init__(self, inc, ouc, k) -> None:
        super().__init__()

        self.in_conv = Conv(inc, ouc, 1)
        self.mid_conv = Conv(ouc, ouc, k, g=ouc)
        self.out_conv = Conv(ouc, inc, 1)

    def forward(self, x):
        return self.out_conv(self.mid_conv(self.in_conv(x)))


class MSBlock(nn.Module):
    def __init__(self, inc, ouc, kernel_sizes, in_expand_ratio=3., mid_expand_ratio=2., layers_num=3,
                 in_down_ratio=2.) -> None:
        super().__init__()

        in_channel = int(inc * in_expand_ratio // in_down_ratio)
        self.mid_channel = in_channel // len(kernel_sizes)
        groups = int(self.mid_channel * mid_expand_ratio)
        self.in_conv = Conv(inc, in_channel)

        self.mid_convs = []
        for kernel_size in kernel_sizes:
            if kernel_size == 1:
                self.mid_convs.append(nn.Identity())
                continue
            mid_convs = [MSBlockLayer(self.mid_channel, groups, k=kernel_size) for _ in range(int(layers_num))]
            self.mid_convs.append(nn.Sequential(*mid_convs))
        self.mid_convs = nn.ModuleList(self.mid_convs)
        self.out_conv = Conv(in_channel, ouc, 1)

        self.attention = None

    def forward(self, x):
        out = self.in_conv(x)
        channels = []
        for i, mid_conv in enumerate(self.mid_convs):
            channel = out[:, i * self.mid_channel:(i + 1) * self.mid_channel, ...]
            if i >= 1:
                channel = channel + channels[i - 1]
            channel = mid_conv(channel)
            channels.append(channel)
        out = torch.cat(channels, dim=1)
        out = self.out_conv(out)
        if self.attention is not None:
            out = self.attention(out)
        return out


class C2f_MSBlock(nn.Module):
    """Faster Implementation of CSP Bottleneck with 2 convolutions."""

    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):
        """Initialize CSP bottleneck layer with two convolutions with arguments ch_in, ch_out, number, shortcut, groups,
        expansion.
        """
        super().__init__()
        self.c = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, 2 * self.c, 1, 1)
        self.cv2 = Conv((2 + n) * self.c, c2, 1)  # optional act=FReLU(c2)
        self.m = nn.ModuleList(MSBlock(self.c, self.c, kernel_sizes=[1, 3, 3]) for _ in range(n))

    def forward(self, x):
        """Forward pass through C2f layer."""
        y = list(self.cv1(x).chunk(2, 1))
        y.extend(m(y[-1]) for m in self.m)
        return self.cv2(torch.cat(y, 1))

    def forward_split(self, x):
        """Forward pass using split() instead of chunk()."""
        y = list(self.cv1(x).split((self.c, self.c), 1))
        y.extend(m(y[-1]) for m in self.m)
        return self.cv2(torch.cat(y, 1))


四、MSBlock的添加方式 

 这个添加方式和之前的变了一下,以后的添加方法都按照这个来了,是为了和群内的文件适配。


4.1 修改一

第一还是建立文件,我们找到如下ultralytics/nn文件夹下建立一个目录名字呢就是'Addmodules'文件夹(用群内的文件的话已经有了无需新建)!然后在其内部建立一个新的py文件将核心代码复制粘贴进去即可。


4.2 修改二 

第二步我们在该目录下创建一个新的py文件名字为'__init__.py'(用群内的文件的话已经有了无需新建),然后在其内部导入我们的检测头如下图所示。


4.3 修改三 

第三步我门中到如下文件'ultralytics/nn/tasks.py'进行导入和注册我们的模块(用群内的文件的话已经有了无需重新导入直接开始第四步即可)

从今天开始以后的教程就都统一成这个样子了,因为我默认大家用了我群内的文件来进行修改!!


4.4 修改四 

按照我的添加在parse_model里添加即可。

到此就修改完成了,大家可以复制下面的yaml文件运行。


五、MSBlock的yaml文件和运行记录

5.1 MSBlock的yaml文件一

下面的添加MSBlock是我实验结果的版本。

此版本的训练信息:YOLOv10n-C2f-MSBlock-2 summary: 962 layers, 2434086 parameters, 2434070 gradients, 7.7 GFLOPs

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv10 object detection model. For Usage examples see https://docs.ultralytics.com/tasks/detect

# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov10n.yaml' will call yolov10.yaml with scale 'n'
  # [depth, width, max_channels]
  n: [0.33, 0.25, 1024]

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_MSBlock, [128, True]]
  - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
  - [-1, 6, C2f_MSBlock, [256, True]]
  - [-1, 1, SCDown, [512, 3, 2]] # 5-P4/16
  - [-1, 6, C2f_MSBlock, [512, True]]
  - [-1, 1, SCDown, [1024, 3, 2]] # 7-P5/32
  - [-1, 3, C2f_MSBlock, [1024, True]]
  - [-1, 1, SPPF, [1024, 5]] # 9
  - [-1, 1, PSA, [1024]] # 10

# YOLOv10.0n head
head:
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  - [[-1, 6], 1, Concat, [1]] # cat backbone P4
  - [-1, 3, C2f_MSBlock, [512]] # 13

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

  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 13], 1, Concat, [1]] # cat head P4
  - [-1, 3, C2f_MSBlock, [512]] # 19 (P4/16-medium)

  - [-1, 1, SCDown, [512, 3, 2]]
  - [[-1, 10], 1, Concat, [1]] # cat head P5
  - [-1, 3, C2fCIB, [1024, True, True]] # 22 (P5/32-large)

  - [[16, 19, 22], 1, v10Detect, [nc]] # Detect(P3, P4, P5)

5.2 MSBlock的yaml文件二

此版本的训练信息:YOLOv10n-C2f-MSBlock summary: 1009 layers, 2507942 parameters, 2507926 gradients, 7.8 GFLOPs

此版本为将YOLOv10自带的C2fCIB也替换掉了!

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv10 object detection model. For Usage examples see https://docs.ultralytics.com/tasks/detect

# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov10n.yaml' will call yolov10.yaml with scale 'n'
  # [depth, width, max_channels]
  n: [0.33, 0.25, 1024]

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_MSBlock, [128, True]]
  - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
  - [-1, 6, C2f_MSBlock, [256, True]]
  - [-1, 1, SCDown, [512, 3, 2]] # 5-P4/16
  - [-1, 6, C2f_MSBlock, [512, True]]
  - [-1, 1, SCDown, [1024, 3, 2]] # 7-P5/32
  - [-1, 3, C2f_MSBlock, [1024, True]]
  - [-1, 1, SPPF, [1024, 5]] # 9
  - [-1, 1, PSA, [1024]] # 10

# YOLOv10.0n head
head:
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  - [[-1, 6], 1, Concat, [1]] # cat backbone P4
  - [-1, 3, C2f_MSBlock, [512]] # 13

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

  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 13], 1, Concat, [1]] # cat head P4
  - [-1, 3, C2f_MSBlock, [512]] # 19 (P4/16-medium)

  - [-1, 1, SCDown, [512, 3, 2]]
  - [[-1, 10], 1, Concat, [1]] # cat head P5
  - [-1, 3, C2f_MSBlock, [1024]] # 22 (P5/32-large)

  - [[16, 19, 22], 1, v10Detect, [nc]] # Detect(P3, P4, P5)


5.3 训练代码 

import warnings
warnings.filterwarnings('ignore')
from ultralytics import YOLO
 
if __name__ == '__main__':
    model = YOLO('ultralytics/cfg/models/v8/yolov8-C2f-FasterBlock.yaml')
    # model.load('yolov8n.pt') # loading pretrain weights
    model.train(data=r'替换数据集yaml文件地址',
                # 如果大家任务是其它的'ultralytics/cfg/default.yaml'找到这里修改task可以改成detect, segment, classify, pose
                cache=False,
                imgsz=640,
                epochs=150,
                single_cls=False,  # 是否是单类别检测
                batch=4,
                close_mosaic=10,
                workers=0,
                device='0',
                optimizer='SGD', # using SGD
                # resume='', # 如过想续训就设置last.pt的地址
                amp=False,  # 如果出现训练损失为Nan可以关闭amp
                project='runs/train',
                name='exp',
                )


5.4 MSBlock的训练过程截图 


五、本文总结

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

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

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

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

相关文章

全网最适合入门的面向对象编程教程:13 类和对象的 Python 实现-可视化阅读代码神器 Sourcetrail 的安装使用

全网最适合入门的面向对象编程教程:13 类和对象的 Python 实现-可视化阅读代码神器 Sourcetrail 的安装使用 摘要: 本文主要介绍了可视化阅读代码神器Sourcetrail的安装与使用,包括软件简介和特性、下载地址、安装方式、新建工程和如何查看…

SpringMVC(3)——SpringMVC注解实战

前言 SpringMVC(2)——controller方法参数与html表单对应(请求参数的绑定) 上篇博客我们提到了controller方法的参数与html表单之间的对应关系 但是这种对应关系有很多缺点: 传递参数只能放在request的body当中&am…

LabVIEW与ABB工业机器人据监控

​1. 前言 随着工业自动化的发展,工业机器人在制造业中的应用越来越广泛。为了实现对工业机器人的高效监控和控制,本文介绍了利用OPC(OLE for Process Control)服务器将ABB工业机器人与LabVIEW连接起来的解决方案。通过OPC服务器…

Python——使用Seaborn钻石数据可视化分析(1)

目录 🧾 1、数据集(部分数据) ✏️ 2、导入数据集与必要模块 1️⃣ 导入数据 📍 通过info函数查看所有列数据的类型信息 2️⃣ 导入Seaborn工具包 📍 set_context 设置图形绘制时的上下文参数 📍 set_style 设置绘图风格 📍 set_palette 设置图标全局颜色…

数智驱动丨zAIoT 连续落地军工、科研院所和机械制造场景,推动数智化转型升级...

引言 在这个万物互联的时代,科技的进步正以不可阻挡之势,深刻地影响并重塑我们的生产和生活方式。数智化转型升级在各个领域展现出强大的动力,已经成为推动社会向前发展的关键力量。 最近,云和恩墨自主研发的数据智能分析处理平台…

mac M1安装 VSCode

最近在学黑马程序员Java最新AI若依框架项目开发,里面前端用的是Visual Studio Code 所以我也就下载安装了一下,系统是M1芯片的,安装过程还是有点坑的写下来大家注意一下 1.在appstore中下载 2.在系统终端中输入 clang 显示如下图 那么在终端输…

从小主机到第一台自组装NAS:升级与优化记录

目录 前言硬件系统安装的波折过程问题解决系统安装 套件/dockerjellyfin 功耗测试刚安装好系统插上缓存盘且运行了更多的套件和 docker 容器之后 温度场景一场景二场景三 后记参考 在使用了一年的小主机 NAS 后,我决定自己组装并安装新 NAS。本文详细记录了硬件选择…

Audio Toolbox 框架简介

Audio Toolbox 框架简介 Audio Toolbox 框架简介Audio Unit播放和录制音频文件和格式 Audio Toolbox 框架简介 AudioToolbox 框架为录制、播放和流解析提供了接口。在 iOS 中,该框架为管理音频会话提供了额外的接口。 AudioToolbox 框架的基本情况: Au…

海狐外卖O2O商城系统:技术架构与运营模式的深度解析

摘要: 本文深入探讨了海狐外卖O2O商城系统的技术架构、功能特性以及运营模式。海狐外卖作为一款专注于细分市场领域的外卖餐饮解决方案,不仅拥有先进的技术栈支持,还通过丰富的系统插件和灵活的运营模式,为商户和用户提供高效、便…

scratch3编程05-画笔绘制圆及与圆相关的图形

目录 一,圆 1,空心圆 2,实心圆 3,嵌套在一起的圆 4,圆环 二,五角星 1,空心五角星 1)思路 2)完整的程序 2,实心五角星 1)思路 2&…

14-62 剑和诗人36 - 混合专家 (MoE) 扩展 AI 视野

了解混合专家 (MoE) 混合专家 (MoE) 是一种机器学习技术,它将多个“专家”神经网络模型组合成一个更大的模型。MoE 的目标是通过组合专业专家(每个专家专注于不同的子领域)来提高 AI 系统的准确性和能力。 MoE 模型的一些关键特征&#xff1…

C. Earning on Bets

题目 个人补充&#xff1a; #include <bits/stdc.h> using namespace std; #define int long long #define pb push_back #define fi first #define se second #define lson p << 1 #define rson p << 1 | 1 #define ll long longconst int maxn 1e6 5, in…

打印任务无法删除怎么办?

在删除打印任务的时候&#xff0c;你可能会遇到这样的情况&#xff0c;当我们想把打印任务取消的时候&#xff0c;却一直显示正在删除&#xff0c;而过了很久还没有取消掉&#xff0c;下面就分享一下处理这个问题的方法。 1、停止打印服务&#xff0c;按WinR键打开运行对话框&a…

项目进度管理(5-1)常见的缓冲区监控方法

缓冲区监控是一种项目管理技术&#xff0c;主要用于关键链项目管理系统&#xff08;Critical Chain Project Management, CCPM&#xff09;中。它的核心理念是识别和管理项目中的不确定性和依赖性&#xff0c;以提高项目完成的可靠性。 缓冲区监控方法主要是针对项目进度计划执…

Java面试八股之Redis有哪些数据类型?底层实现分别是什么

Redis有哪些数据类型&#xff1f;底层实现分别是什么 Redis数据类型概述 Redis作为一款键值存储系统&#xff0c;提供了丰富多样的数据类型以满足不同场景的需求。以下是Redis支持的主要数据类型及其基本用途&#xff1a; String&#xff08;字符串&#xff09; 存储单个键…

Python | Leetcode Python题解之第220题存在重复元素III

题目&#xff1a; 题解&#xff1a; class Solution(object):def containsNearbyAlmostDuplicate(self, nums, k, t):from sortedcontainers import SortedSetst SortedSet()left, right 0, 0res 0while right < len(nums):if right - left > k:st.remove(nums[left]…

Nginx七层(应用层)反向代理:UWSGI代理uwsgi_pass篇

Nginx七层&#xff08;应用层&#xff09;反向代理 UWSGI代理uwsgi_pass篇 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this a…

攻防世界 Web_python_template_injection(flask模版注入)

学习文章&#xff1a;https://www.freebuf.com/column/187845.html https://blog.csdn.net/weixin_54515836/article/details/113778233 flask的渲染方法有render_template和render_template_string两种。 render_template()是用来渲染一个指定的文件的。使用如下 return re…

时序分解 | Matlab基于ESMD极点对称模态分解

时序分解 | Matlab基于ESMD极点对称模态分解 目录 时序分解 | Matlab基于ESMD极点对称模态分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 ESMD&#xff08;Extreme-point Symmetric Mode Decomposition&#xff09;是一种信号分解方法&#xff0c;用于提取信号中的模…

MVC 返回集合方法,以及分页

返回一个数据集方法 返回多个数据集方法 》》定义一个Model public class IndexMoel {public List<UserGroup> UserGroup{get;set;}public List<User> User{get;set;}}》》》控制器 //db 是 EF 中的上下文 var listnew IndexModel(); list.UserGroupdb.UserGro…