YOLOv5改进之BiFPN(含代码,超详细哦)

张开发
2026/4/11 23:26:54 15 分钟阅读

分享文章

YOLOv5改进之BiFPN(含代码,超详细哦)
有问题的看下面这篇文章点击即可跳转YOLOv5改进 | Neck | 添加双向特征金字塔BiFPN【小白轻松上手 | 论文必备】专栏目录《YOLOv5入门 改进涨点》专栏介绍 专栏目录 |目前已有40篇内容内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进BiFPN论文论文地址[1911.09070] EfficientDet: Scalable and Efficient Object Detection (arxiv.org)BiFPN简介BiFPN即“双向特征金字塔网络”是一种常用于计算机视觉任务特别是目标检测和实例分割的神经网络架构。它扩展了特征金字塔网络FPN通过在金字塔级别之间引入双向连接使信息能够在网络中同时进行自底向上和自顶向下的流动。以下是BiFPN的工作原理概述1. 特征金字塔生成最初网络通过从骨干网络通常是ResNet等卷积神经网络的多个层中提取特征来生成特征金字塔。2. 双向连接与传统FPN不同BiFPN在特征金字塔相邻级别之间引入了双向连接。这意味着信息可以从更高级别的特征流向更低级别的特征自顶向下路径也可以从更低级别的特征流向更高级别的特征自底向上路径。3. 特征整合双向连接允许在两个方向上整合来自特征金字塔不同级别的信息。这种整合有助于有效地捕获多尺度特征。4. 加权特征融合BiFPN采用加权特征融合机制将不同级别的特征进行组合。融合的权重在训练过程中学习确保了最佳的特征整合。BiFPN中的双向连接有助于更好地在不同尺度上捕获特征表示提高了网络处理不同尺寸和复杂度对象的能力。这在目标检测任务中尤为重要因为图像中的对象大小可能差异显著。研究表明BiFPN可以提高模型的效率和性能特别是对于目标检测、实例分割和其他相关计算机视觉任务。BiFPN结构图添加代码在common.py中添加BiFPN模块将下面BiFPN模块的代码复制粘贴到common.py文件的末尾。# 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, dtypetorch.float32), requires_gradTrue) self.epsilon 0.0001 self.conv nn.Conv2d(c1, c2, kernel_size1, stride1, padding0) self.silu nn.SiLU() def forward(self, x): w self.w weight w / (torch.sum(w, dim0) 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, dtypetorch.float32), requires_gradTrue) self.epsilon 0.0001 self.conv nn.Conv2d(c1, c2, kernel_size1, stride1, padding0) self.silu nn.SiLU() def forward(self, x): w self.w weight w / (torch.sum(w, dim0) self.epsilon) # Fast normalized fusion return self.conv(self.silu(weight[0] * x[0] weight[1] * x[1] weight[2] * x[2]))步骤2在yolo.py文件中加入类名在yolo.py文件的parse_model函数中找到elif m is Conat: 语句在其后面加上下列语句# 添加bifpn_add结构 elif m in [BiFPN_Add2, BiFPN_Add3]: c2 max([ch[x] for x in f])步骤3创建自定义yaml文件然后将yaml文件中所有Concat换成BiFPN_Add。yaml文件修改后的完整代码如下# YOLOv5 by Ultralytics, GPL-3.0 license # Parameters nc: 80 # 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) ]步骤4验证是否加入成功在yolo.py文件里配置我们刚才自定义的yolov5s_BiFPN.yaml然后运行yolo.py得到结果。由运行结果可以看到所有Concat已被换成了BiFPN_Add。这样就算添加成功了。步骤5修改train.py首先找到train.py文件中的#Optimizer加入下列代码g0, g1, g2 [], [], [] # optimizer parameter groups for v in model.modules(): if hasattr(v, bias) and isinstance(v.bias, nn.Parameter): # bias g2.append(v.bias) if isinstance(v, nn.BatchNorm2d): # weight (no decay) g0.append(v.weight) elif hasattr(v, weight) and isinstance(v.weight, nn.Parameter): # weight (with decay) g1.append(v.weight) # BiFPN_Concat elif isinstance(v, BiFPN_Add2) and hasattr(v, w) and isinstance(v.w, nn.Parameter): g1.append(v.w) elif isinstance(v, BiFPN_Add3) and hasattr(v, w) and isinstance(v.w, nn.Parameter): g1.append(v.w)此时会出现报错提示原因是我们没有导入相应的包。接下来我们就导入相应的包。导入完毕后我们可以看到报错消失了然后在train.py文件中找到parse_opt函数然后将第二行--cfg的default改为models/yolov5s_BiFPN.yaml然后就可以开始进行训练了。快去运行吧

更多文章