文章目录
-
- 前言
- 修改common.py
- 修改yolo.py
- yolov5s-bifpn.yaml
- 测试结果
- Concat全部换成BiFPN_Concat
- References
前言 在之前的这篇博客中,简要介绍了BiFPN的原理,以及YOLOv5作者如何结合BiFPN:【魔改YOLOv5-6.x(中)】:加入ACON激活函数、CBAM和CA注意力机制、加权双向特征金字塔BiFPN
本文将尝试进一步结合BiFPN,主要参考自:YOLOv5结合BiFPN
修改common.py
- 复制粘贴一下代码:
# 结合BiFPN 设置可学习参数 学习不同分支的权重
class BiFPN_Concat(nn.Module):
def __init__(self, c1, c2):
super(BiFPN_Concat, self).__init__()
# 设置可学习参数 nn.Parameter的作用是:将一个不可训练的类型Tensor转换成可以训练的类型parameter
# 并且会向宿主模型注册该参数 成为其一部分 即model.parameters()会包含这个parameter
# 从而在参数优化的时候可以自动一起优化
self.w1 = nn.Parameter(torch.ones(2, dtype=torch.float32), requires_grad=True)
self.w2 = 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):
if len(x) == 2:# add两个分支
w = self.w1
weight = w / (torch.sum(w, dim=0) + self.epsilon)
return self.conv(self.silu(weight[0] * x[0] + weight[1] * x[1]))
elif len(x) == 3:# add三个分支
w = self.w2
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
- 在
parse_model
函数中找到elif m is Concat:
语句,在其后面加上BiFPN_Concat
相关语句:
elif m is Concat:
c2 = sum(ch[x] for x in f)
elif m is BiFPN_Concat:# 增加BiFPN_Concat
c2 = max([ch[x] for x in f])
yolov5s-bifpn.yaml 修改模型配置文件时要注意以下几点:
- 这里的yaml文件只修改了一处,也就是将19层的Concat换成了BiFPN_Concat,要想修改其他层的Concat,可以类比进行修改
- BiFPN_Concat本质是add操作,不是concat操作,因此,BiFPN_Concat的各个输入层要求大小完全一致(通道数、feature map大小等),因此,这里要修改之前的参数[-1, 13, 6],来满足这个要求:
- -1层就是上一层的输出,原来上一层的输出channel数为256,这里改成512
- 13层就是这里
[-1, 3, C3, [512, False]], # 13
- 这样修改后,BiFPN_Concat各个输入大小都是
[bs,256,40,40]
- 最后BiFPN_Concat后面的参数层设置为
[256, 256]
也就是输入输出channel数都是256
# YOLOv5by 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.0 BiFPN head
head:
[[-1, 1, Conv, [512, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 6], 1, Concat, [1]],# 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, Concat, [1]],# cat backbone P3
[-1, 3, C3, [256, False]],# 17 (P3/8-small)[-1, 1, Conv, [512, 3, 2]],# 为了BiFPN正确add,调整channel数
[[-1, 13, 6], 1, BiFPN_Concat, [256, 256]],# cat P4 <--- BiFPN change 注意v5s通道数是默认参数的一半
[-1, 3, C3, [512, False]],# 20 (P4/16-medium)[-1, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]],# cat head P5
[-1, 3, C3, [1024, False]],# 23 (P5/32-large)[[17, 20, 23], 1, Detect, [nc, anchors]],# Detect(P3, P4, P5)
]
测试结果 最后可以参考这篇博客:【YOLOv5-6.x】模型参数及detect层输出测试(自用),进行模型配置文件测试并查看输出结果:
fromnparamsmodulearguments
0-113520models.common.Conv[3, 32, 6, 2, 2]
1-1118560models.common.Conv[32, 64, 3, 2]
2-1118816models.common.C3[64, 64, 1]
3-1173984models.common.Conv[64, 128, 3, 2]
4-12115712models.common.C3[128, 128, 2]
5-11295424models.common.Conv[128, 256, 3, 2]
6-13625152models.common.C3[256, 256, 3]
7-111180672models.common.Conv[256, 512, 3, 2]
8-111182720models.common.C3[512, 512, 1]
9-11656896models.common.SPPF[512, 512, 5]
10-11131584models.common.Conv[512, 256, 1, 1]
11-110torch.nn.modules.upsampling.Upsample[None, 2, 'nearest']
12[-1, 6]10models.common.Concat[1]
13-11361984models.common.C3[512, 256, 1, False]
14-1133024models.common.Conv[256, 128, 1, 1]
15-110torch.nn.modules.upsampling.Upsample[None, 2, 'nearest']
16[-1, 4]10models.common.Concat[1]
17-1190880models.common.C3[256, 128, 1, False]
18-11295424models.common.Conv[128, 256, 3, 2]
19[-1, 13, 6]165797models.common.BiFPN_Concat[256, 256]
20-11296448models.common.C3[256, 256, 1, False]
21-11590336models.common.Conv[256, 256, 3, 2]
22[-1, 10]10models.common.Concat[1]
23-111182720models.common.C3[512, 512, 1, False]
24[17, 20, 23]1229245models.yolo.Detect[80, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [128, 256, 512]]
Model Summary: 272 layers, 7448898 parameters, 7448898 gradients, 17.2 GFLOPs
Concat全部换成BiFPN_Concat
# YOLOv5by 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.0 BiFPN head
head:
[[-1, 1, Conv, [512, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 6], 1, BiFPN_Concat, [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_Concat, [128, 128]],# cat backbone P3
[-1, 3, C3, [256, False]],# 17 (P3/8-small)[-1, 1, Conv, [512, 3, 2]],# 为了BiFPN正确add,调整channel数
[[-1, 13, 6], 1, BiFPN_Concat, [256, 256]],# cat P4 <--- BiFPN change 注意v5s通道数是默认参数的一半
[-1, 3, C3, [512, False]],# 20 (P4/16-medium)[-1, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, BiFPN_Concat, [256, 256]],# cat head P5
[-1, 3, C3, [1024, False]],# 23 (P5/32-large)[[17, 20, 23], 1, Detect, [nc, anchors]],# Detect(P3, P4, P5)
]
模型输出结果:
fromnparamsmodulearguments
0-113520models.common.Conv[3, 32, 6, 2, 2]
1-1118560models.common.Conv[32, 64, 3, 2]
2-1118816models.common.C3[64, 64, 1]
3-1173984models.common.Conv[64, 128, 3, 2]
4-12115712models.common.C3[128, 128, 2]
5-11295424models.common.Conv[128, 256, 3, 2]
6-13625152models.common.C3[256, 256, 3]
7-111180672models.common.Conv[256, 512, 3, 2]
8-111182720models.common.C3[512, 512, 1]
9-11656896models.common.SPPF[512, 512, 5]
10-11131584models.common.Conv[512, 256, 1, 1]
11-110torch.nn.modules.upsampling.Upsample[None, 2, 'nearest']
12[-1, 6]165797models.common.BiFPN_Concat[256, 256]
13-11296448models.common.C3[256, 256, 1, False]
14-1133024models.common.Conv[256, 128, 1, 1]
15-110torch.nn.modules.upsampling.Upsample[None, 2, 'nearest']
16[-1, 4]116517models.common.BiFPN_Concat[128, 128]
17-1174496models.common.C3[128, 128, 1, False]
18-11295424models.common.Conv[128, 256, 3, 2]
19[-1, 13, 6]165797models.common.BiFPN_Concat[256, 256]
20-11296448models.common.C3[256, 256, 1, False]
21-11590336models.common.Conv[256, 256, 3, 2]
22[-1, 10]165797models.common.BiFPN_Concat[256, 256]
23-111051648models.common.C3[256, 512, 1, False]
24[17, 20, 23]1229245models.yolo.Detect[80, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [128, 256, 512]]
Model Summary: 278 layers, 7384017 parameters, 7384017 gradients, 17.2 GFLOPs
References 【YOLOv5|【YOLOv5-6.x】通过设置可学习参数来结合BiFPN】YOLOv5结合BiFPN
【论文笔记】EfficientDet(BiFPN)(2020)
nn.Module、nn.Sequential和torch.nn.parameter学习笔记
推荐阅读
- #|【进阶篇】全流程学习《20天掌握Pytorch实战》纪实 | Day02 | 图片数据建模流程范例
- 深度学习|(超详细) Gradient Descent(梯度下降)和Back propagation(反向传播)的关系
- 学习|学习笔记(深度学习(2)——BP神经网络)
- 热荐(每个机器学习工程师都应该知道的十大算法)
- 学习资源|【好文导读】人工智能和机器学习的富有启迪的文章
- 学习资源|【好文导读】人工智能和机器学习富有启迪的文章2020
- 学习方法|【好文导读】人工智能和机器学习的富有启迪的文章2019
- 学习资源|【好文导读】人工智能和机器学习的富有启迪的文章2018
- 学习方法|【实战技能】软件工程师与AI工程师的区别是什么()