yolov5 引入RepVGG模型结构

news2024/11/27 2:25:20

(一)前情

这个工作已经有大佬用在自己的工程里了,他的帖子链接:https://blog.csdn.net/weixin_45829462/article/details/120372921
但他的这个lite主要不是研究repvgg的,是做移动端的,但是里面加了这个repvgg
他的代码链接:https://github.com/ppogg/YOLOv5-Lite/tree/ca7ed7ca0bb578fe6e5eaa777e84f661ad457e49
我是看了看他的代码,然后把关于repvgg的地方加到了自己的yolov5-7.0中(但后续我没用seg去做训练,就正常训练)
后续我还试着把rep-vgg官方的预训练模型的backbone移植到了自己的yolov5-repvgg训练了50epoch的pt中,效果不好。

理论知识:
我先看了个原作者写的帖子:结构重参数化:利用参数转换解耦训练和推理结构,大致看了看
后来去看了原作者的一个视频:丁霄汉:结构重参数化是怎么来的【深度学习】【直播回放】
主要是讲作者写这个的一个思路,和为什么写这个,有助于理解
又看了个我比较喜欢的up主的讲解:RepVGG网络讲解
还有他的csdn:RepVGG网络简介

(二)YOLOv5改进之结合​RepVGG

1.配置common.py文件

# build repvgg block
# -----------------------------
def conv_bn(in_channels, out_channels, kernel_size, stride, padding, groups=1):
    result = nn.Sequential()
    result.add_module('conv', nn.Conv2d(in_channels=in_channels, out_channels=out_channels,
                                        kernel_size=kernel_size, stride=stride, padding=padding, groups=groups,
                                        bias=False))
    result.add_module('bn', nn.BatchNorm2d(num_features=out_channels))

    return result
    
#RepVGGBlock
class RepVGGBlock(nn.Module):
 
    def __init__(self, in_channels, out_channels, kernel_size=3,
                 stride=1, padding=1, dilation=1, groups=1, padding_mode='zeros', deploy=False, use_se=False):
        super(RepVGGBlock, self).__init__()
        self.deploy = deploy
        self.groups = groups
        self.in_channels = in_channels
 
        padding_11 = padding - kernel_size // 2
 
        self.nonlinearity = nn.SiLU()
 
        # self.nonlinearity = nn.ReLU()
 
        if use_se:
            self.se = SEBlock(out_channels, internal_neurons=out_channels // 16)
        else:
            self.se = nn.Identity()
 
        if deploy:
            self.rbr_reparam = nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size,
                                         stride=stride,
                                         padding=padding, dilation=dilation, groups=groups, bias=True,
                                         padding_mode=padding_mode)
 
        else:
            self.rbr_identity = nn.BatchNorm2d(
                num_features=in_channels) if out_channels == in_channels and stride == 1 else None
            self.rbr_dense = conv_bn(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size,
                                     stride=stride, padding=padding, groups=groups)
            self.rbr_1x1 = conv_bn(in_channels=in_channels, out_channels=out_channels, kernel_size=1, stride=stride,
                                   padding=padding_11, groups=groups)
            # print('RepVGG Block, identity = ', self.rbr_identity)
 
    def get_equivalent_kernel_bias(self):
        kernel3x3, bias3x3 = self._fuse_bn_tensor(self.rbr_dense)
        kernel1x1, bias1x1 = self._fuse_bn_tensor(self.rbr_1x1)
        kernelid, biasid = self._fuse_bn_tensor(self.rbr_identity)
        return kernel3x3 + self._pad_1x1_to_3x3_tensor(kernel1x1) + kernelid, bias3x3 + bias1x1 + biasid
 
    def _pad_1x1_to_3x3_tensor(self, kernel1x1):
        if kernel1x1 is None:
            return 0
        else:
            return torch.nn.functional.pad(kernel1x1, [1, 1, 1, 1])
 
    def _fuse_bn_tensor(self, branch):
        if branch is None:
            return 0, 0
        if isinstance(branch, nn.Sequential):
            kernel = branch.conv.weight
            running_mean = branch.bn.running_mean
            running_var = branch.bn.running_var
            gamma = branch.bn.weight
            beta = branch.bn.bias
            eps = branch.bn.eps
        else:
            assert isinstance(branch, nn.BatchNorm2d)
            if not hasattr(self, 'id_tensor'):
                input_dim = self.in_channels // self.groups
                kernel_value = np.zeros((self.in_channels, input_dim, 3, 3), dtype=np.float32)
                for i in range(self.in_channels):
                    kernel_value[i, i % input_dim, 1, 1] = 1
                self.id_tensor = torch.from_numpy(kernel_value).to(branch.weight.device)
            kernel = self.id_tensor
            running_mean = branch.running_mean
            running_var = branch.running_var
            gamma = branch.weight
            beta = branch.bias
            eps = branch.eps
        std = (running_var + eps).sqrt()
        t = (gamma / std).reshape(-1, 1, 1, 1)
        return kernel * t, beta - running_mean * gamma / std
 
    def forward(self, inputs):
        if hasattr(self, 'rbr_reparam'):
            return self.nonlinearity(self.se(self.rbr_reparam(inputs)))
 
        if self.rbr_identity is None:
            id_out = 0
        else:
            id_out = self.rbr_identity(inputs)
 
        return self.nonlinearity(self.se(self.rbr_dense(inputs) + self.rbr_1x1(inputs) + id_out))
 
    def fusevggforward(self, x):
        return self.nonlinearity(self.rbr_dense(x))

我看网上有些帖子的代码,加到自己工程里有问题,是因为缺conv_bv代码块。自己加上就行了,我这个上面是加进去的。

2.配置yolo.py文件

加入这里

3.配置yolov5_​​RepVGG.yaml文件

我新建了一个yolov5s-repvgg.yaml

# YOLOv5 馃殌 by Ultralytics, GPL-3.0 license

# Parameters
nc: 4  # number of classes
depth_multiple: 1  # model depth multiple
width_multiple: 1  # 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, RepVGGBlock, [64, 3, 2]],  # 0-P1/2
   [-1, 1, RepVGGBlock, [64, 3, 2]], # 1-P2/4
   [-1, 1, RepVGGBlock, [64, 3, 1]], # 2-P2/4
   [-1, 1, RepVGGBlock, [128, 3, 2]], # 3-P3/8
   [-1, 3, RepVGGBlock, [128, 3, 1]],
   [-1, 1, RepVGGBlock, [256, 3, 2]], # 5-P4/16
   [-1, 13, RepVGGBlock, [256, 3, 1]],
   [-1, 1, RepVGGBlock, [512, 3, 2]], # 7-P4/16
  ]
# YOLOv5 head
head:
  [[-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P4
   [-1, 1, C3, [256, False]],  # 11
 
   [-1, 1, Conv, [128, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 4], 1, Concat, [1]],  # cat backbone P3
   [-1, 1, C3, [128, False]],  # 15 (P3/8-small)
 
   [-1, 1, Conv, [128, 3, 2]],
   [[-1, 12], 1, Concat, [1]],  # cat head P4
   [-1, 1, C3, [256, False]],  # 18 (P4/16-medium)
 
   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 8], 1, Concat, [1]],  # cat head P5
   [-1, 1, C3, [512, False]],  # 21 (P5/32-large)
 
   [[15, 18, 21], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

至于number那里为什么是1,1,1,1,3,1,13,1
depth_multiple: 1 # model depth multiple
width_multiple: 1 # layer channel multiple

是为了和repvgg原网络的A1结构保持一致,方便后续做一个预训练模型的迁移

训练结果

开始训练

python train.py --weights ./weights/yolov5s.pt --data ./data/coco-repvgg.yaml --epochs 50 --img 640 --cfg models/yolov5s-repvgg.yaml --name yolov5s-repvgg

这里加不加预训练都行,但是我的实验结果发现,加了预训练模型,会导致训练50epoch,没有原来的yolov5s训练50epoch以后的结果好。

但是yolov5s与改进的yolov5-repvgg俩模型,都不加预训练模型,一起训50,yolov5-repvgg的效果是要更好的!也就是很有效其实。
这是我的结果
后面迁移repvgg预训练模型的代码,后续也会发出来。

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

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

相关文章

【BP靶场portswigger-服务端8】文件上传漏洞-7个实验(全)

前言: 介绍: 博主:网络安全领域狂热爱好者(承诺在CSDN永久无偿分享文章)。 殊荣:CSDN网络安全领域优质创作者,2022年双十一业务安全保卫战-某厂第一名,某厂特邀数字业务安全研究员&…

Linux应用编程---13.网络编程

Linux应用编程—13.网络编程 ​ 网络编程要熟悉一些计算机网络有关的名词,可以先做了解,后续实际开发在深入研究,自上而下学习。与本次Linux应用编程有关的就是TCP与UDP协议。简明概念如下图1所示。 图1 计算机网络体系结构 ​ 前面学习的进…

数控机床各种加工模式以及英文简写

AUTO(自动模式) 机床自动运行加工程序,对零件进行加工。前提是所编的程序经过试验后是可行的,而且是加工出来的件经过检验后是合格的,才可以使用该程序。 EDIT(编辑模式) 在此模式下&#xff…

Spring Boot集成第三方登录之微博登录

准备工作 微博开放平台:https://open.weibo.com/ 网站接入 登陆微博开放平台,进入微连接,选择网站接入 点击立即接入 开发者信息认证 填写开发者信息与身份认证信息 创建应用 开发者信息认证通过后即可创建应用。 应用创建成功后会得到app …

哪种台灯质量好又实惠?性价比最高的护眼台灯

l 只要台灯质量过关就是及格的第一步,首先就是有3C质量认证,符合国A或国AA照度标准。l 显色也会是很重要的,光源品质高的产品,显色性不会低于Ra90的,太阳光的显色指数=100,那么意味着显色指数越…

一文详解Paramiko安装与使用

项目要求 定期向特定服务器传输软件运行状况文件(基于SFTP),因此计划写一个Python脚本,该脚本首先要定期读取产品运营数据,然后按要求生成数据文件,最后通过 Paramiko 上传到SFTP服务器。 这篇文章是我在实…

【Spring源码】19. 没合适的构造器?找determineCandidateConstructors()!

上篇介绍了instantiateBean()(其实这个方法在后面还会再次被调用)如果在前两篇的内容结束后都还未获取到构造函数,那么则继续向下执行,调用determineConstructorsFromBeanPostProcessors()方法determineConstructorsFromBeanPostP…

如何确定梯度消失/爆炸和解决梯度消失/爆炸

1、梯度消失的原因和表现1.1、梯度消失的原因:在深层网络中,如果激活函数的导数小于1,根据链式求导法则,靠近输入层的参数的梯度因为乘了很多的小于1的数而越来越小,最终就会趋近于0,例如sigmoid函数&#…

【C++常用算法】STL基础语法学习 | 算数生成算法集合算法

目录 ●accumulate ●fill ●set_intersection ●set_union ●set_difference ●accumulate 1.功能描述: 计算容器内元素累计总和 2.查看accumulate定义下底层代码的函数原型: 3.向vector容器中插入0~100,使用accumulate算法去计算其和…

RabbitMQ的五大常用模型介绍以及SpringAMQP的使用

目录MQ的介绍使用MQ的好处技术对比RabbitMQ的使用Docker启动MQ角色介绍五大常用消息模型使用SpringAMQP模板简单队列模型工作队列模型广播模型 Fanout路由模式 Direct主题模式 TopicMQ的介绍 MQ,MessageQuene即 消息队列,是程序与程序之间的异步通信一种…

spring的IOC与DI小案例

注:本博客用于自学,如有错误,敬请指正。 一、首先要了解的概念 IOC是一种思想:将创建、初始化对象的控制权交给IOC容器 IOC容器:用来装对象的容器 Bean:IOC容器中装的对象 DI:将IOC容器种Bean…

打破光缆资源管理难题

如何打破光缆资源管理难题,将光缆资源价值最大化,相信是每个运维人都关心的焦点问题。 一、背景 全业务发展到今天,我们逐渐意识到,市场竞争的核心已聚焦到传输资源。从拼资源总量到拼资源管理,传统的运维管理模式面临…

【每日一题】【LeetCode】【第九天】存在重复元素

解决之路 题目描述 测试案例(部分) 第一次 关键就是看是否有重复元素,暴力解法就是双循环,然后有相同元素就返回True,否则就等循环结束,返回False。 但是自己想到了另一个只需要一个循环的解法。用一个…

C++11 简化 “策略模式” 的一种思路

策略模式是一种定义一系列算法的模式,从概念上看,所有这些算法完成的都是相同接口的工作(只是实现不同),它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法的类之间的耦合。实践中只要在分析过…

开发者工具中performance面板解析

目录总览设置面板网络性能总览图火焰图:耗费的时间相关信息总览 如图,主要分为以下4个方面 设置面板 1, 不刷新页面进行录制 2,刷新页面进行录制 3,删除性能展示页面 4,上传本地的性能页面 5&#xff0c…

若依mybatis升级mybatis-plus,其他也适用

若依mybatis升级mybatis-plus,其他也适用 本文档记录若依mybatis升级plus,其他也类似 文章目录若依mybatis升级mybatis-plus,其他也适用第一步 修改ruoyi-common的pom.xml第二步 修改ruoyi-admin的application.yml第三步 修改ruoyi-framework的MyBatisConfig.java开始测试1. 修…

一、计算机系统概论

文章目录一、计算机系统简介1.计算机软硬件概念2.计算机系统的层次结构(1)现代计算机(2)发展(3)软硬件分布3.计算机组成和计算机体系结构二、计算机的基本组成1.冯诺依曼计算器2.计算机硬件框图3.计算机工作…

android架构拆分方案-编译相关方案与技术

接上文https://blog.csdn.net/dongyi1988/article/details/128617738直接拆分那么在代码和做包过程中,需要用到分仓,super.img、boot、OTA升级包的拆分与组合,vendor与system相关依赖处理,开机验证链还必须给镜像签名。代码管理定…

VisualODX——ODX数据自动转换工具

在创建ODX数据库的过程中,我们需要录入大量的数据以及应对多种数据格式。这不仅费时费力,而且还需要很高的人力成本,并且其错误率也高,从而导致了效率低下、开发速度缓慢。基于多年的汽车行业诊断经验,Softing开发了Vi…

基于微信小程序的课程分享平台小程序

文末联系获取源码 开发语言:Java 框架:ssm JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7/8.0 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven3.3.9 浏览器…