YOLOv5_DEPTH_ANALYSIS

Yolov5深度剖析

一、评估方式

1. 混淆矩阵(confusion_matrix)

混淆矩阵是对分类问题预测结果的总结。使用计数值汇总正确和不正确预测的数量,并按每个类进行细分,显示了分类模型进行预测时会 对哪一部分产生混淆。通过这个矩阵可以方便地看出机器是否将两个不同的类混淆了(把一个类错认成了另一个)。混淆矩阵不仅可以让 我们直观的了解分类模型所犯的错误,更重要的是可以了解哪些错误类型正在发生,正是这种对结果的分解克服了仅使用分类准确率带来 的局限性(总体到细分)。

混淆矩阵

比如上图中的Y轴代表预测类别,X轴代表真实类别,从上图中可以看到call与play均存在0.01%比列的目标存在漏报。并且其中玩手机存在大量不存在该行为的目标被识别为存在该行为的现象。

2. F1分数(F1_curve)

F1分数与置信度之间的关系。F1分数(F1-score)是分类问题的一个衡量指标,是精确率precision和召回率recall的调和平均数,最大为1,最小为0, 1是最好,0是最差。

F1_curve

3. 标注统计数据(labels)

labels

4. 体现中心点横纵坐标以及框的高宽间的关系(labels_correlogram)

表示中心点坐标x和y,以及框的高宽间的关系。每一行的最后一幅图代表的是x,y,宽和高的分布情况,对应关键图的说明如下:

correlogram

5. 单一类准确率(P_curve)

准确率曲线图,当判定概率超过置信度阈值时,各个类别识别的准确率。当置信度越大时,类别检测越准确,但是这样就有可能漏掉一些判定概率较低的真实样本。

6. 单一类召回率(R_curve)

召回率曲线图,当置信度越小的时候,类别检测的越全面(不容易被漏掉,但容易误判)。

7. 精确率和召回率的关系图(PR_curve)

R曲线体现精确率和召回率的关系。mAP 是 Mean Average Precision 的缩写,即 均值平均精度。可以看到:精度越高,召回率越低。我们希望:在准确率很高的前提下,尽可能的检测到全部的类别。因此希望我们的曲线接近(1,1),即希望mAP曲线的面积尽可能接近1。

8. 结果Loss(results)

results

二、基础知识

1.相关配置

首先我们通过打开对应模型的配置文件,如yolov5s.yaml文件,我们可以针对其中的参数进行分析,首先是关键的参数。即针对网络 模型的宽度以及程度的控制参数,本质上yolo模型的网络构成是一致的,其主要是对应的深度以及宽度的差异导致模型的复杂度的差异性。

depth_multiple: 模型层数因子(用来调整网络的深度),再后续的backbone以及head中会有网络的数量,该数量将会与这里的因子关联,从而 导致具体的网络的深度存在差异性;
width_multiple: 模型通道数因子(用来调整网络的宽度),用于控制backbone以及head模型的输出通道数,从而影响特征图的宽度,从而导致其 可携带的信息减少;

不同的网络主要是依据上面2个核心参数决定其复杂度以及准确度,主要为yolov5nyolov5syolov5myolov5l等。

2.锚框Anchors

通过yolov5s.yaml可以观察到默认的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

其代后面的注释代表P3为层数,/后面的数字为下采样率,8代表按照原图1/8缩放。其默认初始化了9个anchors,分别在三个特征图(feature map) 中使用,每个feature map的每个grid cell都有三个anchor进行预测。分配规则:

针对其中所提及的特征图的含义可以通过通道与特征图学习了解,进一步完善相关基础知识。

3.网络构成

通过yolov5s.yaml可以发现其通过配置实现网络模型的构成,为此我们需要了解其中所代表的含义,下面截取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]],  # 9

上述的结构按照顺序主要代表的含义如下:

举例我们有这么一个模块对应的参数如何对照到其中并影响,比如模块的入参要求如下。

class Conv(nn.Module):
    # Standard convolution
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groups
        """
        @Pargm c1: 输入通道数
        @Pargm c2: 输出通道数
        @Pargm k : 卷积核大小(kernel_size)
        @Pargm s : 卷积步长 (stride)
        @Pargm p : 特征图填充宽度 (padding)
        @Pargm g : 控制分组,必须整除输入的通道数(保证输入的通道能被正确分组)
        """
        pass

width_multiple设置为0.5,该模块在yaml中的参数为[64, 6, 2, 2]首先输入通道数是由上层决定所以默认会在此参数前追加,对应的64代表 输出的通道数,但是实际输出的通道数是64*0.5=32通道数,从而控制了通道数,即宽度。

depth_multiple则是与模块的数量进行计算,其计算的代码如 n = n_ = max(round(n * gd), 1) if n > 1 else n比如某个 模块设置的数量是4,对应的深度为0.5那么通过上述的公式最终实际的数量就为2了。

三、经验集合

1. 数据集标准

参考文献

返回首页 发表评论

评论与讨论