本文章纯属记录学习使用 我也不太明白是否为小目标检测层 不对的地方还希望一块交流

 yolov5初始模型在特征融合时只对P3、P4、P5、三个特征层进行了融合 添加小目标检测层的目的是把P2 也就是yaml文件中第二个conv层得到的特征图 也加入到特征融合中。

P2位于低特征层 具有较强的位置信息 语义特征信息较弱 常用来进行小目标检测 这篇博客我觉得写的很好     高低特征层。

但并不是你觉得你所要检测的是小目标 就需要加入小目标检测层 当添加小目标检测层有时会适得其反 并不会有所改进。看论文对于小目标的定义为 小于32*32像素的目标为小目标。

yaml能跑通但是有些不合理 等有时间会修改

添加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, dtype torch.float32), requires_grad True)
 self.epsilon 0.0001
 self.conv nn.Conv2d(c1, c2, kernel_size 1, stride 1, padding 0)
 self.silu nn.SiLU()
 def forward(self, x):
 w self.w
 weight w / (torch.sum(w, dim 0) self.epsilon)
 return self.conv(self.silu(weight[0] * x[0] weight[1] * x[1]))

super(BiFPN_Add3, self).__init__() self.w nn.Parameter(torch.ones(3, dtype torch.float32), requires_grad True) self.epsilon 0.0001 self.conv nn.Conv2d(c1, c2, kernel_size 1, stride 1, padding 0) self.silu nn.SiLU() def forward(self, x): w self.w weight w / (torch.sum(w, dim 0) self.epsilon) # Fast normalized fusion return self.conv(self.silu(weight[0] * x[0] weight[1] * x[1] weight[2] * x[2]))

第二步 修改 yolo.py 

 elif m in [BiFPN_Add2, BiFPN_Add3]:
 c2 max([ch[x] for x in f])

 

第三步 修改 train.py

看下边

  该部分代码还请去看迪导博客 他提供很多改进方法 值得学习 强烈推荐

Yolov5如何更换BiFPN?

6.2版本的train.py代码有些变化 需要进入smart_optomizer这个函数中加入train.py这部分代码

6.2版本会出现报错 后续会解决

2023.3.6 最近在忙并没进行解决 报错的原因大概就是执行顺序的问题

解决思路:把smart_optimizer复制到train.py里 然后加上面红框的代码就可以 如果还报错请留言我再解决

2023.3.13 解决报错

只需要把smart_optimizer这个函数放在train.py就行 位置随便

 # BiFPN_Concat
 elif isinstance(v, BiFPN_Add2) and hasattr(v, w ) and isinstance(v.w, nn.Parameter):
 g[1].append(v.w)
 elif isinstance(v, BiFPN_Add3) and hasattr(v, w ) and isinstance(v.w, nn.Parameter):
 g[1].append(v.w)

 导入BiFPN_Add2 BiFPN_Add3

from models.common import BiFPN_Add3, BiFPN_Add2

记得要把这个删除 不然会报错

 运行成功


 

接下来便是修改后的yaml文件

# Parameters
nc: 1 # number of classes
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
anchors: 3 # AutoAnchor evolves 3 anchors per P output layer
# YOLOv5 v6.0 backbone
# Adding connection in architecture between backbone and multi-stage head
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.0 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 (P3/8-small)
 [-1, 1, Conv, [128, 1, 1]],
 [-1, 1, nn.Upsample, [None, 2, nearest ]],
 [[-1, 2], 1, BiFPN_Add2, [64,64]], # cat backbone P2
 [-1, 3, C3, [128, False]], # 21 (P2/4-tiny)
 [-1, 1, Conv, [256, 3, 2]],
 [[-1, 17, 4], 1, BiFPN_Add3, [128,128]],
 [-1, 3, C3, [256, False]], # 24 (P4/16-medium)
 [-1, 1, Conv, [512, 3, 2]],
 [[-1, 13, 6], 1, BiFPN_Add3, [256,256]],
 [-1, 3, C3, [512, False]], # 27 (P4/16-medium)
 [-1, 1, Conv, [512, 3, 2]],
 [[-1, 10], 1, BiFPN_Add2, [256,256]],
 [-1, 3, C3, [1024, False]], # 30 (P5/32-large)
 [[21, 24, 27, 30], 1, Detect, [nc, anchors]], # Detect(P2, P3, P4, P5)
 ]

经过修改后的四检测头结合BiFPN 若有错误还请大佬指点一下

# YOLOv5 by Ultralytics, GPL-3.0 license
# Parameters (P2, P3, P4, P5)都输出 宽深与large版本相同 相当于比large版本能检测更小物体
nc: 1 # number of classes
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
anchors: 4 # AutoAnchor evolves 3 anchors per P output layer
# 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.0 head with (P2, P3, P4, P5) outputs
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 (P3/8-small)
 [-1, 1, Conv, [128, 1, 1]],
 [-1, 1, nn.Upsample, [None, 2, nearest ]],
 [[-1, 2], 1, BiFPN_Add2, [64,64]], # cat backbone P2
 [-1, 1, C3, [128, False]], # 21 (P2/4-xsmall)
 [-1, 1, Conv, [128, 3, 2]],
 [-1, 1, Conv, [256, 1, 1]],
 [[-1, 17, 4], 1, BiFPN_Add3, [128,128]], # cat head P3
 [-1, 3, C3, [256, False]], # 25 (P3/8-small)
 [-1, 1, Conv, [256, 3, 2]],
 [-1, 1, Conv, [512, 1, 1]],
 [[-1, 13, 6], 1, BiFPN_Add3, [256,256]], # cat head P4
 [-1, 3, C3, [512, False]], # 29 (P4/16-medium)
 [-1, 1, Conv, [512, 3, 2]],
 [[-1, 10], 1, BiFPN_Add2, [256,256]], # cat head P5
 [-1, 3, C3, [1024, False]], # 32 (P5/32-large)
 [[21, 25, 29, 32], 1, Detect, [nc, anchors]], # Detect(P2, P3, P4, P5)

题外话

这个博客中的BiFPN代码有两个版本 个人感觉第二个版本更合理些 因为不会出现我用1*1conv更换通道使得BiFPN_Add3结合成功 可以尝试下


抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

更多文章请关注《万象专栏》