当前位置: 首页 > news >正文

YOLOv10改进 | Neck | 添加双向特征金字塔BiFPN【含二次独家创新】


💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡


专栏目录:《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有40+篇内容,内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进


针对在特征提取过程中,特征信息丢失,特征提取能力不足等问题,研究人员提出了一种加权双向特征金字塔网络(BiFPN),它允许简单快速的多尺度特征融合;可以同时统一缩放所有主干网络、特征网络以及边界框/类别预测网络的分辨率、深度和宽度。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。

 专栏地址YOLOv10入门 + 涨点——持续更新各种涨点方法

目录

1. 原理

2.BiFPN代码实现

2.1 将BiFPN代码添加到YOLOv10种

2.2 更改init.py文件

2.3 添加yaml文件

2.4 在task.py中进行注册

2.5 执行程序

 3. 完整代码分享

4. GFLOPs

5. 进阶

6. 总结


1. 原理

论文地址:EfficientDet: Scalable and Efficient Object Detection——点击即可跳转

官方代码:BiFPN官方代码仓库——点击即可跳转

BIFPN,全称为双向特征金字塔网络(Bidirectional Feature Pyramid Network),是一种用于目标检测和图像分割的神经网络架构。它在EfficientDet和其他一些计算机视觉任务中被广泛使用。BIFPN的设计目标是提高特征融合的效率和效果,使得模型在计算资源有限的情况下仍能保持高性能。以下是对BIFPN的详细讲解:

背景

在计算机视觉任务中,特征金字塔网络(FPN)是一种常用的方法,它通过构建不同尺度的特征图来捕获不同尺度的目标。然而,传统的FPN存在一些缺点,如特征融合效率低、信息流通不充分等。BIFPN则通过引入双向的特征融合机制和加权的特征融合方法来克服这些问题。

核心思想

  1. 双向特征融合: 传统的FPN是单向的,即从高层特征图向低层特征图传递信息。而BIFPN在此基础上增加了反向的信息传递,即从低层特征图向高层特征图传递信息。这种双向的信息流动使得特征图之间的信息融合更加充分。

  2. 加权特征融合: 在BIFPN中,不同尺度的特征图在融合时会分配不同的权重。这些权重是可学习的参数,模型在训练过程中会自动调整它们,以最优地融合不同尺度的特征。这样一来,模型能够更好地利用每个特征图的信息,提高整体的特征表示能力。

结构细节

BIFPN的结构设计非常灵活,可以适应不同的网络架构和任务需求。以下是BIFPN的几个关键组件:

  • 上下文融合层:在上下文融合层中,BIFPN将来自不同尺度的特征图进行融合,采用加权求和的方式。这种加权求和通过学习到的权重来平衡不同特征图的贡献。

  • 重复融合模块:BIFPN中通常会堆叠多个融合模块,这些模块会反复进行特征融合,从而进一步增强特征的表达能力。

  • 尺度变化处理:BIFPN能够处理不同尺度的特征图,并在融合过程中考虑到这些尺度变化。通过上下采样等操作,BIFPN可以有效地处理不同分辨率的特征图。

优势

  1. 高效性:通过加权特征融合和重复融合模块,BIFPN能够在保持高效计算的同时,提升特征表示能力。

  2. 鲁棒性:双向特征融合使得BIFPN对不同尺度目标的检测更加鲁棒,能够更好地应对多尺度问题。

  3. 灵活性:BIFPN可以方便地集成到不同的神经网络架构中,适应不同的任务需求。

应用

BIFPN被广泛应用于各种计算机视觉任务中,尤其是在目标检测和图像分割方面表现出色。比如,在EfficientDet中,BIFPN作为核心组件之一,通过高效的特征融合机制显著提升了模型的检测性能。

总结

BIFPN通过引入双向特征融合和加权特征融合,克服了传统FPN的局限性,提高了特征融合的效率和效果。其灵活高效的设计使其在计算机视觉任务中得到广泛应用,为提升模型性能提供了有力支持。

2.BiFPN代码实现

2.1 将BiFPN代码添加到YOLOv10种

关键步骤一: 将下面代码粘贴到在/ultralytics/ultralytics/nn/modules/block.py中,并在该文件的__all__中添加“Concat_BiFPN” 

class Concat_BiFPN(nn.Module):def __init__(self, dimension=1):super(Concat_BiFPN, self).__init__()self.d = dimensionself.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]]return torch.cat(x, self.d)

BiFPN的主要流程可以分为以下几个步骤:

  1. 特征提取:首先,输入图像经过卷积神经网络(如EfficientNet等)进行特征提取,得到一系列特征图,这些特征图包含了不同层级的语义信息。

  2. 自下而上特征传递:BiFPN从底层开始,利用双线性池化将低分辨率特征图上采样到高分辨率,然后使用双向连接,将上一层的特征图与下一层的上采样特征图进行融合。这种自下而上的特征传递可以帮助从更低层级获取更丰富的信息。

  3. 自上而下特征传递:接着,BiFPN沿着特征金字塔网络的自上而下路径进行特征传递。在这个过程中,BiFPN利用双向连接,将上一层的特征图与下一层的上采样特征图进行融合,以获得更加丰富和准确的特征表征。

  4. 多尺度特征融合:BiFPN在每个层级上都进行多尺度特征融合,将不同分辨率的特征图通过双线性池化进行融合,从而提高特征的表征能力和鲁棒性。

  5. 最终特征输出:最后,BiFPN输出的特征图经过一系列后续处理,如分类器和回归器等,用于目标检测任务中的目标分类和边界框回归等。

通过这样的流程,BiFPN能够充分利用不同层级的特征信息,并通过双向连接和双线性池化等技巧,提高了特征的表征能力和目标检测的性能。

2.2 更改init.py文件

关键步骤二:修改modules文件夹下的__init__.py文件,先导入函数

然后在下面的__all__中声明函数

2.3 添加yaml文件

关键步骤三:在/ultralytics/ultralytics/cfg/models/v10下面新建文件yolov10_BiFPN.yaml文件,粘贴下面的内容

# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, # [depth, width, max_channels]n: [0.33, 0.25, 1024] # YOLOv10n backbone
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, [128, True]]- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8- [-1, 6, C2f, [256, True]]- [-1, 1, SCDown, [512, 3, 2]] # 5-P4/16- [-1, 6, C2f, [512, True]]- [-1, 1, SCDown, [1024, 3, 2]] # 7-P5/32- [-1, 3, C2f, [1024, True]]- [-1, 1, SPPF, [1024, 5]] # 9- [-1, 1, PSA, [1024]] # 10# YOLOv10 head
head:- [-1, 1, nn.Upsample, [None, 2, "nearest"]]- [[-1, 6], 1, Concat, [1]] # cat backbone P4- [-1, 3, C2f, [512]] # 13- [-1, 1, nn.Upsample, [None, 2, "nearest"]]- [[-1, 4], 1, Concat_BiFPN, [1]] # cat backbone P3- [-1, 3, C2f, [256]] # 16 (P3/8-small)- [-1, 1, Conv, [256, 3, 2]]- [[-1, 13], 1, Concat_BiFPN, [1]] # cat head P4- [-1, 3, C2f, [512]] # 19 (P4/16-medium)- [-1, 1, SCDown, [512, 3, 2]]- [[-1, 10], 1, Concat_BiFPN, [1]] # cat head P5- [-1, 3, C2fCIB, [1024, True, True]] # 22 (P5/32-large)- [[16, 19, 22], 1, v10Detect, [nc]] # Detect(P3, P4, P5)

温馨提示:本文只是对yolov10n基础上添加模块,如果要对yolov10n/l/m/x进行添加则只需要指定对应的depth_multiple 和 width_multiple。 


# YOLOv10n
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.25  # layer channel multiple# YOLOv10s
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple# YOLOv10l 
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple# YOLOv10m
depth_multiple: 0.67  # model depth multiple
width_multiple: 0.75  # layer channel multiple# YOLOv10x
depth_multiple: 1.33  # model depth multiple
width_multiple: 1.25  # layer channel multiple

2.4 在task.py中进行注册

关键步骤四:在parse_model函数中进行注册

elif m is Concat_BiFPN:c2 = sum(ch[x] for x in f)

2.5 执行程序

关键步骤五:在ultralytics文件中新建train.py,将model的参数路径设置为yolov10_BiFPN.yaml的路径即可

from ultralytics import YOLOv10# Load a model
# model = YOLO('yolov8n.yaml')  # build a new model from YAML
# model = YOLO('yolov8n.pt')  # load a pretrained model (recommended for training)model = YOLOv10(r'/projects/yolo/yolov10/ultralytics/cfg/models/v10/yolov10_BiFPN.yaml')  # build from YAML and transfer weights# Train the model
model.train(batch=16)

建议大家写绝对路径,确保一定能找到

  🚀运行程序,如果出现下面的内容则说明添加成功🚀

3. 完整代码分享

https://pan.baidu.com/s/1ZDM2aQ55nXx_aFxqPm9Jgg?pwd=z95u

 提取码: z95u 

4. GFLOPs

关于GFLOPs的计算方式可以查看:百面算法工程师 | 卷积基础知识——Convolution

未改进的YOLOv10nGFLOPs

改进后的GFLOPs 

5. 进阶

只需要更换code和ymal文件,其他的步骤相同 

# 结合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)
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, # [depth, width, max_channels]n: [0.33, 0.25, 1024] # YOLOv10n backbone
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, [128, True]]- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8- [-1, 6, C2f, [256, True]]- [-1, 1, SCDown, [512, 3, 2]] # 5-P4/16- [-1, 6, C2f, [512, True]]- [-1, 1, SCDown, [1024, 3, 2]] # 7-P5/32- [-1, 3, C2f, [1024, True]]- [-1, 1, SPPF, [1024, 5]] # 9- [-1, 1, PSA, [1024]] # 10# YOLOv10 head
head:- [-1, 1, nn.Upsample, [None, 2, "nearest"]]- [[-1, 6], 1, Concat, [1]] # cat backbone P4- [-1, 3, C2f, [512]] # 13- [-1, 1, nn.Upsample, [None, 2, "nearest"]]- [[-1, 4], 1, BiFPN_Concat2, [1]] # cat backbone P3- [-1, 3, C2f, [256]] # 16 (P3/8-small)- [-1, 1, Conv, [256, 3, 2]]- [[-1, 13], 1, BiFPN_Concat3, [1]] # cat head P4- [-1, 3, C2f, [512]] # 19 (P4/16-medium)- [-1, 1, SCDown, [512, 3, 2]]- [[-1, 10], 1, BiFPN_Concat2, [1]] # cat head P5- [-1, 3, C2fCIB, [1024, True, True]] # 22 (P5/32-large)- [[16, 19, 22], 1, v10Detect, [nc]] # Detect(P3, P4, P5)

6. 总结

BIFPN(双向特征金字塔网络)通过双向特征融合和加权特征融合的创新设计,显著提升了特征金字塔网络(FPN)的性能。其核心思想是将信息在特征金字塔中双向传递,即从高层特征图向低层特征图传递,同时也从低层特征图向高层特征图传递,确保特征信息的充分融合。同时,BIFPN引入了可学习的加权机制,通过在训练过程中自动调整权重,优化不同尺度特征图的融合效果。这种设计不仅提高了特征表示的能力,还保持了计算的高效性,使其在目标检测和图像分割等计算机视觉任务中表现出色,能够更好地应对多尺度问题和不同任务需求。

相关文章:

  • RK3568技术笔记十四 Ubuntu创建共享文件夹
  • 掌握心理学知识成为产品经理一门必修课?
  • 第一百一十六节 Java 面向对象设计 - Java 终止块
  • MySQL 常用函数总结
  • SAP 新安装的系统,财务开账期OB52需要传输
  • C++的智能指针 RAII
  • 【AI应用探讨】— 盘古大模型应用场景
  • 如何选择合适的半桥栅极驱动芯片?KP8530X,KP85402,KP85211A满足你对半桥栅极驱动一切需求
  • Oracle最终还是杀死了MySQL
  • 步步为营:电商项目业务测试实战指南
  • 考试系统Spring Security的配置
  • SQL题:未完成率较高的50%用户近三个月答卷情况
  • 深入了解常用负载均衡软件
  • 第三方软件测试机构流程分享,软件检测报告需多少时间和费用?
  • 如何利用AI大模型设计电机本体?
  • 【347天】每日项目总结系列085(2018.01.18)
  • HomeBrew常规使用教程
  • in typeof instanceof ===这些运算符有什么作用
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • Magento 1.x 中文订单打印乱码
  • Mybatis初体验
  • mysql 5.6 原生Online DDL解析
  • Objective-C 中关联引用的概念
  • Spark in action on Kubernetes - Playground搭建与架构浅析
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • Webpack 4 学习01(基础配置)
  • 电商搜索引擎的架构设计和性能优化
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 目录与文件属性:编写ls
  • 使用权重正则化较少模型过拟合
  • 微服务入门【系列视频课程】
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 我的zsh配置, 2019最新方案
  • 系统认识JavaScript正则表达式
  • 一份游戏开发学习路线
  • 用jQuery怎么做到前后端分离
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • ​Benvista PhotoZoom Pro 9.0.4新功能介绍
  • #nginx配置案例
  • (2.2w字)前端单元测试之Jest详解篇
  • (33)STM32——485实验笔记
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (附源码)springboot宠物管理系统 毕业设计 121654
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (几何:六边形面积)编写程序,提示用户输入六边形的边长,然后显示它的面积。
  • (三)mysql_MYSQL(三)
  • (生成器)yield与(迭代器)generator
  • **PyTorch月学习计划 - 第一周;第6-7天: 自动梯度(Autograd)**
  • .NET BackgroundWorker
  • .NET C# 操作Neo4j图数据库
  • .NET Project Open Day(2011.11.13)
  • .Net Remoting常用部署结构
  • .net websocket 获取http登录的用户_如何解密浏览器的登录密码?获取浏览器内用户信息?...
  • .NET6 命令行启动及发布单个Exe文件