YOLOv5算法改进(13)— 替换主干网络之PP-LCNet

前言:Hello大家好,我是小哥谈。PP-LCNet是一个由百度团队针对Intel-CPU端加速而设计的轻量高性能网络。它是一种基于MKLDNN加速策略的轻量级卷积神经网络,适用于多任务,并具有提高模型准确率的方法。与之前预测速度相近的模型相比,PP-LCNet具有更高的准确性。此外,对于计算机视觉的下游任务(如目标检测、语义分割等),该模型的效果也很好。 PP-LCNet还采用了H-Swish激活函数,这是一种优化的激活函数,可以提高性能而几乎不增加预测时间。🌈 

 前期回顾:

              YOLOv5算法改进(1)— 如何去改进YOLOv5算法

              YOLOv5算法改进(2)— 添加SE注意力机制

              YOLOv5算法改进(3)— 添加CBAM注意力机制

              YOLOv5算法改进(4)— 添加CA注意力机制

              YOLOv5算法改进(5)— 添加ECA注意力机制

              YOLOv5算法改进(6)— 添加SOCA注意力机制

              YOLOv5算法改进(7)— 添加SimAM注意力机制

              YOLOv5算法改进(8)— 替换主干网络之MobileNetV3

              YOLOv5算法改进(9)— 替换主干网络之ShuffleNetV2

              YOLOv5算法改进(10)— 替换主干网络之GhostNet

              YOLOv5算法改进(11)— 替换主干网络之EfficientNetv2

              YOLOv5算法改进(12)— 替换主干网络之Swin Transformer

             目录

🚀1.论文

🚀2.PP-LCNet网络架构及原理

YOLOv5%E7%BB%93%E5%90%88PP-LCNet-toc" style="margin-left:80px;">🚀3.YOLOv5结合PP-LCNet

💥💥步骤1:在common.py中添加PP-LCNet模块

💥💥步骤2:在yolo.py文件中加入类名

💥💥步骤3:创建自定义yaml文件

💥💥步骤4:验证是否加入成功

💥💥步骤5:修改train.py中的'--cfg'默认参数

🚀1.论文

PP-LCNet是百度团队结合Intel-CPU端侧推理特性而设计的轻量高性能网络,所提方案在图像分类任务上取得了比ShuffleNetV2MobileNetV2MobileNetV3以及GhostNet更优的延迟-精度均衡。论文提出了一种基于MKLDNN加速的轻量CPU模型PP-LCNet,它在多个任务上改善了轻量型模型的性能🍃

如下图所示,在图像分类任务方面,所提PP-LCNet在推理延迟-精度均衡方面大幅优于ShuffleNetV2、MobileNetV2、MobileNetV3以及GhostNet。

论文试验结果:

不同尺度的PP-LCNet在ImageNet上的精度和延迟如下表所示:

 和其它轻量模型的对比如下表所示:

说明:♨️♨️♨️

本文提出一个能够在 CPU 上训练的深度学习网络模型,文章和算法都很简单,很容易复现。

文章总结起来就 4 点

📚(1)使用 H-Swish (替代传统的 ReLU);

📚(2)SE 模块放在最后一层,并使用大尺度卷积核;

📚(3)大尺度卷积核放在最后几层;

📚(4)在最后的 global average pooling 后增加更大尺寸的 1 × 1 卷积层。

论文题目:《PP-LCNet: A Lightweight CPU Convolutional Neural Network》

论文地址:  https://arxiv.org/abs/2109.15099

代码实现:  GitHub - ngnquan/PP-LCNet: PyTorch implementation of PP-LCNet


🚀2.PP-LCNet网络架构及原理

PP-LCNet网络结构整体如下图所示:

🍀(1)模块

使用了类似 MobileNetV1 中的深度可分离卷积作为基础,通过堆叠模块构建了一个类似 MobileNetV1 的BaseNet,然后组合BaseNet与某些现有技术构建了一种更强力网络PP-LCNet。

结构图如下,左图是卷积+标准化+激活函数,右图是PP-LCNet中的基础模块,源代码中是先卷积+SE模块+卷积。👇

🍀(2)激活函数的使用

自从卷积神经网络使用了 ReLU 激活函数后,网络性能得到了大幅度的提升,近些年 ReLU 激活函数的变体也相继出现,如 Leaky-ReLU、P-ReLU、ELU 等。2017 年,谷歌大脑团队通过搜索的方式得到了 swish 激活函数,该激活函数在轻量级网络上表现优异,在 2019 年,MobileNetV3 的作者将该激活函数进一步优化为 H-Swish,该激活函数去除了指数运算、速度更快、网络精度几乎不受影响,也经过很多实验发现该激活函数在轻量级网络上有优异的表现。所以在 PP-LCNet 中,选用了该激活函数🌱

🍀(3)SE 模块

SE模块使用了激活函数ReLU和H-sigmoid。

🍀(4)合适的位置添加更大的卷积核

通过实验总结了一些更大的卷积核在不同位置的作用,类似 SE 模块的位置,更大的卷积核在网络的中后部作用更明显,所以在网络的后部会使用很多5x5的卷积核。

🍀(5)GAP 后使用更大的 1x1 卷积层

在 GoogLeNet 之后,GAP(Global-Average-Pooling)后往往直接接分类层,但是在轻量级网络中,这样会导致 GAP 后提取的特征没有得到进一步的融合和加工。如果在此后使用一个更大的 1x1 卷积层(等同于 FC 层),GAP 后的特征便不会直接经过分类层,而是先进行了融合,并将融合的特征进行分类。这样可以在不影响模型推理速度的同时大大提升准确率。


YOLOv5%E7%BB%93%E5%90%88PP-LCNet">🚀3.YOLOv5结合PP-LCNet

💥💥步骤1:在common.py中添加PP-LCNet模块

将下面PP-LCNet模块的代码复制粘贴到common.py文件的末尾。

class SeBlock(nn.Module):
    def __init__(self, in_channel, reduction=4):
        super().__init__()
        self.Squeeze = nn.AdaptiveAvgPool2d(1)

        self.Excitation = nn.Sequential()
        self.Excitation.add_module('FC1', nn.Conv2d(in_channel, in_channel // reduction, kernel_size=1))  # 1*1卷积与此效果相同
        self.Excitation.add_module('ReLU', nn.ReLU())
        self.Excitation.add_module('FC2', nn.Conv2d(in_channel // reduction, in_channel, kernel_size=1))
        self.Excitation.add_module('Sigmoid', nn.Sigmoid())

    def forward(self, x):
        y = self.Squeeze(x)
        ouput = self.Excitation(y)
        return x * (ouput.expand_as(x))
 
 
class DepthSepConv(nn.Module):
    def __init__(self, inp, oup, dw_size, stride, use_se):
        super(DepthSepConv, self).__init__()
        self.stride = stride
        self.inp = inp
        self.oup = oup
        self.dw_size = dw_size
        self.dw_sp = nn.Sequential(
            nn.Conv2d(self.inp, self.inp, kernel_size=self.dw_size, stride=self.stride, padding=(dw_size - 1) // 2, groups=self.inp, bias=False),
            nn.BatchNorm2d(self.inp),
            nn.Hardswish(),

            SeBlock(self.inp, reduction=16) if use_se else nn.Sequential(),

            nn.Conv2d(self.inp, self.oup, kernel_size=1, stride=1, padding=0, bias=False),
            nn.BatchNorm2d(self.oup),
            nn.Hardswish())

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

💥💥步骤2:在yolo.py文件中加入类名

首先在yolo.py文件中找到 parse_model函数这一行,加入DepthSepConv

💥💥步骤3:创建自定义yaml文件

models文件夹中复制yolov5s.yaml,粘贴并重命名为yolov5s_PPLCNet.yaml

然后根据PP-LCNet的网络架构来修改配置文件。

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

#  PP-LCNet backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [16, 3, 2, 1]],              # 0-P1/2  ch_out, kernel, stride, padding
   [-1, 1, DepthSepConv, [32, 3, 1, False]],  # 1

   [-1, 1, DepthSepConv, [64, 3, 2, False]],  # 2-P2/4
   [-1, 1, DepthSepConv, [64, 3, 1, False]],  # 3

   [-1, 1, DepthSepConv, [128, 3, 2, False]], # 4-P3/8
   [-1, 1, DepthSepConv, [128, 3, 1, False]], # 5

   [-1, 1, DepthSepConv, [256, 3, 2, False]], # 6-P4/16
   [-1, 5, DepthSepConv, [256, 5, 1, False]], # 7

   [-1, 1, DepthSepConv, [512, 5, 2, True]],  # 8-P5/32
   [-1, 1, DepthSepConv, [512, 5, 1, True]],  # 9
  ]

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

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

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

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

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

💥💥步骤4:验证是否加入成功

yolo.py文件里,配置我们刚才自定义的yolov5s_PPLCNet.yaml

然后运行yolo.py,得到结果。

这样就算添加成功了。🎉🎉🎉  

💥💥步骤5:修改train.py中的'--cfg'默认参数

train.py文件中找到 parse_opt函数,然后将第二行 '--cfg的default改为 'models/yolov5s_PPLCNet.yaml ',然后就可以开始进行训练了。🎈🎈🎈 



http://www.niftyadmin.cn/n/4995367.html

相关文章

多线程练习-顺序打印

wait和notify的使用推荐看通过wait和notify来协调线程执行顺序 题目 有三个线程,线程名称分别为:a,b,c。 每个线程打印自己的名称。 需要让他们同时启动,并按 c,b,a的顺序打印 代码及其注释…

windows|修复桌面图标变成白色.bat

taskkill /f /im explorer.exe DEL %localappdata%\IconCache.db /a start explorer.exe打开方式 1 桌面新建txt文件, 复制以上代码 粘贴保存,另存为 修复桌面图标.bat 双击运行 打开方式 2 win R 输入cmd 打开终端 输入以上代码

微信小程序通过npm引入tdesign包进行构建的时候报错

问题 在通过npm 引入 tdesign时:https://tdesign.tencent.com/miniprogram/getting-started 通过微信小程序IDE进行npm构建的时候出现:无法构建,应该怎么办? 解决方法: 1 输入: npm init -y命令 2 重新点…

基于Vue3+ts+Pinia的后台管理系统

Vue3tsPinia管理系统 项目介绍项目简介界面展示登录界面商品界面用户界面角色管理界面 接口文档项目地址 项目介绍 包含对商品、订单、用户增删改查等后台的管理业务,并提供数据可视化的报表功能的管理系统。界面进行了高级封装,可以通过引入组件传入配…

WSL中为Ubuntu和Debian设置固定IP的终极指南

文章目录 **WSL中为Ubuntu和Debian设置固定IP的终极指南****引言/背景****1. 传统方法****2. 新方法:添加指定IP而不是更改IP****结论**WSL中为Ubuntu和Debian设置固定IP的终极指南 引言/背景 随着WSL(Windows Subsystem for Linux)的普及,越来越多的开发者开始在Windows…

创建性-构造者设计模式

前言 我们在使用Retrofit等这些第三方框架的时候,发现他们的使用都很方便,比如Retrofit retrofit new Retrofit.Builder().build(),和我们通常直接new一个对象不同,他是交给Builder类,通过build()函数来构造一个Retro…

人工智能论文通用创新点(一)——ACMIX 卷积与注意力融合、GCnet(全局特征融合)、Coordinate_attention、SPD(可替换下采样)

1.ACMIX 卷积与注意力融合 论文地址:https://arxiv.org/pdf/2111.14556.pdf 为了实现卷积与注意力的融合,我们让特征图经过两个路径,一个路径经过卷积,另外一个路径经过Transformer,但是,现在有一个问题,卷积路径比较快,Transformer比较慢。因此,我们让Q,K,V通过1*1的…

es5的实例__proto__(原型链) prototype(原型对象) {constructor:构造函数}

现在看这张图开始变得云里雾里,所以简单回顾一下 prototype 的基本内容,能够基本读懂这张图的脉络。 先介绍一个基本概念: function Person() {}Person.prototype.name KK;let person1 new Person();在上面的例子中, Person …