PyTorch实现YOLOV3

YOLOV3的实现教程

Posted by BY on August 10, 2018

感谢

学习对象检测的最佳方式是从头开始实现算法。 我们将使用PyTorch从头开始实现YOLO(v3)对象检测器,YOLOv3是一种更快的对象检测算法。


本教程分为5个部分:

第1部分(本章):了解YOLO的工作原理 第2部分:创建网络体系结构的层 第3部分:实现网络的正向传递 第4部分:对象分数阈值和非最大抑制 第5部分:设计输入和输出管道

先决条件

1.您应该了解卷积神经网络的工作原理。这还包括残差块,跳过连接和上采样的知识。 2.什么是对象检测,边界框回归,IoU和非最大抑制。 3.基本的PyTorch用法。您应该能够轻松创建简单的神经网络

什么是YOLO?

YOLO代表你只看一次。它是一个物体探测器,它使用深度卷积神经网络学习的特征来探测物体。在我们弄清楚代码之前,我们必须了解YOLO的工作原理。

完全卷积神经网络

YOLO仅使用卷积层,使其成为完全卷积网络(FCN)。它有75个卷积层,具有跳过连接和上采样层。不使用任何形式的池化层,并且使用具有步幅2的卷积层来对特征图进行下采样,这样可以有助于因为池化层所造成的低层语义特征的丢失。

作为FCN,YOLO对输入大小的大小保持不变。然而,在实践中,当我们实现算法时由于在前端可能会遇到的各种问题,我们通常希望输入大小保持不变。

这些问题中的最重要一点是,如果我们想要批处理我们的图像(GPU可以并行处理批量图像,从而提高速度),我们就需要具有固定宽与高的图像。这需要连接多副图像为一个大的块,对应于将多个PyTorch张量连接成一个。 网络中对图像的下采样是通过网络步幅因子实现的。例如:如果网络的步幅为32,那么输入为416×416的图像将会产生大小为13×13的输出。

解释输出

通常,(对于所有的目标检测器而言),由卷积学习到的特征被传递到分类器/回归器上,该分类器/回归器进行检测预测(边界框的坐标,类别的标签)。 在YOLO中,通常使用1×1的卷积层来完成预测。 现在,首先需要注意的是我们的输出是一个特征图。由于我们使用了1×1卷积层,因为预测图的大小正好等于之前特征图的大小。在YOLOV3(及其后代)中,您解释此预测图的方式是每个单元格可以预测固定数量的边界框。 在特征图中,我们有(B*(5+C))个元素。B代表了每个元可以预测的框的数量。由论文可知,这些B框的每一个都可以专门检测一个确切的类别种类。每一个框有5+C个属性,描述了每一个框的中心坐标,维度,坐标分数和C类别置信度。YOLOV3为每一个元格预测3个边界框。

如果目标的中心落在该单元格的感知区域中,您希望特征图的每一个单元格可以通过其中一个边界框预测目标。 这与YOLO的训练方式有关,其中只有一个边界框负责检测任何给定的对象。首先,我们必须确定这个边界框属于哪个单元格。

为此,我们将输入图像划分为网格维度等同于最终特征图大小的网格。 显示 然后,包含了目标真实坐标框中心的输入图像上的单元格被选定用于预测目标。在图像中,此单元格被标记为红色,包含了真实坐标框的中心坐标。(被标记为黄色) 现在,红色的单元格位于图中网络单元的第7列和第7行。我们现在将特征图山的第7行,第7列的单元格作为检测狗的单元格。 现在,这个单元格可以预测三个边界框。哪一个被安排为狗的真实标签呢?为了便于理解,我们需要理解锚点的概念。

说明

这里我们所说的单元格指的是在预测特征图上的单元格。我们将输入图像分割成网格去决定预测特征图上的哪一个单元格来负责检测。

锚点

预测边界框的宽度和高度可能是有意义的,但是在实践中,这导致了训练时梯度的不稳定性。相反,大部分的现代检测器预测log空间变换,或者叫做锚点的预定义的默认边框的偏移。

然后,这些变换被应用到锚点框获得预测结果。YOLOV3有三种锚点框,对每一个单元格产生了三个边界框的预测结果。 回到我们之前的问题,负责检测狗的边界框是与真实边界框有着最高IOU的锚点。

预测

下边的公式描述了网络输出是怎么转化从而获得边框预测值的。 display bx,by,bw,bh是预测的x,y的中心联合坐标,宽与高。tx,ty,tw,th是网络的输出。cx,cy是网格的左上角坐标。pw,ph是该框的锚点维度。

中心坐标

注意到我们通过sigmod函数运行我们的中心坐标预测。这强制了输出值位于0到1之间。为什么会是这样呢? 一般情况下,YOLO并没有预测边界框中心的绝对坐标值。它预测了偏移量: 1.对用来预测目标的单元格左上角坐标的相对值 2.由特征图单元格维度进行标准化 例如,考虑我们狗的图像,如果预测的中心坐标为(0.4,0.7),这意味着在13×13特征图上中心坐标在(6.4,6.7)。(因为红色单元格的左上角坐标为(6,6))。 但是,如果预测到的x,y坐标值大于1呢?假设是(1.2,0.7)。这意味着中心坐标是(7.2,6.7)。注意位于单元格的中心现在位于红色单元格的右边,在第7行的第8个单元格。这违反了YOLO的理论。因为如果我们假设红色框负责预测狗的话,狗的中心坐标必须位于红色单元格内,而不是位于旁边。 因此,为了解决这个问题,输出必须经过sigmod函数,这将输出强制压缩在0到1之间,有效的将预测中心保持在单元格中。

边界框的维度

通过对输出应用对数空间变换然后乘以锚点得到预测的边界框的维度。 display 检测器输出是如何转化给出最终预测结果。图像来源 由此产生的预测,bw与bh,由图像的高与宽进行标准化。(以这种方式选择训练标签)。所以,如果预测的包含狗的边界框的bx与by是(0.3,0.8),然后实际的13×13特征图上的宽与高是(13×0.3,13×0.8)。

目标分数

目标分数代表了目标落在检测框里的概率。对于红色和相邻的网格,它应该接近于1,而对于其它角落处的网格来说,应该接近于0. 目标分数也是通过sigmoid函数,被解释为概率。

类别置信度

类别置信度代表了检测到的目标属于一个特定类的概率。在V3之前,YOLO用softmax类别分数。 然而,这个设计在V3中被抛弃了,相反作者选择了sigmod。Softmax类别分数假设类别是互斥的。换句话说,如果一个目标属于一个类,那么它就不属于其他类。这对于将用作我们的基检测器的COCO数据集来说是正确的。 然而,当我们的类别里有女人或者人,这个假设可能不成立。这就是作者坚持用Softmax的原因。

不同尺度之间的预测

YOLO V3在3个不同尺度之间进行预测。检测层用来在三个不同大小的特征图之间进行预测,各自的步幅为32,16,8.这意味着,对于大小为416×416的图像来说,我们在大小为13×13,26×26,52×52的特征图上进行检测。 直到第一检测层,网络对图像进行下采样,在步幅为32的特征图上进行检测。进一步,用上采样因子2对该层上采样然后与之前有同样大小的特征图进行联接。此时,另一个检测在步幅为16的特征图上进行。重复相同的上采样步骤,最后的检测在步幅为8的特征图上进行。 在每一个尺度,每个单元格用3个锚点预测3个边界框,使得总的锚点为9.(锚点在不同尺度下是不同的) display display 作者报告这帮助YOLO V3在检测小目标时表现更好,解决了早期YOLO版本所面临的问题。上采样可以帮助网络学习细粒度的特征,这些特征有助于检测小物体。

输出处理

对于大小为416×416的图像,YOLO预测((52×52)+(26×26)+(13×13))×3 = 10647个边界框。然而,在我们的图像例子中,仅有一个目标,狗。我们怎样将检测个数从10647减到1呢?

通过目标置信度的阈值处理

首先,我们基于目标检测分数进行边界框的过滤。一般来将,边界框的分数低于某个阈值的直接过滤掉。

非最大值抑制

NMS旨在解决同一图像的多个检测问题。例如,红色网格的三个边界框可能检测到一个框或者其相邻的单元格也会检测到相同的目标。 display

我们的实现

YOLO只能检测用来训练网络的训练集里出现过的类别。我们将用官方权重文件作为我们的检测器。这些权重通过训练coco数据集获得,因此,我们可以检测80个类别。

这是第一部分,这部分解释了关于YOLO算法部分。然而,如果你想深入了解YOLO是怎样工作与训练的,以及与其它检测器对比时的表现,你可以去读原始论文。

下一部分,我们将实现组成检测器的各种层。