本文仅供作者复习使用,如有侵权联系即删。
Yolov5s 6.0版网络架构
1. 基础组件
Focus 2023年yolov5的focus被替换成了6x6卷积层.
1.1 CBS
CBS
class Conv(nn.Module):
# Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)
default_act = nn.SiLU() # default activation
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
super().__init__()
self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
self.bn = nn.BatchNorm2d(c2)
self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()
# 正向计算,网络执行的顺序是根据forward函数来决定的
def forward(self, x):
# conv卷积 -> bn -> act激活
return self.act(self.bn(self.conv(x)))
# 正向融合计算
def forward_fuse(self, x):
# 只有卷积和激活
return self.act(self.conv(x))
CBL
1.2 BottleNeck
class Bottleneck(nn.Module):
# Standard bottleneck
def __init__(self, c1, c2, shortcut=True, g=1, e=0.5): # ch_in, ch_out, shortcut, groups, expansion
super().__init__()
c_ = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, c_, 1, 1) #这里的Conv就是上面写的CBS
self.cv2 = Conv(c_, c2, 3, 1, g=g)
self.add = shortcut and c1 == c2
def forward(self, x):
return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
1.2.1 BottleNeck_1
1.2.2 BottleNeck_2
1.3 BottleNeckCSP
BottleneckCSP中cv2和cv3调用的是系统的卷积层,使用concat连接之后,加上BN和激活函数。
CSP结构想在输入block(如Bottleneck)之前,将输入分为两个部分,其中一部分通过block进行计算,另一部分通过卷积计算,再concat。
主要作用是加强CNN的学习能力、减少内存消耗,减少计算瓶颈,现在的网络大多计算代价昂贵,不利于工业落地。
1.4 C3
3代表三个卷积
C3是一种简化版的BottleneckCSP,模块和BotttleneckCSP模块类似,但是少了一个Conv模块,只有3个卷积,可以减少参数,所以取名C3。
BottleneckCSP中cv2和cv3调用的是系统的卷积层,使用concat连接之后加上BN层和激活函数。C3则直接使用了CBS。
class C3(nn.Module):
# CSP Bottleneck with 3 convolutions
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
super().__init__()
c_ = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = Conv(c1, c_, 1, 1)
self.cv3 = Conv(2 * c_, c2, 1) # optional act=FReLU(c2)
self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)))
def forward(self, x):
return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))
CSP1_X
CSP2_X
1.5 SPP
SPP
SPP空间金字塔池化,用在骨干网络收尾阶段,用于融合多尺度特征。由何凯明等大陆提出,这个模块的主要作用是为了将更多不同分辨率的特征进行融合,得到更多的信息。
SPPF
SPPF是快速版的空间金字塔池化
SPPF是快速版的空间金字塔池化
池化尺寸等价于:5、9、13和原来一样,但是运算量从减少到了。
比spp更快,缓解多尺度问题
yaml文件
[from, number, module, args]
- from:当前模块的输入来自哪一层的输出,-1表示将上一层的输出当作自己的输入。第0层的-1表示输入的图像
- number:当前模块的重复次数,实际的重复次数还要由上面的参数depth_multiple共同决定,决定网络模型的深度
- module:该层模块的名称,会从common.py中调用对应的组件,进行模块化的网络搭建
- args:类的初始化参数,用于解析作为module的传入参数,会在网络搭建过程中根据不同层进行改变。
2. 输入端:
2.1 Mosaic数据增强
Mosaic数据增强算法将多张图片(一般4张)按照一定比例组合成一张图片,使模型在更小的范围内识别目标。
2.1.1 步骤
2.1.2 优点:
丰富数据集:随机使用4张图像,随机缩放后随机拼接,增加很多小目标,大大增加了数据多样性 增强鲁棒性:混合四张具有不同语义信息的图片,可以让模型检测超出常规语境的目标 加强批归一化层的效果: 有利于提升小目标检测性能:数据增强图像由四张原始图像拼接而成,这样每张图像会有大概率包含小目标,从而提升了模型的检测能力
2.2 自适应锚框计算
Yolov5在每次训练开始之前,都会根据不同的数据集来自适应计算anchor,在训练时,网络会在anchor的基础上进行预测,输出预测框,再和标签框进行对比,最后就进行梯度的反向传播。
在训练模型时,YOLOv5 会自己学习数据集中的最佳 anchor boxes,而不再需要先离线运行 K-means 算法聚类得到 k 个 anchor box 并修改 head 网络参数。总的来说,YOLOv5 流程简单且自动化了。
2.2.1 计算过程
- 获取数据集中所有目标的宽和高
- 将每张图片中按照等比例缩放的方式到resize指定大小,保证宽高中的最大值符合指定大小
- 将bboxes从相对坐标改成绝对坐标,这里乘以的是缩放后的宽高
- 筛选bboxes,保留宽高都大于等于两个像素的bboxes
- 使用k-means聚类三方得到n个anchors
- 使用遗传算法随机对anchors的宽高进行变异。倘若变异后的效果好,就将变异后的结果赋值给anchors;如果变异后效果变差就跳过,默认变异1000次i。这里是使用anchor_fitness方法计算得到的适应度fitness,然后再进行评估。
2.3 自适应图片缩放
在常用的目标检测算法中,不同的图片长宽都不相同,因此常用的方式是将原始图片统一缩放到一个标准尺寸,再送入检测网络中。
3. Backbone:骨干网络特征提取
Backbone负责提取输入图像的特征。
在Yolov5中,常见的Backbone网络包括CSPDarknet53或ResNet。这些网络都是相对轻量级的,能够在保证较高检测精度的同时,尽可能地减少计算量和内存占用。
其结构主要有Conv模块、C3模块、SPPF模块。
Conv模块主要由卷积层、BN层和激活函数组成。
C3模块则将前面的特征图进行自适应聚合。
SPPF模块通过全局特征与局部特征的加权融合,获取更全面的空间信息
3.1 Focus
在图片进入Backbone前,对图片进行切片操作。在一张图片中,每隔一个像素拿到一个值,类似于邻近下采样,这样就拿到了四张图片互补。四张图片长得差不多,同时信息也没有丢失,这样就将W、H信息集中到了通道空间,输入通道扩充了4倍。即拼接好的图片相对于原先的RGB图像,由3通道变成了3x4=12通道,最后再将新得到的图片进行卷积操作,最终得到没有信息丢失情况下的二倍下采样特征图。
Focus层原理和PassThrough层很类似。它采用切片操作把高分辨率的图片(特征图)拆分成多个低分辨率的图片/特征图,即隔列采样+拼接。
优点:可以使信息不丢失的情况下提高计算力
缺点:有些设备不支持Focus,且开销很大。另外如果切片不对齐的话,模型会崩
改进:在新版yolov5中,Focuse模块被替换成了一个6x6的卷积层。两者的计算是等价的,但6x6的卷积层更高效。
原始的640 × 640 × 3的图像输入Focus结构,采用切片(slice)操作,先变成320 × 320 × 12的特征图,拼接(Concat)后,再经过一次卷积(CBL(后期改为SiLU,即为CBS))操作,最终变成320 × 320 × 64的特征图。
3.2 C3
Yolov5s中设计了两种C3结构,C3_1应用于Backbone主干网络,C3_2结构用于Neck中
4. Neck:颈部网络增强特征表达能力
4.1 FPN
自顶向下
4.2 PAN
自底向上
自上而下,自下而上的特征融合,可以更充分提取特征
Yolov5的Neck中,采用CSPNet设计的CSP2结构,从而加强了网络特征融合能力。
FPN层自顶向下传达强语义特征,而PAN自底向上传达定位特征
5. Head:头部网络进行模型预测
5.1 Bounding box损失函数
Yolov5采用CIOU_LOSS作为bounding box的损失函数。
IOU_Loss
GIOU_LOSS
DIOU_LOSS
CIOU_LOSS
5.2 NMS非极大值抑制
非极大值抑制主要用来抑制检测时冗余的框。在目标检测中,同一目标的位置上会产生大量的候选框,这些候选框相互之间可能会有重叠。通过非极大值抑制可以找到最佳的目标边界框,消除冗余的边界框。
- 对所有预测框的置信度降序排序
- 选出置信度最高的预测框,确认其为正确预测,并计算他与其他预测框的IOU
- 根据步骤2中计算的IOU去除重叠度高的,IOU > threshold就直接删除
- 剩下的预测框返回第1步,直到没有剩下的位置。
SoftNMS
当两个目标靠的非常近时,置信度低的会被置信度高的框所抑制,那么当两个目标靠的十分近的时候就只会识别出一个Box。SoftNMS使用稍微低一点的分数来代替原有的分数,而不是像NMS一样直接置零。