版本 | 作者 | 时间 | 备注 |
---|---|---|---|
V1.0.0 | Zhe Chen | 2021.1.27 | YOLO系列学习笔记 |
**目标检测 **的任务是找出图像中所有感兴趣的目标(物体),确定它们的位置和大小,是机器视觉领域的核心问题之一。由于各类物体有不同的外观,形状,姿态,加上成像时光照,遮挡等因素的干扰,目标检测一直是机器视觉领域最具有挑战性的问题。
计算机视觉中关于图像识别有四大类任务:
除了图像分类之外,目标检测要解决的核心问题是:
目标可能出现在图像的任何位置。
目标有各种不同的大小。
目标可能有各种不同的形状。
如果用矩形框来定义目标,则矩形有不同的宽高比。由于目标的宽高比不同,因此采用经典的滑动窗口+图像缩放的方案解决通用目标检测问题的成本太高。
目标检测架构分为两种,一种是two-stage(R-CNN),一种是one-stage(YOLO),区别就在于 two-stage 有候选框提取(region proposal) 过程,类似于一种海选过程,网络会根据候选区域生成位置和类别,而 one-stage 直接从图片生成位置和类别。
相对于R-CNN系列的"看两眼"(候选框提取与分类),YOLO只需要Look Once。YOLO统一为一个回归问题,而R-CNN将检测结果分为两部分求解:物体类别(分类问题),物体位置即bounding box(回归问题)。
YOLO的核心思想就是利用整张图作为网络的输入,直接在输出层回归bounding box的位置和bounding box所属的类别。
之前刚开始接触物体检测算法的时候,老是分不清deep learning中,物体检测和图片分类算法上的区别,弄得我头好晕,终于在这篇paper上,看到了解释。
物体检测和图片分类的区别:图片分类不需要定位,而物体检测需要定位出物体的位置,也就是相当于把物体的bbox检测出来,还有一点,物体检测是要把所有图片中的物体都识别定位出来。
作者将目标检测的流程统一为单个神经网络。该神经网络采用整个图像信息来预测目标的bounding boxes的同时识别目标的类别,实现端到端实时目标检测任务。
而YOLOv1中的S=7, B=2, Pascal VOC有20个类别标签,C=20,所以最终的预测是一个7×7×30的张量。
YOLOv1采用卷积神经网络,开始由卷积层提取图像特征,全连接层预测输出概率。模型结构类似于GoogleNet,如图3所示。作者还训练了YOLO的快速版本(fast YOLO)。Fast YOLO模型卷积层和filter更少。最终输出为7×7×30的tensor。
作者采用sum-squared error为目标函数来优化,下图为总的loss训练:
作者在PASCAL VOC2007和PASCAL VOC2012数据集上进行了训练和测试。训练135轮,batch size为64,动量为0.9,学习速率延迟为0.0005. Learning schedule为:第一轮,学习速率从0.001缓慢增加到0.01(因为如果初始为高学习速率,会导致模型发散);保持0.01速率到75轮;然后在后30轮中,下降到0.001;最后30轮,学习速率为0.0001.
作者还采用了dropout和 data augmentation来预防过拟合。dropout值为0.5;data augmentation包括:random scaling,translation,adjust exposure和saturation。
这里,作者用到了一个trick,稍微缓解了yolo对大目标和小目标检测精度的平衡。这就是后续作者要进行改进的地方。
对于PASCAL VOC数据集,模型需要对每张图片预测98个bounding box和对应的类别。对于大部分目标只包含一个box;其它有些面积大的目标包含了多个boxes,采用了Non-maximal suppression(非最大值抑制)来提高准确率。
- NMS(非最大值抑制): 抑制目标框中的重合框。目的就是要去除冗余的检测框,保留最好的一个。
如表4-1所示,在准确率保证的情况下,YOLO速度快于其它方法,下表 PASCAL VOC 2007数据集测试
从测试效果来看,YOLOv2在当时主流框架的对比下,生命力还是很强的。
批量归一化使得在收敛方面得到了显著改进,同时消除需要其他形式的正则化。通过对YOLO中所有卷积层添加批量归一进行标准化,我们在mAP上得到了超过2%的改进。批量正常化也有助于使模型规范化。使用批量归一化,我们删除dropout,也可以防止过度拟合。
采用k-means聚类的方法来获得anchor的个数。
作者发现:如果直接采用anchor boxes的方式运用到yolo时,模型会很不稳定,因为没有对 t x 和 t y t_x和t_y tx和ty进行限制,所有预测boxes会跑到图中任意的位置。
对此,作者对以上公式进行了如下修改,对 t x 、 t y t_x、t_y tx、ty应通过逻辑激活函数(sigmoid函数)进行限制,因此预测结构只会出现在grid cell之间,让每个anchor去负责预测目标中心落在某个grid cell区域内的目标:
通过增加anchor和sigmoid函数,YOLO有5% mAP的提升。
作者将底层的26×26×512的特征图和64 1×1的卷积层进行融合通过PassThrough Layer转变 为13×13×256。
为了提升YOLO的鲁棒性,作者在训练过程中,作者每迭代10个batch,会对网络的输入尺寸进行一个随机的尺寸进行选择(全部都是32的整数倍),以此来达到速度和精度的一个平衡。
建立在YOLOv1的基础上,经过Joseph Redmon等的改进,YOLOv2和YOLO9000算法在2017年CVPR上被提出,重点解决YOLOv1召回率和定位精度方面的误差。在提出时,YOLOv2在多种监测数据集中都要快过其他检测系统,并可以在速度与精确度上进行权衡。
文章提出了一种新的训练方法–联合训练算法。这种算法可以把这两种的数据集混合到一起。使用一种分层的观点对物体进行分类,用巨量的分类数据集数据来扩充检测数据集,从而把两种不同的数据集混合起来。基本思路就是:同时在检测数据集和分类数据集上训练物体检测器(Object Detectors ),用监测数据集的数据学习物体的准确位置,用分类数据集的数据来增加分类的类别量、提升鲁棒性。YOLO9000 就是使用联合训练算法训练出来的,他拥有 9000 类的分类信息,这些分类信息学习自ImageNet分类数据集,而物体位置检测则学习自 COCO 检测数据集。
YOLOV2着重改善 recall,提升定位的准确度,同时保持分类的准确度。
这个网络主要是由一系列的1x1和3x3的卷积层组成(每个卷积层后都会跟一个BN层和一个LeakyReLU)层,作者说因为网络中有53个convolutional layers,所以叫做Darknet-53(2 + 12 + 1 + 22 + 1 + 82 + 1 + 82 + 1 + 4*2 + 1 = 53 按照顺序数,最后的Connected是全连接层也算卷积层,一共53个)。上图就是Darknet-53的结构图,在右侧标注了一些信息方便理解。(卷积的strides默认为(1,1),padding默认为same,当strides为(2,2)时padding为vali。
看完上图应该就能自己搭建出Darknet-53的网络结构了,上图是以输入图像256 x 256进行预训练来进行介绍的,常用的尺寸是416 x 416,都是32的倍数。下面我们再来分析下YOLOv3的特征提取器,看看究竟是在哪几层Features上做的预测。
作者在论文中提到利用三个特征层进行边框的预测,具体在哪三层我感觉作者在论文中表述的并不清楚(例如文中有“添加几个卷积层”这样的表述),同样根据代码我将这部分更加详细的分析展示在上图中。
注意:原Darknet53中的尺寸是在图片分类训练集上训练的,所以输入的图像尺寸是256x256,上图是以YOLO v3 416模型进行绘制的,所以输入的尺寸是416x416,预测的三个特征层大小分别是52,26,13。
在上图中我们能够很清晰的看到三个预测层分别来自的什么地方,以及Concatenate层与哪个层进行拼接。**注意Convolutional是指Conv2d+BN+LeakyReLU,和Darknet53图中的一样,而生成预测结果的最后三层都只是Conv2d。**通过上图我们就能更加容易地搭建出YOLOv3的网络框架了。
注:这里作者在YOLO3的模型中把池化层换成了卷积层来做上采样层。
YOLOv3网络在三个特征图中分别通过(4+1+c)×k个大小为1×1的卷积核进行卷积预测,k为预设边界框(bounding box prior)的个数(k默认取3),c为预测目标的类别数,其中4k个参数负责预测目标边界框的偏移量,k个参数负责预测目标边界框内包含目标的概率,ck个参数负责预测这k个预设边界框对应c个目标类别的概率。下图展示了目标边界框的预测过程(该图是本人重新绘制的,与论文中的示意图有些不同,个人感觉自己绘制的更便于理解)。图中虚线矩形框为预设边界框,实线矩形框为通过网络预测的偏移量计算得到的预测边界框。其中sigmoid函数其目的是将预测偏移量缩放到0到1之间(这样能够将预设边界框的中心坐标固定在一个cell当中,作者说这样能够加快网络收敛)。这里跟yolov2是一样的。
下图给出了三个预测层的特征图大小以及每个特征图上预设边界框的尺寸(这些预设边界框尺寸都是作者根据COCO数据集聚类得到的):
关于YOLOv3的损失函数文章中写的很粗略,比如坐标损失采用的是误差的平方和,类别损失采用的是二值交叉熵,本人在github上也找了很多YOLO v3的公开代码,有的采用的是YOLOv1或者YOLOv2的损失函数,下面给出本人认为正确的损失函数。YOLOv3的损失函数主要分为三个部分:目标定位偏移量损失+目标置信度损失+目标分类损失。
( λ 1 和 λ 2 和 λ 3 \lambda_1和\lambda_2和\lambda_3 λ1和λ2和λ3是平衡系数)
目标置信度可以理解为预测目标矩形框内存在目标的概率,目标置信度损失采用的是二值交叉熵损失(Binary Cross Entropy), o i = 0 o r 1 o_i={0 or 1} oi=0or1表示预测目标边界框i中是否真实存在目标,0表示不存在,1表示存在。表示预测目标矩形框$$i内是否存在目标的Sigmoid概率(将预测值通过sigmoid函数得到)。
目标类别损失同样采用的是二值交叉熵损失(采用二值交叉熵损失的原因是,作者认为同一目标可同时归为多类,比如猫可归为猫类以及动物类,这样能够应对更加复杂的场景。但在本人实践过程中发现使用原始的多类别交叉熵损失函数效果会更好一点,原因是本人针对识别的目标都是固定归于哪一类的,并没有可同时归于多类的情况)。 o i = 0 o r 1 o_i={0 or 1} oi=0or1表示预测目标边界框 i i i中是否真实存在目标,0表示不存在,1表示存在。
目标定位损失采用的是真实偏差值与预测偏差值差的平方和,其中 i i i表示预测矩形框坐标偏移量(注意网络预测的是偏移量,不是直接预测坐标), g g g表示与之匹配的GTbox与默认框之间的坐标偏移量。这些参数都是映射在预测特征图上的。
( b x , b y , b w , b h b^x,b^y,b^w,b^h bx,by,bw,bh)是预测的目标矩形框参数,( c x , c y , p w , p h c^x,c^y,p^w,p^h cx,cy,pw,ph)是默认矩形框参数,( g x , g y , g w , g h g^x,g^y,g^w,g^h gx,gy,gw,gh)是与之匹配的真实目标矩形框参数,这些参数都是映射在预测特征图上的。
分而治之:从yolo_v1开始,yolo算法就是通过划分单元格来做检测,只是划分的数量不一样。
采用Leaky ReLU作为激活函数。
端到端进行训练。一个loss function搞定训练,只需关注输入端和输出端。
从yolo_v2开始,yolo就用batch normalization作为正则化、加速收敛和避免过拟合的方法,把BN(Batch Normalization)层和leaky relu层接到每一层卷积层之后。
多尺度训练。在速度和准确率之间的平衡(tradeoff)。想速度快点,可以牺牲准确率;想准确率高点儿,可以牺牲一点速度。
Yolo每一代的提升很大一部分决定于backbone网络的提升,从v2的darknet-19到v3的darknet-53。yolo_v3还提供替换backbone——tiny darknet。要想性能好,backbone可以用Darknet-53,要想轻量高速,可以用tiny-darknet。总之,yolo就是天生“灵活”,所以特别适合作为工程算法。
Darknet-53和Resnet-152正确率相同,但速度是2倍。
后续的YOLOv3-spp和YOLOv4和YOLOv5其实都是沿用YOLOv3的框架,只是加了各自的工业上提升检测速度和精度的方法,如YOLOv4把IoU更换为GIoU、DIoU和CIoU加快了训练和检测速度等tricks。
随着深度学习的发展,目前已经出现了很多算法(或者训练技巧,tricks)来提升神经网络的准确率。在实际测试中评价一个算法的好坏优劣主要看两点,一是能否在大规模的数据集中起作用(work),二是是否有理论依据。一些算法仅能在某些特定的模型上或者某类特定的问题上运行,亦或是适用于一些小规模的数据集。然而,还有一些算法,例如batch normalization(BN)或者残差连接(residual-connections)已经被用在了不同的模型,任务以及不同的数据集中,已经被充分的证明了这些算法的普适性,是一个general的算法。我们假设这样的general(or universal)的算法包括Weighted-residual-connection(WRC),cross-stage-partial-connections(SCP),cross mini-batch Normalization(CmBN),self-adversarial-training(SAT)以及mish-activation。此外,我们还加了一些其余的tricks,包括Mosaic data augmentation,DropBlock regularization,CIoU loss,设计了一个YOLO-V4,并且在MS coco数据集中取得了新的state-of-the-art的结果:在Tesla V100显卡能达到43.5% AP(65.7% AP)的精度,且达到~65FPS的速度。目前代码已经开源。
Yolo-V4的主要目的在于设计一个能够应用于实际工作环境中的快速目标检测系统,且能够被并行优化,并没有很刻意的去追求理论上的低计算量(BFLOP)。同时,Yolo-V4的作者希望算法能够很轻易的被训练,也就是说拥有一块常规了GTX-2080ti或者Titan-XP GPU就能够训练Yolo-V4, 同时能够得到一个较好的结果。主要贡献可以总结为以下几点:
作者的目标是在输入网络分辨率,卷积层数,参数数量和层输出(filters)的数量之间找到最佳平衡。
YOLOv4 = CSPDarknet53+SPP+PAN+YOLOv3
其中YOLOv4用到相当多的技巧:
论文做了大量的实验,因为包含的Tticks太多了。论文验证了大量的BoF,包括grid sensitivity elimination, mosaic data augmentation, IoU threshold, genetic algorithm,class label smoothing, cross mini-batch normalization, self adversarial training, cosine annealing scheduler, dynamic mini-batch size, DropBlock, Optimized Anchors, different kind of IoU losses。我们还对各种BoS验证,包括Mish、SPP、SAM、RFB、BiFPN、BiFPN和Gaussian YOLO。对于所有的实验,只使用一个GPU训练。
YOLOv4 算法在实时目标检测算法中精度最高,实现了精度和速度的最佳平衡。
论文包含了大量的知识点,需要看很多论文才能知道很多Tricks是什么,因此也可以作为综述类的论文来看。Bag of freebies和Bag of specials对工业界或者打比赛也是十分有帮助的。YOLOv4意义不仅仅是一篇论文,更重要的是能在落地应用基础上提高了性能。
YOLOv4模型 = CSPDarkNet53 + SPP + PANet(path-aggregation neck) + YOLOv3-head
YOLOv4使用这些新的技巧:WRC、CSP、CmBN、SAT,Mish-activation,Mosaic data augmentation、CmBN、DropBlock正则化和CIoU损失,以及组合技巧,以达到最好的效果。在MS COCO数据集中的AP43.5%(65.7% AP50),在实际应用中,Tesla V100上速度可达到65FPS。
YOLOv4网络结构图如下:
所以说,Yolov4大部分框架还是采用的v3的结构,需要把v3给吃透,v4提到的一些tricks可以尝试地加到自己的网络中,如马赛克增强图像增广和Loss训练的改进等。
Yolov5的作者并没有发表论文,因此只能从代码角度进行分析。
Yolov5代码:https://github.com/ultralytics/yolov5
目标检测发展很快,但对于小目标的检测还是有一定的瓶颈,特别是大分辨率图像小目标检测。比如7920×2160,甚至16000×16000像素的图像。
图像的分辨率很大,但又有很多小的目标需要检测。但是如果直接输入检测网络,比如Yolov3,检出效果并不好。
主要原因是:
(1)小目标尺寸: 以网络的输入608×608为例,Yolov3、Yolov4,Yolov5中下采样都使用了5次,因此最后的特征图大小是19×19,38×38,76×76。三个特征图中,最大的76×76负责检测小目标,而对应到608×608上,每格特征图的感受野是608/76=8×8大小。再将608×608对应到7680×2160上,以最长边7680为例,7680/608×8=101。即如果原始图像中目标的宽或高小于101像素,网络很难学习到目标的特征信息。
(PS:这里忽略多尺度训练的因素及增加网络检测分支的情况)
(2)高分辨率: 而在很多遥感图像中,长宽比的分辨率比7680×2160更大,比如上面的16000×16000。如果采用直接输入原图的方式,很多小目标都无法检测出。
(3)显卡爆炸:很多图像分辨率很大,如果简单的进行下采样,下采样的倍数太大,容易丢失数据信息。但是倍数太小,网络前向传播需要在内存中保存大量的特征图,极大耗尽GPU资源,很容易发生显卡爆炸显存爆炸,无法正常的训练及推理。
YOLOv1-v3是YOLO系列的精华之作,后续的YOLOv3-SPP、YOLOv4和YOLOv5都是针对V3版本进行修改、增加的一些工程上的Tricks,从而提高YOLO的推理速度。YOLOv1解决了传统的目标检测速度慢等问题,将检测问题转变成回归问题;YOLOv2解决了v1中准确率的问题,能够提升多目标检测的精度,进一步提升了检测速度;YOLOv3进一步提升了v2中的速度和准确率,增加多尺度训练,灵活处理输入图片,提升了小目标检测的精度,改善了Loss训练的效率;YOLOv4解决了GPU训练的问题,只需要单片GPU1080Ti就可以开始你的模型训练了;Pytorch版本YOLOv5的发布解决了YOLO体积大的问题,可以在移动边缘端部署YOLO。
[1] Redmon, Joseph, et al. “You only look once: Unified, real-time object detection.” Proceedings of the IEEE conference on computer vision and pattern recognition. 2016.
[2] Redmon J, Farhadi A. YOLO9000: better, faster, stronger[J]. arXiv preprint, 2017.
[3] Redmon, Joseph, and Ali Farhadi. “Yolov3: An incremental improvement.” arXiv preprint arXiv:1804.02767 (2018).
[4] AlexeyAB. YOLOv4: Optimal Speed and Accuracy of Object Detection. arxiv:https://arxiv.org/abs/2004.10934