当前位置: 代码网 > it编程>前端脚本>Python > yoloV5更换BiFPN结合小目标检测层

yoloV5更换BiFPN结合小目标检测层

2024年07月31日 Python 我要评论
小目标检测层结合BiFPN

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

 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]))


# 三个特征图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.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结合成功,可以尝试下

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com