理解 YOLOv3 的训练输出日志信息


引言


YOLOv3 训练过程中输出在终端的不同的参数分别代表什么含义, 如何去理解这些参数? 也许对于使用 YOLO 很久的用户来说, 对这些概念依然很模糊.

下边训练中使用的 .cfg 文件(文件保存在在工程目录的 cfg/ 目录下):

[net]
# Training
batch=64
subdivisions=8
height=416
width=416
channels=3
momentum=0.9
decay=0.0005
angle=0
saturation = 1.5
exposure = 1.5
hue=.1

learning_rate=0.001
burn_in=1000
max_batches = 80200
policy=steps
steps=40000,60000
scales=.1,.1

以下是训练过程中终端输出的一个截图:

理解 YOLOv3 的训练输出日志信息_第1张图片

以上截图显示了所有训练图片的一个批次(batch), 批次大小的划分根据我们在 .cfg 文件中设置的 subdivisions 参数。在我使用的 .cfg 文件中 batch = 64 , subdivision = 8, 所以在训练输出中, 训练迭代包含了 8 组, 每组又包含了 8 张图片, 跟设定的 batch 和 subdivision 的值一致。

(注: 也就是说每轮迭代会从所有训练集里随机抽取 batch = 64 个样本参与训练, 所有这些 batch 个样本又被均分为 subdivision = 8 次送入网络参与训练, 以减轻 GPU 内存占用的压力).


Batch 输出


针对上图中最后一行中的信息, 我们来一步一步的分析。如下的输出是由 detector.c 生成的, 具体代码见:点击打开链接.

部分关键代码如下:

...

if (avg_loss < 0) avg_loss = loss;
avg_loss = avg_loss*.9 + loss*.1;

i = get_current_batch(net);

printf("%ld: %f, %f avg, %f rate, %lf seconds, %d images\n", 
        get_current_batch(net), 
        loss, 
        avg_loss, 
        get_current_rate(net), 
        what_time_is_it_now()-time, 
        i*imgs);
...
  • 9798: 指示当前训练的迭代次数;
  • 0.370096: 是总体的 Loss(损失);
  • 0.451929 avg: 是平均 Loss, 这个数值应该越低越好, 一般来说, 一旦这个数值低于 0.060730 avg 就可以终止训练了;
  • 0.001000 rate: 代表当前的学习率, 是在.cfg文件中定义的;
  • 3.300000 seconds: 表示当前批次训练花费的总时间;
  • 627072 images: 这一行最后的这个数值是 9798*64 的大小, 表示到目前为止, 参与训练的图片的总量.

以下输出是我在训练 VOC 时达到 283234 次迭代时候的输出:

283234: 0.783273, 0.827796 avg, 0.000020 rate, 1.650999 seconds, 33988080 images

可以看到 28W 次的训练之后, Loss 和 Avg Loss 并没有降低到 0.1 以下. 但是模型检测目标的准确率也已经很高了, 这就说明如果 Loss 和 Avg Loss 随着训练迭代次数的增加下降幅度变化很小, 这时就可以测试训练得到的模型了.

当然在实际应用过程中, 并不是 Loss 越低, 模型的精度和泛化性能越好.


Subdivision 输出


在分析 Subdivision 之前, 我们得了解一下 IOU(Intersection over Union, 也被称为交并集之比:点击打开链接), 这样就能理解为什么 Subdivision 中的参数是一些重要且必须要输出的参数了.

理解 YOLOv3 的训练输出日志信息_第2张图片

可以看到, IOU(交集比并集)是一个衡量我们的模型检测特定的目标好坏的重要指标。100% 表示我们拥有了一个完美的检测, 即我们的矩形框跟目标完美重合。很明显, 我们需要优化这个参数。

回归正题, 我们来分析一下这些用来描述训练图集中的一个 Batch 的训练结果的输出。那些想自己深入源代码验证我所说的内容的同学可以查看这段代码:点击打开链接, 重要的实现部分摘录如下: 

*(l.cost) = pow(mag_array(l.delta, l.outputs * l.batch), 2);
printf("Region %d Avg IOU: %f, Class: %f, \ 
        Obj: %f, No Obj: %f,  \
        .5R: %f, .75R: %f, count: %d\n", 
        net.index, avg_iou/count, avg_cat/class_count, 
        avg_obj/count, avg_anyobj/(l.w*l.h*l.n*l.batch), 
        recall/count, recall75/count, count);

输出信息的数量是: subdivisions * ngpus * 3, 最小单元包含三条信息, 分别是:

Region 82 Avg IOU: 0.759600, Class: 0.809470, Obj: 0.732717, No Obj: 0.002799, .5R: 1.000000, .75R: 0.500000,  count: 4
Region 94 Avg IOU: 0.699416, Class: 0.917663, Obj: 0.226457, No Obj: 0.000643, .5R: 1.000000, .75R: 0.333333,  count: 6
Region 106 Avg IOU: 0.667185, Class: 0.959919, Obj: 0.089371, No Obj: 0.000099, .5R: 1.000000, .75R: 0.000000,  count: 1

以上信息表示三个不同尺度(82, 94, 106)上预测到的不同大小的框的参数.

  • 82 卷积层为最大的预测尺度, 使用较大的 mask, 但是可以预测出较小的物体;
  • 94 卷积层为中间的预测尺度, 使用中等的 mask;
  • 106卷积层为最小的预测尺度, 使用较小的 mask, 可以预测出较大的物体.

上述输出信息的各个参数含义是(主要观察某一个尺度上的参数), 下面就 Region 82 分析:

  • Region Avg IOU: 0.326577: 表示在当前 subdivision 内的图片的平均 IOU, 代表预测的矩形框和真实目标的交集与并集之比, 这里是 75.96%, 这个模型此时已经达到了很高的训练精度;
  • Class: 0.809470: 标注物体分类的正确率, 期望该值趋近于1;
  • Obj: 0.732717: 越接近 1 越好;
  • No Obj: 0.002799: 期望该值越来越小, 但不为零;
  • .5R: 1.000000: 是在 recall/count 中定义的, 是当前模型在所有 subdivision 图片中检测出的正样本与实际的正样本的比值。在本例中, 全部的正样本被正确的检测到。
    count: 4: 所有当前 subdivision 图片(本例中一共 8 张)中包含正样本的图片的数量。 在输出 log 中的其他行中, 可以看到其他 subdivision 也有的只含有 6 或 1 个正样本, 说明在 subdivision 中含有不包含在检测对象 classes 中的图片。

参考资料

[1]. 理解 YOLOv2 训练过程中输出参数含义
[2]. YOLOv3 训练过程中重要参数的理解和输出参数的含义
[3]. https://timebutt.github.io/static/understanding-YOLOv3-training-output/

你可能感兴趣的:(深度学习,YOLO,源码分析,-,入门之路,YOLO,-,darknet,源码阅读)