赞
踩
目录
2.1第一步:common.py构建Concat_BIFPN模块
2.2第二步:yolo.py中注册Concat_BIFPNt模块
2.3第三步:修改yaml文件(以修改官方YOLOv5s.yaml为例),需要修改head(特征融合网络)
论文《EfficientDet: Scalable and Efficient Object Detection》地址:https://arxiv.org/abs/1911.09070
BiFPN 全称 Bidirectional Feature Pyramid Network 加权双向(自顶向下 + 自低向上)特征金字塔网络。
加入BIFPN加权双向金字塔结构,提升不同尺度的检测效果。
图中蓝色部分为自顶向下的通路,传递的是高层特征的语义信息;红色部分是自底向上的通路,传递的是低层特征的位置信息;紫色部分是同一层在输入节点和输入节点间新加的一条边。
我们删除那些只有一条输入边的节点。这么做的思路很简单:如果一个节点只有一条输入边而没有特征融合,那么它对旨在融合不同特征的特征网络的贡献就会很小。删除它对我们的网络影响不大,同时简化了双向网络;如上图d 的 P7右边第一个节点
如果原始输入节点和输出节点处于同一层,我们会在原始输入节点和输出节点之间添加一条额外的边。思路:以在不增加太多成本的情况下融合更多的特性;
与只有一个自顶向下和一个自底向上路径的PANet不同,我们处理每个双向路径(自顶向下和自底而上)路径作为一个特征网络层,并重复同一层多次,以实现更高层次的特征融合。如下图EfficientNet 的网络结构所示,我们对BiFPN是重复使用多次的。而这个使用次数也不是我们认为设定的,而是作为参数一起加入网络的设计当中,使用NAS技术算出来的。
Weighted Feature Fusion 带权特征融合:学习不同输入特征的重要性,对不同输入特征有区分的融合。
设计思路:传统的特征融合往往只是简单的 feature map 叠加/相加 (sum them up),比如使用concat或者shortcut连接,而不对同时加进来的 feature map 进行区分。然而,不同的输入 feature map 具有不同的分辨率,它们对融合输入 feature map 的贡献也是不同的,因此简单的对他们进行相加或叠加处理并不是最佳的操作。所以这里我们提出了一种简单而高效的加权特融合的机制。
常见的带权特征融合有三种方法。
- class Concat_bifpn(nn.Module):
- # Concatenate a list of tensors along dimension
- def __init__(self, c1, c2):
- super(Concat_bifpn, self).__init__()
- 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.w3 = nn.Parameter(torch.ones(3, dtype=torch.float32), requires_grad=True)
- self.epsilon = 0.0001
- self.conv = Conv(c1, c2, 1 ,1 ,0 )
- self.act= nn.ReLU()
-
- def forward(self, x): # mutil-layer 1-3 layers #ADD or Concat
- #print("bifpn:",x.shape)
- if len(x) == 2:
- w = self.w1
- weight = w / (torch.sum(w, dim=0) + self.epsilon)
- x = self.conv(self.act(weight[0] * x[0] + weight[1] * x[1]))
- elif len(x) == 3:
- w = self.w2
- weight = w / (torch.sum(w, dim=0) + self.epsilon)
- x = self.conv(self.act (weight[0] * x[0] + weight[1] * x[1] + weight[2] * x[2]))
- # elif len(x) == 4:
- # w = self.w3
- # weight = w / (torch.sum(w, dim=0) + self.epsilon)
- # x = self.conv(self.act(weight[0] * x[0] + weight[1] * x[1] + weight[2] *x[2] + weight[3]*x[3] ))
- return x
- elif m is Concat_bifpn:
- c2 = max([ch[x] for x in f])
- # parameters
- nc: 80 # number of classes
- depth_multiple: 0.33 # model depth multiple
- width_multiple: 0.50 # layer channel multiple
-
- # anchors
- 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 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]],
- ]
-
- # YOLOv5 head
- head:
- [[-1, 1, Conv, [512, 1, 1]],
- [-1, 1, nn.Upsample, [None, 2, 'nearest']],
- [[-1,6], 1, Concat_bifpn, [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, Concat_bifpn, [128,128]], # cat backbone P3
- [-1, 3, C3, [256, False]], # 17 (P3/8-small)
-
-
- [-1, 1, Conv, [512, 3, 2]], # 320, 640 #
- [[-1, 6, 13], 1, Concat_bifpn, [256,256]], # cat head P4
- [-1, 3, C3, [512, False]], # 20 (P4/16-medium)
-
- [-1, 1, Conv, [1024, 3, 2]], # 640, 1280 #
- [[-1, 9], 1, Concat_bifpn, [512, 512]], # cat head P5 cat 20,20 #22
- [-1, 3, C3, [1024, False]], # 25 (P5/32-large) # 1280, 1280 #23
-
-
- [[17, 20, 23], 1, Detect, [nc, anchors]] # Detect(P3, P4, P5)
- ]
Model Summary: 290 layers, 8114651 parameters, 8114651 gradients, 17.4 GFLOPs
如果需要在YOLOv5l.yaml等网络结构进行修改的话,不可直接用以上的yaml文件或者就简单修改depth_multiple为1.0,而是 需要修改Concat_bifpn, [256,256]中的通道数为对应网络实际通道数。具体如下所示:
- # parameters
- nc: 80 # number of classes
- depth_multiple: 1.0 # model depth multiple
- width_multiple: 1.0 # layer channel multiple
-
- # anchors
- 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 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]],
- ]
-
- # YOLOv5 head
- head:
- [[-1, 1, Conv, [512, 1, 1]],
- [-1, 1, nn.Upsample, [None, 2, 'nearest']],
- [[-1,6], 1, Concat_bifpn, [512,512]], # 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_bifpn, [256,256]], # cat backbone P3
- [-1, 3, C3, [256, False]], # 17 (P3/8-small)
-
-
- [-1, 1, Conv, [512, 3, 2]], # 320, 640 #
- [[-1, 6, 13], 1, Concat_bifpn, [512,512]], # cat head P4
- [-1, 3, C3, [512, False]], # 20 (P4/16-medium)
-
- [-1, 1, Conv, [1024, 3, 2]], # 640, 1280 #
- [[-1, 9], 1, Concat_bifpn, [1024, 1024]], # cat head P5 cat 20,20 #22
- [-1, 3, C3, [1024, False]], # 25 (P5/32-large) # 1280, 1280 #23
-
-
- [[17, 20, 23], 1, Detect, [nc, anchors]] # Detect(P3, P4, P5)
- ]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。