对整体网络架构的解读,请集合博客末尾附录资料(两个网络架构图、配置文件)。
一、Focus
如下图是Focus模块,对应下面配置文件中的第三十行:
[[-1, 1, Focus, [64, 3]], # 0-P1/2
在网络前面,Focus模块的用作是加速数据处理,但并不能提升网络速度。如下图,将左边4×4×3的特征图进行分块,显然颜色一样的最终被分到一起,最终得到如右图的2×2×12的特征图。就是简单拆分,然后堆叠。
二、激活函数模块
YOLOV5中使用的激活函数是上述Hish函数,看到第三项公式:x*(x+3)/6,其对应下图(黑色部分就是常规加减乘除,下图和附录图可能版本不对应,但不影响理解):
三、BottlenckCSP模块
后续的SPP与PANet在详细架构图中比较抽象。常用的模块在common.py中。
其中,BottleneckCSP层的定义在conmmon.py中,
1 class BottleneckCSP(nn.Module): 2 # CSP Bottleneck https://github.com/WongKinYiu/CrossStagePartialNetworks 3 def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion 4 super(BottleneckCSP, self).__init__() 5 c_ = int(c2 * e) # hidden channels 6 self.cv1 = Conv(c1, c_, 1, 1) 7 self.cv2 = nn.Conv2d(c1, c_, 1, 1, bias=False) 8 self.cv3 = nn.Conv2d(c_, c_, 1, 1, bias=False) 9 self.cv4 = Conv(2 * c_, c2, 1, 1) 10 self.bn = nn.BatchNorm2d(2 * c_) # applied to cat(cv2, cv3) 11 self.act = nn.LeakyReLU(0.1, inplace=True) 12 self.m = nn.Sequential(*[Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)]) 13 14 def forward(self, x): 15 # BottleneckCSP 的两条线 16 y1 = self.cv3(self.m(self.cv1(x))) 17 y2 = self.cv2(x) 18 # 在这里汇合 19 return self.cv4(self.act(self.bn(torch.cat((y1, y2), dim=1))))
BottlenckCSP = CSP + ResNet Block。如下图,input后面分为两条路,对应上图y1,y2;之后是一个concat,和上面代码对应。需要注意的是,Bottleneck里面是一个残差连接模块。
附:
YOLO5网络结构图(简图):
YOLO5S配置文件YOLOV5S.yaml
1 # parameters 2 nc: 80 # number of classes 3 4 # 在四个yaml文件中, 5 # 5s 5m 5l 5x 也就下面网络的深度、宽度两个参数不同 6 7 # eg:下面backbone中的模块:[-1, 9, C3, [512]] 8 # 重复9次,在yolo5s中,0.33 * 9 = 3,表示仅重复三次 9 depth_multiple: 0.33 # model depth multiple 10 11 # width_multiple:卷积核个数 12 # eg:[-1, 1, Focus, [64, 3]],中的64表示经过该模块后 13 # 得到64个特征图,但是由于这里网络宽度设置为0.5,所以 14 # 输出应该是0.5 * 64 = 32个特征图 15 width_multiple: 0.50 # layer channel multiple 16 17 # anchors 先验框,和V3一样 18 anchors: 19 - [10,13, 16,30, 33,23] # P3/8 20 - [30,61, 62,45, 59,119] # P4/16 21 - [116,90, 156,198, 373,326] # P5/32 22 23 # YOLOv5 backbone 24 backbone: 25 # [from, number, module, args] 26 # from:当前层输入来自哪里,例如:-1:连接上一层;6:表示第6层输入 27 # number:模块重复次数 28 # module:模型名字 29 # args:模型参数,eg:卷积核尺寸 30 [[-1, 1, Focus, [64, 3]], # 0-P1/2 31 [-1, 1, Conv, [128, 3, 2]], # 1-P2/4 32 [-1, 3, C3, [128]], 33 [-1, 1, Conv, [256, 3, 2]], # 3-P3/8 34 [-1, 9, C3, [256]], 35 [-1, 1, Conv, [512, 3, 2]], # 5-P4/16 36 [-1, 9, C3, [512]], 37 [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32 38 [-1, 1, SPP, [1024, [5, 9, 13]]], 39 [-1, 3, C3, [1024, False]], # 9 40 ] 41 42 # YOLOv5 head 43 head: 44 [[-1, 1, Conv, [512, 1, 1]], 45 [-1, 1, nn.Upsample, [None, 2, 'nearest']], 46 [[-1, 6], 1, Concat, [1]], # cat backbone P4 47 [-1, 3, C3, [512, False]], # 13 48 49 [-1, 1, Conv, [256, 1, 1]], 50 [-1, 1, nn.Upsample, [None, 2, 'nearest']], 51 [[-1, 4], 1, Concat, [1]], # cat backbone P3 52 [-1, 3, C3, [256, False]], # 17 (P3/8-small) 53 54 [-1, 1, Conv, [256, 3, 2]], 55 [[-1, 14], 1, Concat, [1]], # cat head P4 56 [-1, 3, C3, [512, False]], # 20 (P4/16-medium) 57 58 [-1, 1, Conv, [512, 3, 2]], 59 [[-1, 10], 1, Concat, [1]], # cat head P5 60 [-1, 3, C3, [1024, False]], # 23 (P5/32-large) 61 62 [[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5) 63 ]
YOLO5S网络结构图(详细):