YOLO v3算法介绍

图片来自https://towardsdatascience.com/yolo-v3-object-detection-with-keras-461d2cfccef6

YOLO v3同时构建了三个不同尺度(13\times 13,\space 26\times 26,\space 52\times 52)的探测器来进行目标检测,每个探测器的网格内嵌入了3个anchor box,假设要检测的类别数为80,则探测器每个网格内的输出格式如上图所示。需要注意的是YOLO v3的网络架构在每个网格上直接输出的是一个255维的向量,在后续计算中转化成了如上图所示的385列的矩阵。

YOLO v3共有9个anchor box,按照大小不同分配给三个探测器,最大的3个分配给13\times 13的探测器,中间的3个分配给26\times 26的探测器,最小的3个分配给52\times 52的探测器。YOLO v3中anchor box的确定方法是对训练集上的所有真实box进行聚类,将每个类的中心设为anchor box。聚类距离通过IoU来定义,IoU越大,距离越小:\large{d(\text {box}, \text {centroid})=1-\operatorname{IoU}(\text {box}, \text {centroid})}IoU的定义如下图所示:

本文主要介绍以下四部分内容:

  • 1. YOLO v3的数据前处理
  • 2. YOLO v3的网络架构
  • 3. YOLO v3的损失函数设计
  • 4. 使用YOLO v3预测新的图片



1. 数据前处理

输入的图片维数:(416, 416, 3),输入的图片标注:[(x_1, y_1, x_2, y_2, class{\_}index), (x_1, y_1, x_2, y_2,class{\_}index), \ldots, (x_1, y_1, x_2, y_2,class{\_}index)]表示图片中标注的所有真实box,其中class{\_}index代表对应的box所属的类别,(x_1, y_1)表示对应的box左上角的坐标值,(x_2, y_2)表示对应的box右下角的坐标值

前处理中最重要的一步就是将图片标注转化为模型的输出格式。首先要确定每个真实box对应哪个anchor box (与box的IoU最大的那个anchor box),然后将box的信息写在对应的anchor box的位置。

点击查看代码




2. 模型架构

YOLO v3的架构搭建主要分为两个部分,第一部分基于Darknet网络构建52\times 52, \space 26\times 26, \space 13\times 13的特征图,第二部分构建基于这三类特征图的探测器,如下图所示:

图片来自https://towardsdatascience.com/dive-really-deep-into-yolo-v3-a-beginners-guide-9e3d2666280e (对其中的错误进行了修正)

点击查看代码




3. 损失函数

YOLO v3中的损失函数有许多不同的变种,这里选取一种比较经典的进行介绍。损失函数可以分解为边框损失、目标损失以及分类损失这三项之和,下面对这三项逐一进行介绍。

边框损失:原始论文中使用MSE(均方误差)作为边框的损失函数,但是不同质量的预测结果,利用MSE有时候并不能区分开来。使用IoU更能体现回归框的质量,并且具有尺度不变性,但是IoU仅能描述两个边框重叠的面积,不能描述两个边框重叠的形式;并且若两个边框完全不相交,则IoU为0,不适合继续进行梯度优化。GIoU (Generalized IoU)继承了IoU的优点,并且一定程度上解决了IoU存在的问题:\large{GIoU=IoU-\frac{|C \backslash(B_1 \cup B_2)|}{|C|}}其中C为包含B_1B_2的最小封闭形状。边框损失可表示为1-GIoU,下面以13\times 13这一检测器为例来计算边框损失,总的边框损失为三个检测器的损失之和。

要计算边框损失,首先要对YOLO v3的网络输出进行转换,假设网络输出的边框信息为(t_x,t_y,t_w,t_h),其中(t_x,t_y)为边框中心点信息,(t_w,t_h)为边框的宽度和高度信息,转换公式如下所示:\large{ \begin{cases} b_x=sigmoid(t_x)+c_x \\ b_y=sigmoid(t_y)+c_y \\ b_w=p_w\exp (t_w) \\ b_h=p_h\exp (t_h)\end{cases} }其中(c_x,c_y)表示(t_x,t_y)所在网格的左上角那个点的坐标位置,(p_w,p_h)表示边框对应的anchor box的宽度和高度。

点击查看代码

接下来计算网络输出的边框与真实边框的GIoU,进而得到边框损失:

点击查看代码


目标损失:仍以13\times 13这一检测器为例来计算,目标损失实际上是一个不平衡二分类问题,因为一般来说检测器的13\times 13\times 3个anchor box内真实对象(正样本)的数量要远小于没有真实对象(负样本)的数量。采用Focal Loss来处理这一问题,Focal Loss对难分类的样本采用较大的权重,对易分类的样本采用较小的权重:\large{FL(p)=\left\{\begin{aligned}-(1-p)^{\gamma} \log (p), & \text { positive samples } \\ -p^{\gamma} \log (1-p), & \text { negative samples }\end{aligned}\right.}Focal Loss还有另外一种公式,即在上述基础上引入类别权重\alpha\large{FL(p)=\left\{\begin{aligned}-\alpha(1-p)^{\gamma} \log (p), & \text { positive samples} \\ -(1-\alpha) p^{\gamma} \log (1-p), & \text { negative samples }\end{aligned}\right.}本文采用第一种公式,并将\gamma设为2。另外在目标损失的计算过程中对负样本的定义进行了一定修改,如果一个anchor box内没有真实对象,但它预测的边框和对应的探测器上的某个真实边框有较大的IoU,那么就不把它作为负样本,从而在损失计算过程中忽略它,这也在一定程度上减少了负样本的数量。

点击查看代码


分类损失:仍以13\times 13这一检测器为例来计算,使用交叉熵损失函数,值得注意的是在YOLO v3的类别预测中使用sigmoid作为激活函数代替之前的softmax,主要是因为不同的类别不一定是互斥的,一个对象可能会同时属于多个类别。

点击查看代码

综合上述的三类损失,可以计算出在13\times 13探测器上的总损失,其余两个探测器(26\times 26,\space 52\times 52)上的损失可采取同样的方法计算,三个探测器的总损失为:





4. 模型预测

同损失函数那一部分中的介绍,首先将网络输出的格式进行转换:

点击查看代码

接下来删除得分较低的预测box,得分通过box内为真实对象的概率乘以最大的类别概率进行确定

点击查看代码

对剩余的预测box进行Non-Maximum Suppression (NMS),NMS的主要目的是去除预测类别相同但是重叠度比较大的box: 

点击查看代码




参考资料

Leave a Comment

Your email address will not be published. Required fields are marked *