资讯详情

[纯理论] YOLOv5

YOLOv5

作者: ultralytics

论文源码: https://github.com/ultralytics/yolov5

0. 引言

YOLOv5 ?? is a family of object detection architectures and models pretrained on the COCO dataset, and represents Ultralytics open-source research into future vision AI methods, incorporating lessons learned and best practices evolved over thousands of hours of research and development.

YOLOv五是一个COCO代表数据集上预训练的物体检测架构和模型系列Ultralytics对未来视觉AI该方法的开源研究包括数千小时的研发经验教训和最佳实践。


YOLOv5仓库是在2020-05-18到目前为止,已经迭代了许多大版本,现在已经迭代到v6.1.下表是现在(v6.1)关于不同大小模型和输入尺度对应的官网贴出mAP、推理速度、参数量和理论计算量FLOPs。

Model size(pixels) mAPval0.5:0.95 mAPval0.5 SpeedCPU b1(ms) SpeedV100 b1(ms) SpeedV100 b32(ms) params(M) FLOPs@640 (B)
YOLOv5n 640 28.0 45.7 45 6.3 0.6 1.9 4.5
YOLOv5s 640 37.4 56.8 98 6.4 0.9 7.2 16.5
YOLOv5m 640 45.4 64.1 224 8.2 1.7 21.2 49.0
YOLOv5l 640 49.0 67.3 430 10.1 2.7 46.5 109.1
YOLOv5x 640 50.7 68.9 766 12.1 4.8 86.7 205.7
YOLOv5n6 1280 36.0 54.4 153 8.1 2.1 3.2 4.6
YOLOv5s6 1280 44.8 63.7 385 8.2 3.6 12.6 16.8
YOLOv5m6 1280 51.3 69.3 887 11.1 6.8 35.7 50.0
YOLOv5l6 1280 53.7 71.3 1784 15.8 10.5 76.8 111.4
YOLOv5x6 TTA 12801536 55.055.8 72.772.7 3136- 26.2- 19.4- 140.7- 209.8-

1. 网络结构

YOLOv5的网络结构主要由以下几部分组成:

  1. : New CSP-Darknet53
  2. : SPPF, New CSP-PAN
  3. : YOLOv3 Head

下面是霹雳吧啦Wz根据yolov5l.yaml网络的整体结构,YOLOv针对不同的大小(n, s, m, l, x)网络的整体架构是一样的,只是,分别应对yaml文件中的depth_multiplewidth_multiple参数。还需要注意的是,除了官方n, s, m, l, x版本外还有n6, s6, m6, l6, x6,区别在于后者是针对更大分辨率的图片,比如1280x当然,1280有一些结构差异。后者采样64倍,采用4个预测特征层,前者只采样32倍,采用3个预测特征层。本文只讨论前者。

在这里插入图片描述

1.1 Backbone

通过上一篇博文YOLOv4对比,其实。但是YOLOv5在v6.0版本后,与之前的版本相比,网络的第一层(原来是Focus用模块代替6×6大小的卷积层。理论上,两者实际上是相等的,但对于现有的一些GPU设备(以及相应的优化算法)使用6×6使用大小卷积层比Focus模块更高效。详情请参考此issue #4825 -> Is the Focus layer equivalent to a simple Conv layer?。

下图是原来的Focus模块(和以前一样Swin Transformer中的Patch Merging类似),每2×2相邻像素分为一个patch,然后将每个patch同一位置(同一颜色)像素拼在一起得到4个feature map,然后连接一个3×三大小的卷积层。直接使用一个6×卷积层大小等效。

1.2 Neck

YOLOv5在Neck部分变化相对较大,首先是SPP换成成了SPPF(Spatial Pyramid Pooling - Fast, 是Glenn Jocher我个人认为自己设计的)这个变化还是很有意思的。两者的作用是一样的,但是

1.2.1 SPP (Spatial Pyramid Pooling)

SPP结构如下图所示,是将输入并行通过多个不同大小的MaxPool,然后做进一步融合,能在一定程度上解决目标多尺度问题。

每一个分支得到fmap的shape都一样, 最后会实现通道数×4

1.2.2 SPPF (Spatial Pyramid Pooling Fast)

而SPPF结构是将输入通过多个5×5大小的MaxPool层,这里需要注意的是串行两个5×5大小的MaxPool层是和一个9×9大小的MaxPool层计算结果是一样的,串行三个5×5大小的MaxPool层是和一个13×13大小的MaxPool层计算结果是一样的。

SPPF最后同样会实现通道数×4

SPPF的代码如下:

class SPPF(nn.Module):
    # Spatial Pyramid Pooling - Fast (SPPF) layer for YOLOv5 by Glenn Jocher
    def __init__(self, c1, c2, k=5):  # equivalent to SPP(k=(5, 9, 13))
        super().__init__()
        c_ = c1 // 2  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c_ * 4, c2, 1, 1)
        self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2)
 
    def forward(self, x):
        x = self.cv1(x)  # 先通过CBL进行通道数的减半
        with warnings.catch_warnings():
            warnings.simplefilter('ignore')  # suppress torch 1.9.0 max_pool2d() warning
            y1 = self.m(x)
            y2 = self.m(y1)
            # 上述两次最大池化
            # 将原来的x,一次池化后的y1,两次池化后的y2,3次池化的self.m(y2)先进行拼接,然后再CBL
            return self.cv2(torch.cat([x, y1, y2, self.m(y2)], 1))

1.2.3 SPP和SPPF速度对比

下面做个简单的小实验,对比下SPP和SPPF的计算结果以及速度,代码如下(注意这里将SPPF中最开始和结尾处的1×1卷积层给去掉了,只对比含有MaxPool的部分):

import time
import torch
import torch.nn as nn


class SPP(nn.Module):
    def __init__(self):
        super().__init__()
        self.maxpool1 = nn.MaxPool2d(5, 1, padding=2)
        self.maxpool2 = nn.MaxPool2d(9, 1, padding=4)
        self.maxpool3 = nn.MaxPool2d(13, 1, padding=6)

    def forward(self, x):
        o1 = self.maxpool1(x)
        o2 = self.maxpool2(x)
        o3 = self.maxpool3(x)
        return torch.cat([x, o1, o2, o3], dim=1)


class SPPF(nn.Module):
    def __init__(self):
        super().__init__()
        self.maxpool = nn.MaxPool2d(5, 1, padding=2)

    def forward(self, x):
        o1 = self.maxpool(x)
        o2 = self.maxpool(o1)
        o3 = self.maxpool(o2)
        return torch.cat([x, o1, o2, o3], dim=1)


def main():
    input_tensor = torch.rand(8, 32, 16, 16)
    spp = SPP()
    sppf = SPPF()
    output1 = spp(input_tensor)
    output2 = sppf(input_tensor)

    print(torch.equal(output1, output2))

    t_start = time.time()
    for _ in range(100):
        spp(input_tensor)
    print(f"spp time: { 
          time.time() - t_start}")

    t_start = time.time()
    for _ in range(100):
        sppf(input_tensor)
    print(f"sppf time: { 
          time.time() - t_start}")


if __name__ == '__main__':
    main()

终端输出结果:

True
spp time: 0.6333663463592529
sppf time: 0.2547760009765625

通过对比可以发现,两者的计算结果是一模一样的,但SPPF比SPP计算速度快了不止两倍,快乐翻倍。

1.2.4 CSP-PAN

在Neck部分另外一个不同点就是New CSP-PAN了,在YOLOv4中,Neck的PAN结构是没有引入CSP结构的,但在YOLOv5中作者在PAN结构中加入了CSP。详情见上面的网络结构图,每个C3模块里都含有CSP结构。

CSP结构是在CSPNet(Cross Stage Partial Network)论文中提出的,CSPNet作者说在目标检测任务中使用CSP结构有如下好处:

  • Strengthening learning ability of a CNN: 增强CNN的学习能力
  • Removing computational bottlenecks: 移除计算瓶颈
  • Reducing memory costs: 减少MACs

CSP的加入可以: 减少网络的计算量以及对显存的占用,同时保证网络的能力不变或者略微提升。CSP结构的思想参考原论文中绘制的CSPDenseNet,进入每个stage(一般在下采样后)先将数据划分成俩部分,如下图左图所示的Part1和Part2。

左边的图是CSPDenseNet(来源于CSPNet论文)。CSP结构会将网络分为两个部分。Part2分支首先会经过一系列的Block(这里是DenseBlock),最后经过Transition,得到输出后再与Part1上的输出进行Transition融合。

1.3 Head

在Head部分,YOLOv3, v4, v5都是一样的。

2. 数据增强策略

在YOLOv5代码里,关于数据增强策略还是挺多的,这里简单罗列部分方法:

2.1 Mosaic

将四张图片拼成一张图片。

2.2 Copy Paste

将部分目标随机的粘贴到图片中,前提是数据要有segments数据才行,即每个目标的实例分割信息。下面是Copy paste原论文中的示意图。

可以理解为是升级版的Mosaic

2.3 Random affine(Rotation, Scale, Translation and Shear)

随机进行仿射变换,但根据配置文件里的超参数发现只使用了Scale (缩放)和Translation (平移)。

数据增强中的仿射变换:旋转,缩放,平移以及错切(shear)

2.4 MixUp

Mixup就是将两张图片按照一定的透明度融合在一起,具体有没有用不太清楚,毕竟没有论文,也没有消融实验。代码中只有较大的模型才使用到了MixUp,而且每次只有 10 % 10\% 10% 的概率会使用到。

2.5 Albumentations

主要是做些滤波、直方图均衡化以及改变图片质量等等,我看代码里写的只有安装了albumentations包才会启用,但在项目的requirements.txt文件中albumentations包是被注释掉了的,所以


Albumentations官方文档: https://albumentations.readthedocs.io/en/latest/

albumentations 是一个给予 OpenCV 的快速训练数据增强库,拥有非常简单且强大的可以用于多种任务(分割、检测)的,易于定制且添加其他框架非常方便。

它可以对数据集进行逐像素的转换,如:

  1. 模糊
  2. 下采样
  3. 高斯造点
  4. 高斯模糊
  5. 动态模糊
  6. RGB转换
  7. 随机雾化

也可以进行空间转换(同时也会对目标进行转换),如:

  1. 裁剪
  2. 翻转
  3. 随机裁剪等。

github及其示例地址如下:

GitHub: https://github.com/albumentations-team/albumentations 示例:https://github.com/albumentations-team/albumentations_examples

参考: https://zhuanlan.zhihu.com/p/107399127/

2.6 Augment HSV(Hue, Saturation, Value)

随机调整色度,饱和度以及明度。

2.7 Random horizontal flip,随机水平翻转

3. 训练策略

在YOLOv5源码中使用到了很多训练的策略,这里简单总结几个:

  1. Multi-scale training(0.5~1.5x): 假设设置输入图片的大小为 640 × 640 640 \times 640 640×640,训练时采用尺寸是在 0.5 × 640 ∼ 1.5 × 640 0.5 \times 640 \sim 1.5 \times 640 0.5×640∼1.5×640 之间随机取值,注意取值时取得都是32的整数倍(因为网络会最大下采样32倍)。
  2. AutoAnchor(For training custom data): 训练自己数据集时可以根据自己数据集里的目标进行重新聚类生成Anchors模板。
  3. Warmup and Cosine LR scheduler: 训练前先进行Warmup热身,然后在采用Cosine学习率下降策略。
  4. EMA(Exponential Moving Average): 可以理解为给训练的参数加了一个动量,让它更新过程更加平滑。
  5. Mixed precision: ,能够减少显存的占用并且加快训练速度,前提是GPU硬件支持。
  6. Evolve hyper-parameters: 没有炼丹经验的人勿碰,保持默认就好。

4. 其他

4.1 损失计算

YOLOv5的损失主要由三个部分组成:

  1. Classes loss,: 采用的是BCE loss,注意只计算正样本的分类损失。
  2. Objectness loss,: 采用的依然是BCE loss,注意这里的obj指的是网络预测的目标边界框与GT Box的CIoU。这里计算的是font color=‘red’>所有样本的obj损失。
  3. Location loss,: 采用的是CIoU loss,注意只计算正样本的定位损失。

L a l l = λ 1 L c l s + λ 2 L o b j + λ 3 L l o c {\mathcal L}_{all} = \lambda_1 {\mathcal L}_{\rm cls} + \lambda_2 {\mathcal L}_{\rm obj} + \lambda_3 {\mathcal L}_{\rm loc} Lall​=λ1​Lcls​+λ2​Lobj​+λ3​Lloc​

其中, λ 1 , λ 2 , λ 3 \lambda_1, \lambda_2, \lambda_3 λ1​,λ2​,λ3​ 为平衡系数。

4.2 平衡不同尺度的损失

这里是指针对三个预测特征层(P3, P4, P5)上的obj损失采用不同的权重。在源码中,针对预测小目标的预测特征层(P3)采用的权重是4.0,针对预测中等目标的预测特征层(P4)采用的权重是1.0,针对预测大目标的预测特征层(P5)采用的权重是0.4,作者说这是针对COCO数据集设置的超参数。

L o b j = 4.0 ⋅ L o b j s m a l l + 1.0 ⋅ L o b j m e d i u m + 0.4 ⋅ L l a r g e s m a l l {\mathcal L}_{\rm obj} = 4.0 \cdot {\mathcal L}^{\rm small}_{\rm obj} + 1.0 \cdot {\mathcal L}^{\rm medium}_{\rm obj} + 0.4 \cdot {\mathcal L}^{\rm small}_{\rm large} Lobj​=4.0⋅Lobjsmall​+1.0⋅Lobjmedium​+0.4⋅Llargesmall​

4.3 消除Grid敏感度 (Eliminating grid sensitivity)

在YOLOv4中有提到过,主要是调整预测目标中心点相对Grid网格的左上角偏移量。下图是YOLOv2,v3的计算公式。

其中:

  • t x t_x tx​ 是网络预测的目标中心 x x x 坐标偏移量(相对于网格的左上角)
  • t y t_y ty​ 是网络预测的目标中心 y y y 坐标偏移量(相对于网格的左上角)
  • c x c_x cx​ 是对应网格左上角的 x x x 坐标
  • c y c_y cy​ 是对应网格左上角的 y y y 坐标
  • σ \sigma σ 是sigmoid激活函数,,即预测的中心点不会超出对应的Grid Cell区域

关于预测目标中心点相对Grid网格左上角 ( c x , c y ) (c_x, c_y) (cx​,cy​) 偏移量为 σ ( t x ) , σ ( t y ) \sigma(t_x), \sigma(t_y) σ(tx​),σ(ty​)。YOLOv4的作者认为这样做不太合理,比如当真实目标中心点非常靠近网格的左上角点 σ ( t x ) \sigma(t_x) σ(tx​) 和 σ ( t y ) \sigma(t_y) σ(ty​) 应该趋近与0)或者右下角点( σ ( t x ) \sigma(t_x) σ(tx​) 和 σ ( t y ) \sigma(t_y) σ(ty​) 应该趋近与1)时,网络的预测值需要负无穷或者正无穷时才能取到,而这种很极端的值网络一般无法达到。

为了解决这个问题,作者对偏移量进行了缩放从原来的 ( 0 , 1 ) (0, 1) (0,1) 缩放到 ( − 0.5 , 1.5 ) (-0.5, 1.5) (−0.5,1.5) 这样网络预测的偏移量就能很方便达到0或1,故最终预测的目标 b x , b y b_x, b_y bx​,by​ 的计算公式为:

b x = ( 2 ⋅ σ ( t x ) − 0.5 ) + c x b y = ( 2 ⋅ σ ( t y ) − 0.5 ) + c y b_x = \left( 2 \cdot \sigma(t_x) - 0.5 \right) + c_x \\ b_y = \left( 2 \cdot \sigma(t_y) - 0.5 \right) + c_y bx​=(2⋅σ(tx​)−0.5)+

标签: 1sma22at3g抑制二极管

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台