YOLOv3算法论文笔记及算法细节梳理

YOLOv3算法笔记

1.YOLOv3算法论文笔记

摘要

对YOLO进行l了一些更新,网络有点大,但速度还是比较快。
注:其实YOLOv3不再追求那么高的速度了,而是在保证实时性的基础上,尽量提高准确性。

1.1介绍

对YOLO进行了改进,没什么超级有趣的东西,只是一些使效果更好的小改动。论文首先解释了YOLOv3的要点,然后描述了是怎样做的,接着讨论一些尝试了但没有用的技巧,最后,思考着意味着什么。

1.2The Deal(要点,想法)

YOLOv3的deal:借鉴他人的好idea,并训练一个新的分类网络,其性能比其它网络都好。

1.2.1 Bounding Box Prediction

边界框回归。
锚框的设置、边界框坐标的预测方法和YOLOv2一样,但边界框目标性分数预测不一样。

在这里插入图片描述
在这里插入图片描述

YOLOv3使用logistic regression预测每个边界框的目标性分数(objectness score)。如果一个先验框与ground truth框的重叠最大(大于其它先验框),则这个框的目标得分应该是1。如果一个先验框与真实框的IOU并不是最大的,但是IOU的值超过了阈值,那么忽略它的预测。我们将阈值设置为0.5。(论文中此处的描述比较模糊,详见本文2.3.1节正负样本的确定)

我们仅仅给一个ground truth框分配一个先验框,也就是说,一个目标仅仅用一个先验框去预测。如果一个先验框没有分配到一个ground truth框,那么它在坐标和分类概率上没有损失,仅仅有目标性的损失。

1.2.2 Class Prediction

每个边界框,使用多标签分类器,来预测边界框可能包含的类别。我们不使用softmax,它对实现好的性能不是必要的。我们简单的使用独立的logistic classifier。在训练时,类别预测使用二值交叉熵损失。

当采用复杂的数据集如Open Images Dataset时,这种形式很有帮助。因为有很多重叠标签(如女人和人)。使用softmax会强加假设:每个框只有精确的一个类别,而不可能是其它类别。而多标签分类方法能更好的模拟数据。

1.2.3 Predictions Across Scales

YOLOv3在3个不同的尺度上进行预测,使用类似特征金字塔网络(FPN)的概念来提取特征。从基础的特征提取网络添加几个卷积层。最后的预测是3d的张量,编码了边界框、目标性、类别概率预测。我们的实验中,COCO数据集上每个尺度预测3个框,所以张量为 ,用于4个边界框偏移,1个对象预测和80个类别预测。

网络早期的特征图,与2倍上采样后的网络末端特征图,进行张量拼接,以拼接后的特征图进行预测。这种方法可以从上采样特征中获得更多的语义信息,并从早期特征图中获得细粒度信息。

上述方法再进行一次,得到第3个尺度。

我们仍然使用k-means聚类获得先验边界框,但是取k=9,即9个先验框,每个尺度上3个先验框。在COCO数据集上,这9个聚类中心先验框为(10×13)、(16×30)、(33×23)、(30×61)、(62×45)、(59×119)、(116×90)、(156×198)、(373×326)。

1.2.4 Feature Extractor

提出了一个新的网络Darknet-53,是YOLOv2,、Darknet-19和残差网络的混合结构。使用连续的3x3卷积核1x1卷积,以及一些shortcut连接(张量相加),网络有点大。如下图所示,注意,这里的是分类网络,图像输入尺寸为224x224。

注意:原论文说有53个卷积,其实是说错了,应该是52个卷积+1个全连接,总之叫Darknet-53。检测网络最后用的只是卷积层,也就是前52层。
注意,网络中没有最大池化层,2倍的下采样通过卷积步长为2获得。
在这里插入图片描述
可以看出,每个残差块集合之间的卷积负责缩小特征图,也就是下采样,Darknet-53共有5次下采样,下采样率为32。

1.2.5训练

仍然在整张图像上进行训练,不使用硬性负样本挖掘。**使用多尺度训练、大量的数据增强、BN、还有其它标准东西。**使用Darknet神经网络框架。

1.3 How we do

YOLOv3非常好,见表3。
在这里插入图片描述
在COCO奇怪的mean AP度量标准上,YOLOv3和SSD变体一样,但速度是其3倍快,不过相比RetinaNet等模型性能还是差一点。

但是,如果我们使用IOU=0.5的mAP度量标准(或者AP50),YOLOv3和RetinaNet等模型差不多,远大于SSD变体。这意味着YOLOv3是一个很强的检测器,擅长产生对目标还不错的边界框。但当IOU阈值提高时,性能下降非常严重,这意味着YOLOv3无法产生完美对准的框。

以前的YOLO算法很难检测小目标,但现在,似乎形式发生了逆转。使用多尺度预测,YOLOv3在小目标的精度上较高,但在中目标和大目标的精度上相对较差。

1.4 ThingsWe Tried That Didn’t Work

1.4.1 Anchor box x,y offset predictions

我们尝试使用普通的锚框预测机制,使用线性激活,将(x,y)坐标的偏移,预测为锚框的宽和高的倍数。但这降低了模型的稳定性,效果不好。

1.4.2 Linear x,y predictions instead of logistic

使用线性激活来直接预测x,y的偏移,而不是使用logistic激活,但这降低了mAP 2个点。

1.4.3 Focal loss

这降低了mAP 2个点。这可能是因为YOLOv3对Focal loss要解决的问题足够鲁棒了,因为YOLOv3将目标性预测和条件类别预测分开了。因此大多数样本(负样本)没有分类损失?或者其它原因?论文不太确定。

注意:Focal loss主要是为了解决one-stage目标检测中正负样本比例严重失衡的问题。该损失函数降低了大量简单负样本在训练中所占的权重,也可理解为一种困难样本挖掘。

1.4.4 Dual IOU thresholds and truth assignment

双IOU阈值分配。Faster R-CNN在训练时使用两个IOU阈值,如果预测结果与ground truth的IOU高于0.7,那么是个正样本,如果小于0.3,是个负样本,0.3~0.7之间忽略掉。我们使用了相似的策略,但效果不好。

2.YOLOv3算法梳理

2.1核心思想

(1)使用新的特征提取网络;
(2)使用了多个尺度的特征图进行预测,提高了小目标的检测性能。

2.2网络设计

参考文献:https://blog.csdn.net/leviopku/article/details/82660381
YOLOv3可以有不同的尺寸的输入图像,如608x608,或者416x416。
416x416的输入如下图所示,此图来自上面列出的参考文献。
在这里插入图片描述
需要注意以下几点

2.2.1下采样

(1)下采样方法
基础版本的YOLOv3网络,是通过设置卷积步长为2,来达到下采样的目的,下采样率为2。

但是YOLOv3-tiny网络,是通过最大池化完成下采样的。

(2)下采样的位置
整个网络,只有Darknet-53部分会有下采样,并且是resn组件中的DBL模块进行下采样。

网络输出有3个分支,最小的特征图进行了5次下采样,下采样率为32;最大的特征图仅进行了3次下采样,下采样率为8。

(3)ZeroPadding层
从网络中可以看到,在每次进行下采样之前,特征图会先通过一个ZeroPadding层,这个ZeroPadding层会在特征图的左上角点分别填充一行、一列全0值。

这主要是因为,进行下采样时,输出特征图的尺寸减半,因此下采样层调用Conv2D函数时,参数stride选择(2,2),padding参数只能选择’valid’而不能选择’same’。但是选择’valid’有可能导致输出的特征图不是输入的一半,因此在下采样之前进行ZeroPadding。

举个例子,假设输入特征图尺寸为416x416,如果不进行ZeroPadding层,下采样层的卷积padding参数选择’valid’,卷积核大小为3,stride为2,那么 (416-3)/2 + 1,为207,即输出特征图的尺寸为207x207。

如果进行ZeroPadding层,输入特征图尺寸为416x416,通过ZeroPadding层后变为417x417,再进行下采样,(417-3)/2 + 1,为208,即输出特征图的尺寸为208x208,刚好为输入尺寸的一半,下采样率为2。

2.2.2上采样

YOLOv3需要使用上采样,上采样率为2。原作者的C代码中采用的上采样策略,是简单的最近邻插值,也就是,输入特征图的每个元素复制4份进行输出。

2.2.3激活函数

YOLOv3网络大多数时候使用LeakyReLu激活函数,系数为0.1。只有用于预测输出的卷积层使用线性激活(不激活),也就是说,YOLOv3的3个预测分支的最后一个卷积层使用线性激活。

2.2.4残差结构

YOLOv3使用的残差块,它的shortcut连接是在第二个卷积的激活函数进行的,与标准的ResNet网络采用的shortcut连接不同。将官方的YOLOv3网络结构进行可视化,其shortcut连接如下图所示(图中的YOLOv3采用608x608尺寸的输入图像)。
在这里插入图片描述

2.2.5 卷积核的bias参数

YOLOv3的卷积核不使用bias,这主要是因为使用了BN层,就没有必要再用bias了。

2.2.6卷积核参数的正则化

YOLOv3的卷积核使用L2核正则化,正则化系数为10-4。

2.3损失函数

2.3.1 正、负、忽略样本的确定

论文中对这块的描述很不清晰,通过分析原作者C代码(详见./darknet/src/yolo_layer.c文件中的forward_yolo_layer函数)可知,YOLOv3中的预测框总共可以分为正样本、负样本、忽略样本。正样本具有边界框中心坐标、宽高、置信度、分类损失,负样本只有置信度损失,忽略样本没有任何损失。

2.3.1.1正样本

正样本是通过锚框和groundtruth框的iou来确定的。对输入图像的每个groundtruth框,计算其和9个锚框的iou,iou最大的锚框负责预测该目标,该锚框输出的预测边界框即为正样本。正样本只依赖于锚框和groundtruth框,可以在训练之前确定。

可以根据正样本的在网络输出特征图中的位置,将groundtruth框转化为网络输出的格式(但实际代码中只是进行了一定程度的转化,并没有完全转化为与网络直接输出对应的真值,因为涉及到sigmoid函数的逆运算,比较麻烦)。

特别注意:这里计算的是锚框和groundtruth框的iou。因为YOLOv3中使用的锚框只有宽、高,没有x、y坐标,因此计算iou时,只是简单的把锚框和groundtruth框的中心坐标对齐,然后再计算iou。

但是确定负样本和忽略样本时,计算的是预测框和groundtruth框的iou,它们都具有中心坐标,因此不需要对齐中心坐标

2.3.1.2负样本

在所有的预测框中,除了正样本,剩下的就是负样本或者忽略样本。也就是说,在除了正样本之外的预测框中,通过以下方法确定负样本和忽略样本

负样本是通过预测框和groundtruth框的iou来确定的。经过一次前向传播后,将所有的预测框提取出来(其实只将非正样本的预测框提出来就好),对每个预测框,计算其和所有的groundtruth框的iou,如果最大的iou都小于忽略阈值,那么这个预测框就是负样本。

由于负样本依赖预测框和锚框,只能在训练过程中才能确定。

2.3.1.3忽略样本(忽略阈值论文中取0.5,但是官方.cfg文件中取得是0.7)
在所有的预测框中,除了正样本,剩下的就是负样本或者忽略样本。也就是说,在除了正样本之外的预测框中,通过以下方法确定负样本和忽略样本。

确定完了正负样本,剩下的就是忽略样本。可以看出,忽略样本和负样本的确定方法基本一致,只是忽略样本和groundtruth框的iou是大于忽略阈值。

由于忽略样本依赖预测框和锚框,只能在训练过程中才能确定。

为什么要引入忽略样本呢????

查看了大量博客之后,我比较相信以下几种观点:
(1)降低负样本的数量。一张图像中,groundtruth是很少的,也就是说,正样本比较少。而YOLOv3(416x416的输入尺寸)一次性输出了(13x13+26x26+52x52)x3=10647个预测框,如果没有忽略样本,可能会产生严重的正负样本不平衡问题。

(2)减少对网络训练的不正确监督。这句话的是说,假如一个正样本与groundtruth框的iou为0.98,而一个忽略样本的iou为0.95,如果不采用忽略样本,而是将其作为负样本,那么就会迫使网络认为这个与groundtruth框相差不大的预测框为背景,而实际上,这个预测框相当大一部分为目标,因此会导致网络学习效果不理想。

2.3.2 边界框的编解码

下图来自YOLOv3论文。
在这里插入图片描述
置信度的解码如下:
在这里插入图片描述

说明:t指的是网络的直接输出值, b是解码后的预测框(中心坐标是相对于图像的,宽高是绝对值), p是锚框。

需要注意**!!!**YOLOv3网络卷积输出层使用的是线性激活,也就是不激活,因此我们需要牢牢记住,网络的直接输出值,是没有经过任何激活函数处理的

YOLOv3每个边界框预测值包括5部分:边界框中心坐标x,y,边界框宽高w,h,置信度c,条件类别概率向量C。在COCO数据集中,有80个类别,因此每个预测框输出(4+1+80)个预测值。

2.3.3 损失函数计算

2.3.3.1参考文献

这里给出2篇非常棒的知乎帖子,下面的绝大部分内容,都是来自这2篇帖子。
(1)https://zhuanlan.zhihu.com/p/142662181
该篇文章从原作者C代码的角度,详细分析了边界框中心坐标x,y损失的所产生的的梯度,由此确定,边界框中心坐标x,y使用的是二值交叉熵损失,而不是有些博客中说的均方误差损失(注意,这篇帖子里有个错误,就是边界框的宽高用的是均方误差损失,不是帖子里说的二值交叉熵损失)。

注意!!!原作者的C代码中,损失l.cost这块代码(详见./darknet/src/yolo_layer.c文件中的forward_yolo_layer函数)写的非常玄学!首先,在形式上,l.cost非常像均方误差损失,而且是x,y,w,h,c和C的损失都像是均方误差损失,但通过分析梯度我们可知,边界框中心坐标x,y使用的是二值交叉熵损失。

那为什么原作者的C代码中还给出了非常像均方误差损失的l.cost呢?

作者好像没有用l.cost来求梯度(也可能我漏看了程序),作者直接给出了梯度的代码,我们本来要的就是梯度而不是损失,损失只是用来计算梯度的,既然得到了梯度,那还求损失干什么?

因此,我个人认为,代码中像均方误差损失的l.cost,可能并没有用来求梯度,实际上x,y,c和C使用的仍然是二值交叉熵损失,只有w,h使用的是均方误差损失。大家看到l.cost后,千万不要想当然的认为x,y,w,h,c和C使用的都是均方误差损失。

(2)https://zhuanlan.zhihu.com/p/143106193
该篇文章给出了推导出的损失函数公式(注意,本篇帖子关于正负样本确定的描述有些问题,正确的方法参考本文所述内容)。

2.3.3.1 损失函数形式

(1)边界框中心坐标x,y:使用二值交叉熵损失。
(2)边界框宽高w,h:使用均方误差损失。
(3)置信度c:使用二值交叉熵损失。
(4)类别概率向量C:对每个分类使用二值交叉熵损失。

2.3.3.2 损失函数公式

以下来自第2篇参考知乎帖子(对公式作了部分符号更改,并修正了原公式的权重错误)。
在这里插入图片描述
(1)损失中的网络输出说明
首先,带^的是网络预测值,但并不都是网络的直接输出值,网络的直接输出卷积层使用线性激活(不激活)。

(不想再用csdn的公式编辑器敲一遍公式,大家看下图)

(2)损失中的标签数据说明
在这里插入图片描述
在这里插入图片描述

(3)损失中的权重说明
在这里插入图片描述

为什么要加上这个权重呢???

因为小尺度的边界框的偏差,要比大尺寸的边界框的偏差,产生的影响要大,因此,添加上述权重因子,提高小目标损失的权重,增强网络对小目标的检测能力。

2.4YOLOv3的算法测试流程

2.4.1图像预处理

(1)图像尺寸调整
假设网络的图像输入尺寸为416x416。读取原始图像,将原始图像等比例缩放(312x416),并进行零padding,填充到416x416大小。
举例来说,假设原始图像尺寸为480x640,需要先缩放到312x416(最大的边缩放到416大小),在高度方向进行零padding,填充到416x416大小,然后才可以输入网络。

(2)图像数据归一化
图像数据除以255。

(3)增加batch维度
由于网络是以batch的方式进行处理的,可能还会需要添加batch维度,将图像数据调整为4D张量后再输入网络。

2.4.2前向传播

前向传播,得到3个预测分支的输出。

2.4.3预测值后处理

(1)边界框解码
首先将每个预测分支得到边界框坐标、类别置信度分数(置信度分数乘以类别概率,类别置信度分数是向量)解码出来,得到在416x416网络输入图像尺寸下的边界框坐标。

(2)边界框坐标校正
将在416x416网络输入图像尺寸下的边界框坐标,调整为最原始图像尺寸(480x640)下的边界框坐标。

(3)阈值处理
将置信度分数,与类别概率相乘,得到类别置信度分数。设定类别置信度阈值(默认0.6,或0.3),删除类别置信度分数低于阈值的边界框。

(4)非极大值抑制(NMS)
分别对每一个类别进行NMS,得到最后的预测结果,NMS的默认iou阈值为0.5(或0.45)。

2.5YOLOv3的算法训练流程

2.5.1图像预处理

图像尺寸调整、图像数据归一化(除以255),以及一些数据增强处理(包括旋转,以及调整饱和度、曝光量、色调等)。

2.5.2 前向传播

前向传播,得到3个预测分支的输出。

2.5.3计算损失和梯度

确定正、负、忽略样本,计算损失和梯度。

2.5.4反向传播

反向传播,更新参数。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值