YOLOv5改进(二)BiFPN替换Neck网络

2024-05-09 04:20

本文主要是介绍YOLOv5改进(二)BiFPN替换Neck网络,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

针对红绿灯轻量化检测,上一节使用MobileNetv3替换了主干网络,本篇将在使用BiFPN替换Neck的方式优化算法~

往期回顾

YOLOv5改进(一)MobileNetv3替换主干网络

目录

  • 一、BiFPN简介
  • 二、改进方法一
    • 第一步:在common.py中添加BiFPN模块
    • 第二步:在yolo.py中的parse_model函数加入类名
    • 第三步:制作模型配置文件
    • 第四步:验证新加入的BiFPN
    • 第五步:修改train.py中的cfg参数
    • 第六步:运行 python train.py
  • 三、改进方法二
    • 第一步:在common.py中添加BiFPN模块
    • 第二步:在yolo.py中的parse_model函数加入类名
    • 第三步:制作模型配置文件
    • 第四步:验证新加入的BiFPN
    • 第五步:修改train.py中的cfg参数
    • 第六步:运行 python train.py

一、BiFPN简介

BiFPN即“双向特征金字塔网络”,常用于目标检测和实例分割的神经网络架构。EfficientDet是以EfficientNet模型和双向特征加权金字塔网络BiFPN为基础,于2020年创新推出的新一代目标检测模型。

论文题目:《EfficientDet: Scalable and Efficient Object Detection》(《EfficientDet:可扩展且高效的目标检测》)
原文地址:EfficientDet: Scalable and Efficient Object Detection
论文提供代码地址:https://github.com/google/automl/tree/master/efficientdet
第三方提供代码地址:https://github.com/jewelc92/mmdetection/blob/3.x/projects/EfficientDet/efficientdet/bifpn.py

二、改进方法一

第一步:在common.py中添加BiFPN模块

代码如下:

# BiFPN 
# 两个特征图add操作
class BiFPN_Add2(nn.Module):def __init__(self, c1, c2):super(BiFPN_Add2, self).__init__()# 设置可学习参数 nn.Parameter的作用是:将一个不可训练的类型Tensor转换成可以训练的类型parameter# 并且会向宿主模型注册该参数 成为其一部分 即model.parameters()会包含这个parameter# 从而在参数优化的时候可以自动一起优化self.w = nn.Parameter(torch.ones(2, dtype=torch.float32), requires_grad=True)self.epsilon = 0.0001self.conv = nn.Conv2d(c1, c2, kernel_size=1, stride=1, padding=0)self.silu = nn.SiLU()def forward(self, x):w = self.wweight = w / (torch.sum(w, dim=0) + self.epsilon)return self.conv(self.silu(weight[0] * x[0] + weight[1] * x[1]))# 三个特征图add操作
class BiFPN_Add3(nn.Module):def __init__(self, c1, c2):super(BiFPN_Add3, self).__init__()self.w = nn.Parameter(torch.ones(3, dtype=torch.float32), requires_grad=True)self.epsilon = 0.0001self.conv = nn.Conv2d(c1, c2, kernel_size=1, stride=1, padding=0)self.silu = nn.SiLU()def forward(self, x):w = self.wweight = w / (torch.sum(w, dim=0) + self.epsilon)  # Fast normalized fusionreturn self.conv(self.silu(weight[0] * x[0] + weight[1] * x[1] + weight[2] * x[2]))

效果如下:
在这里插入图片描述

第二步:在yolo.py中的parse_model函数加入类名

添加内容如下:

# 添加bifpn_add结构
elif m in [BiFPN_Add2, BiFPN_Add3]:c2 = max([ch[x] for x in f])

效果如下:
在这里插入图片描述

第三步:制作模型配置文件

复制yolov5s.yaml文件,重命名为yolov5s_BiFPN.yaml,代码如下:

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license# Parameters
nc: 12  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # 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, Conv, [64, 6, 2, 2]],  # 0-P1/2[-1, 1, Conv, [128, 3, 2]],  # 1-P2/4[-1, 3, C3, [128]],[-1, 1, Conv, [256, 3, 2]],  # 3-P3/8[-1, 6, C3, [256]],[-1, 1, Conv, [512, 3, 2]],  # 5-P4/16[-1, 9, C3, [512]],[-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32[-1, 3, C3, [1024]],[-1, 1, SPPF, [1024, 5]],  # 9]# YOLOv5 v6.1 BiFPN head
head:[[-1, 1, Conv, [512, 1, 1]],[-1, 1, nn.Upsample, [None, 2, 'nearest']],[[-1, 6], 1, BiFPN_Add2, [256, 256]],  # cat backbone P4[-1, 3, C3, [512, False]],  # 13[-1, 1, Conv, [256, 1, 1]],[-1, 1, nn.Upsample, [None, 2, 'nearest']],[[-1, 4], 1, BiFPN_Add2, [128, 128]],  # cat backbone P3[-1, 3, C3, [256, False]],  # 17 [-1, 1, Conv, [512, 3, 2]],  [[-1, 13, 6], 1, BiFPN_Add3, [256, 256]],  #v5s通道数是默认参数的一半[-1, 3, C3, [512, False]],  # 20 [-1, 1, Conv, [512, 3, 2]],[[-1, 10], 1, BiFPN_Add2, [256, 256]],  # cat head P5[-1, 3, C3, [1024, False]],  # 23 [[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)]

第四步:验证新加入的BiFPN

运行yolo.py:

在这里插入图片描述
可以看到所有的Concat被换成了BiFPN_Add

第五步:修改train.py中的cfg参数

将模型配置文件修改为yolov5s_BiFPN.yaml

在这里插入图片描述

第六步:运行 python train.py

开始训练:

在这里插入图片描述
训练结束后结果保存到run/train文件夹下~

结果对比:
在这里插入图片描述

可以看到更换BiFPN之后的性能有所下降!

好了,到这里关于YOLOv5中第一种BiFPN替换Neck的改进就完成了!

三、改进方法二

第一步:在common.py中添加BiFPN模块

添加代码如下:

# 结合BiFPN 设置可学习参数 学习不同分支的权重
# 两个分支concat操作
class BiFPN_Concat2(nn.Module):def __init__(self, dimension=1):super(BiFPN_Concat2, self).__init__()self.d = dimensionself.w = nn.Parameter(torch.ones(2, dtype=torch.float32), requires_grad=True)self.epsilon = 0.0001def forward(self, x):w = self.wweight = w / (torch.sum(w, dim=0) + self.epsilon)  # 将权重进行归一化# Fast normalized fusionx = [weight[0] * x[0], weight[1] * x[1]]return torch.cat(x, self.d)# 三个分支concat操作
class BiFPN_Concat3(nn.Module):def __init__(self, dimension=1):super(BiFPN_Concat3, self).__init__()self.d = dimension# 设置可学习参数 nn.Parameter的作用是:将一个不可训练的类型Tensor转换成可以训练的类型parameter# 并且会向宿主模型注册该参数 成为其一部分 即model.parameters()会包含这个parameter# 从而在参数优化的时候可以自动一起优化self.w = nn.Parameter(torch.ones(3, dtype=torch.float32), requires_grad=True)self.epsilon = 0.0001def forward(self, x):w = self.wweight = w / (torch.sum(w, dim=0) + self.epsilon)  # 将权重进行归一化# Fast normalized fusionx = [weight[0] * x[0], weight[1] * x[1], weight[2] * x[2]]return torch.cat(x, self.d)

效果如下:

在这里插入图片描述

第二步:在yolo.py中的parse_model函数加入类名

添加以下代码:

# 添加bifpn_concat结构
elif m in [Concat, BiFPN_Concat2, BiFPN_Concat3]:c2 = sum(ch[x] for x in f)

效果如下:

在这里插入图片描述

第三步:制作模型配置文件

复制yolov5s.yaml重命名为yolov5s-BiFPN1.yaml,内容如下:

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license# Parameters
nc: 12  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # 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, Conv, [64, 6, 2, 2]],  # 0-P1/2[-1, 1, Conv, [128, 3, 2]],  # 1-P2/4[-1, 3, C3, [128]],[-1, 1, Conv, [256, 3, 2]],  # 3-P3/8[-1, 6, C3, [256]],[-1, 1, Conv, [512, 3, 2]],  # 5-P4/16[-1, 9, C3, [512]],[-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32[-1, 3, C3, [1024]],[-1, 1, SPPF, [1024, 5]],  # 9]# YOLOv5 v6.1 BiFPN head
head:[[-1, 1, Conv, [512, 1, 1]],[-1, 1, nn.Upsample, [None, 2, 'nearest']],[[-1, 6], 1, BiFPN_Concat2, [1]],  # cat backbone P4 <--- BiFPN change[-1, 3, C3, [512, False]],  # 13[-1, 1, Conv, [256, 1, 1]],[-1, 1, nn.Upsample, [None, 2, 'nearest']],[[-1, 4], 1, BiFPN_Concat2, [1]],  # cat backbone P3 <--- BiFPN change[-1, 3, C3, [256, False]],  # 17 (P3/8-small)[-1, 1, Conv, [256, 3, 2]],[[-1, 14, 6], 1, BiFPN_Concat3, [1]],  # cat P4 <--- BiFPN change[-1, 3, C3, [512, False]],  # 20 (P4/16-medium)[-1, 1, Conv, [512, 3, 2]],[[-1, 10], 1, BiFPN_Concat2, [1]],  # cat head P5 <--- BiFPN change[-1, 3, C3, [1024, False]],  # 23 (P5/32-large)[[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)]

第四步:验证新加入的BiFPN

运行models/yolo.py

在这里插入图片描述

第五步:修改train.py中的cfg参数

跟上面步骤一样,将模型配置文件修改为yolov5s_BiFPN1.yaml

第六步:运行 python train.py

开始训练:

在这里插入图片描述

训练结束后结果保存到run/train文件夹下~

结果对比:
在这里插入图片描述

可以看到更换BiFPN之后的前30轮均有所提升,后70轮基本相平!

好了,到这里关于YOLOv5中第二种BiFPN替换Neck的改进就完成了!

这篇关于YOLOv5改进(二)BiFPN替换Neck网络的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/972376

相关文章

Python正则表达式匹配和替换的操作指南

《Python正则表达式匹配和替换的操作指南》正则表达式是处理文本的强大工具,Python通过re模块提供了完整的正则表达式功能,本文将通过代码示例详细介绍Python中的正则匹配和替换操作,需要的朋... 目录基础语法导入re模块基本元字符常用匹配方法1. re.match() - 从字符串开头匹配2.

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja

Debian 13升级后网络转发等功能异常怎么办? 并非错误而是管理机制变更

《Debian13升级后网络转发等功能异常怎么办?并非错误而是管理机制变更》很多朋友反馈,更新到Debian13后网络转发等功能异常,这并非BUG而是Debian13Trixie调整... 日前 Debian 13 Trixie 发布后已经有众多网友升级到新版本,只不过升级后发现某些功能存在异常,例如网络转

C#高效实现Word文档内容查找与替换的6种方法

《C#高效实现Word文档内容查找与替换的6种方法》在日常文档处理工作中,尤其是面对大型Word文档时,手动查找、替换文本往往既耗时又容易出错,本文整理了C#查找与替换Word内容的6种方法,大家可以... 目录环境准备方法一:查找文本并替换为新文本方法二:使用正则表达式查找并替换文本方法三:将文本替换为图

Python批量替换多个Word文档的多个关键字的方法

《Python批量替换多个Word文档的多个关键字的方法》有时,我们手头上有多个Excel或者Word文件,但是领导突然要求对某几个术语进行批量的修改,你是不是有要崩溃的感觉,所以本文给大家介绍了Py... 目录工具准备先梳理一下思路神奇代码来啦!代码详解激动人心的测试结语嘿,各位小伙伴们,大家好!有没有想

Python开发简易网络服务器的示例详解(新手入门)

《Python开发简易网络服务器的示例详解(新手入门)》网络服务器是互联网基础设施的核心组件,它本质上是一个持续运行的程序,负责监听特定端口,本文将使用Python开发一个简单的网络服务器,感兴趣的小... 目录网络服务器基础概念python内置服务器模块1. HTTP服务器模块2. Socket服务器模块

Go语言网络故障诊断与调试技巧

《Go语言网络故障诊断与调试技巧》在分布式系统和微服务架构的浪潮中,网络编程成为系统性能和可靠性的核心支柱,从高并发的API服务到实时通信应用,网络的稳定性直接影响用户体验,本文面向熟悉Go基本语法和... 目录1. 引言2. Go 语言网络编程的优势与特色2.1 简洁高效的标准库2.2 强大的并发模型2.

linux批量替换文件内容的实现方式

《linux批量替换文件内容的实现方式》本文总结了Linux中批量替换文件内容的几种方法,包括使用sed替换文件夹内所有文件、单个文件内容及逐行字符串,强调使用反引号和绝对路径,并分享个人经验供参考... 目录一、linux批量替换文件内容 二、替换文件内所有匹配的字符串 三、替换每一行中全部str1为st

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

Python如何判断字符串中是否包含特殊字符并替换

《Python如何判断字符串中是否包含特殊字符并替换》这篇文章主要为大家详细介绍了如何使用Python实现判断字符串中是否包含特殊字符并使用空字符串替换掉,文中的示例代码讲解详细,感兴趣的小伙伴可以了... 目录python判断字符串中是否包含特殊字符方法一:使用正则表达式方法二:手动检查特定字符Pytho