【YOLO系列】YOLO v5(网络结构图+代码)

文章目录

    • 推理
    • 转换onnx
    • 网络架构
      • SPP VS SPPF
      • AutoAnchor
      • Loss
    • 参考

【YOLO系列】YOLO v3(网络结构图+代码)
【YOLO 系列】YOLO v4-v5先验知识
【YOLO系列】YOLO v4(网络结构图+代码)

我是在自己笔记本上配置的YOLO v5环境。首先,conda创建YOLO v5虚拟环境,克隆
ultralytics/yolov5项目,pip install -r requirements.txt安装所需库文件。

YOLO v5提供了五个不同大小的预训练模型,分别是YOLOv5n、YOLOv5s、YOLOv5m、YOLOv5l和YOLOv5x。这五个模型的参数量、mAP和推理速度如下所示:
【YOLO系列】YOLO v5(网络结构图+代码)_第1张图片
这五个模型的网络结构是一样的,不一样的就是通道数和宽度不一样,受depth_multiple和width_multiple两个因子影响。

模型 depth multiple width multiple
YOLOv5n 0.33 0.25
YOLOv5s 0.33 0.50
YOLOv5m 0.67 0.75
YOLOv5l 1.0 1.0
YOLOv5x 1.33 1.25

推理

我笔记本的CPU为Inter i7-7700HQ,使用detect.py进行推理。预训练权重选择yolov5x.pt,推理图像默认来自于"\data\images"文件夹下。推理命令行如下所示:

python detect.py --weights models/yolov5x.pt --device cpu --view-img

推理时,会输出每张图片前处理后的图片大小,检测结果和推理时间。官方给出的YOLOv5x在CPU上的推理时间为766ms,可能笔记本的CPU太弱了吧,这两张图片的推理时间在1.5s~2.0s之内。

image 1/2 F:\yolov5\data\images\bus.jpg: 640x480 4 persons, 1 bus, 1973.8ms
image 2/2 F:\yolov5\data\images\zidane.jpg: 384x640 3 persons, 2 ties, 1565.6ms
Speed: 0.5ms pre-process, 1769.7ms inference, 7.8ms NMS per image at shape (1, 3, 640, 640)

bus图片推理结果展示 zidane图片推理结果展示
【YOLO系列】YOLO v5(网络结构图+代码)_第2张图片 【YOLO系列】YOLO v5(网络结构图+代码)_第3张图片

转换onnx

YOLO v5的模型配置是yaml文件,为了能直观地查看YOLO v5的网络结构,需要将预训练pt模型转换成onnx的格式。onnx的算子版本默认为17,这里设置算子版本为11。

python export.py --weights models/yolov5x.pt --device cpu --opset=11 --include onnx

然后使用生成的onnx文件进行推理,测试一下生成的onnx文件是否正确。

F:\yolov5>python detect.py --weights models/yolov5x.onnx --device cpu --view-img

网络架构

YOLO v5的网络结构也清晰地分为backbone、Neck和Head三部分。YOLO v5第一版于2020年6月发布,距今已有三年,这三年YOLO v5也从第一版已更新到第七版。在前四版时,对PAN和CSP都进行了更新。在第四版时,使用SiLU激活函数代替LeakyReLU和Hardswish激活函数。在第六版时,使用一个Conv(k=6, s=2, p=2) 卷积层替代Focus结构;使用SPPF替代SPP结构。还有一些其他更改,目的都是为了使得YOLO v5模型更轻量、更快和更准确。

自YOLO v5模型第六版之后,backbone、neck和Head的结构就如下所示了。

  • Backbone: New CSP-Darknet 53
  • Neck: SPPF, New CSP-PAN
  • Head: YoLo v3 Head

下图是YOLOv5l的网络架构,YOLO v5在Head时,使用C3结构替代YOLOv3和YOLOv4 head和neck的五层卷积。

【YOLO系列】YOLO v5(网络结构图+代码)_第4张图片

SPP VS SPPF

SPP SPPF
【YOLO系列】YOLO v5(网络结构图+代码)_第5张图片 【YOLO系列】YOLO v5(网络结构图+代码)_第6张图片

SPPF比SPP的运行时间快2倍。SPP的三个最大池化层的size是不一样的,但是输入是一样的;SPPF的三个最大池化层的size是一样的,后续两个最大池化的输入是前一个最大池化层的输出。

AutoAnchor

在YOLO v5中,默认使用autoAnchor,不用手工选择anchor boxes,使用k-means聚类算法在训练集上自动寻找anchor boxes。训练时设置noautoanchor,才能使用自定义的anchor boxes。

parser.add_argument(‘–noautoanchor’, action=‘store_true’, help=‘disable AutoAnchor’)

autoAnchor在yaml配置文件中设置如下所示。其中3表示每个输出层分配3个anchor大小。

anchors: 3 # AutoAnchor evolves 3 anchors per P output layer

k-means是非常经典的聚类方法,通过计算样本之间的距离将相近的样本聚到同一类别。auto anchor的计算函数为utils/autoanchors.py文件的kmean_anchors。源代码有些长,我只截取了k-means计算auto anchor的核心部分和进化算法中的适应度计算。

def metric(k, wh):  # compute metrics
    """
    k: anchor框
    wh: 整个数据集的 wh [N, 2]
    x: [N, 9] N个 gt boxes 与所有 anchor boxes的宽比或高比(两者之中较小者)
    x.max(1)[0]: [N] N个 gt boxes 与所有 anchor boxes中的最大宽比或高比(两者之中较小者)
    """
    r = wh[:, None] / k[None]  # 两者的重合程度越高,越趋近1
    x = torch.min(r, 1 / r).min(2)[0]  # ratio metric
    return x, x.max(1)[0]  # x, best_x

def anchor_fitness(k):  # mutation fitness
    #适应度计算 用于遗传算法中衡量突变是否有效的标注 优胜劣汰
    _, best = metric(torch.tensor(k, dtype=torch.float32), wh)
    return (best * (best > thr).float()).mean()  # fitness

# 得到数据集中所有图像的wh
shapes = img_size * dataset.shapes / dataset.shapes.max(1, keepdims=True) # 将图片的长边缩放到img_size,相应地缩放短边
wh0 = np.concatenate([l[:, 3:5] * s for s, l in zip(shapes, dataset.labels)])  # 将图片中gt boxes的wh缩放到shapes尺度。 dataset.labels其中格式为[类别,x, y , w, h],xywh均已经归一化了

# Filter
i = (wh0 < 3.0).any(1).sum() # 统计gt boxes中w和h小于3像素的个数
if i:
    LOGGER.info(f'{PREFIX}WARNING ⚠️ Extremely small objects found: {i} of {len(wh0)} labels are <3 pixels in size')
# 筛选大于2像素的gt boxes用作聚类
wh = wh0[(wh0 >= 2.0).any(1)].astype(np.float32)  # filter > 2 pixels

# Kmeans init
try:
    LOGGER.info(f'{PREFIX}Running kmeans for {n} anchors on {len(wh)} points...')
    assert n <= len(wh)  # apply overdetermined constraint
    # 计算wh的标准差
    s = wh.std(0)  # sigmas for whitening
    # 聚类
    k = kmeans(wh / s, n, iter=30)[0] * s  # points
    assert n == len(k)  # kmeans may return fewer points than requested if wh is insufficient or too similar
except Exception:
    LOGGER.warning(f'{PREFIX}WARNING ⚠️ switching strategies from kmeans to random init')
    k = np.sort(npr.rand(n * 2)).reshape(n, 2) * img_size  # random init
wh, wh0 = (torch.tensor(x, dtype=torch.float32) for x in (wh, wh0))
k = print_results(k, verbose=False)

Loss

YOLO v5的loss也由三部分组成,Classes loss和Objectness loss都使用的是BCE loss,Location loss为CIoU loss。三个预测层的Objectness loss是有不同权重的,小中大分别是[4.0, 1.0, 0.4]。

YOLO v5更新了YOLO v3中已知偏移量 c x , c y , t w , t h c_{x},c_{y},t_{w},t_{h} cx,cy,tw,th计算预测bbox的公式,公式对比如下所示:

YOLO v3 YOLO v5
【YOLO系列】YOLO v5(网络结构图+代码)_第7张图片 【YOLO系列】YOLO v5(网络结构图+代码)_第8张图片

更新公式之后,中心点偏移量的取值范围由 ( 0 , 1 ) \left( 0, 1\right) (0,1)调整到 ( − 0.5 , 1.5 ) \left( -0.5, 1.5\right) (0.5,1.5),因此,偏移量更容易得到0或者1。在YOLO v3的box方程中,宽度和高度无上限,这是一个严重的缺陷,它可能会导致梯度失控、不稳定性、NaN loss等问题,并最终导致无效训练。

中心点对比 宽度和高度对比
【YOLO系列】YOLO v5(网络结构图+代码)_第9张图片 【YOLO系列】YOLO v5(网络结构图+代码)_第10张图片

参考

  1. ultralytics/yolov5
  2. Architecture Summary

你可能感兴趣的:(机器学习和深度学习之旅,YOLO,目标检测,深度学习,神经网络)