目录
1、网络结构
2、检测原理
3、制作训练正样本方法
4、损失函数
5、前向推理
6、模型缺限
YOLO的全称是you only look once,指只需要浏览一次就可以识别出图中的物体的类别和位置。YOLO被称为Region-free方法,相比于Region-based方法,YOLO不需要提前找到可能存在目标的Region。
一个典型的Region-base方法的流程是这样的:先通过计算机图形学(或者深度学习)的方法,对图片进行分析,找出若干个可能存在物体的区域,将这些区域裁剪下来, 放入一个图片分类器中,由分类器分类。
因为YOLO这样的Region-free方法只需要一次扫描,也被称为单阶段(1-stage)模型。Region-based方法方法也被称为两阶段(2-stage)方法。
YOLO v1在Pascal VOC 2007测试数据集上达到的mAP是63.4%,在输入图像大小为448×448像素的图像上处理速度能够达到每秒45帧,该网络的一个小版本FastYOLO 每秒处理速度也达到了惊人的155帧。虽然YOLO v1的精度不及RCNN系列,但奈何其速度非常快,所以在工业界应用还是很普遍。分几个点来详细介绍:
1、网络结构
论文下载地址:https://arxiv.org/pdf/1506.02640
GitHub源码地址:https://github.com/AlexeyAB/darknet
项目地址:https://pjreddie.com/darknet/yolo/
作者用一个卷积神经网络结构就可以从输入图像直接预测bounding box和类别概率。整个检测网络有24个卷积层,后面跟了2个全连接层。交替的1×1个卷积层目的是减少前一层的特征。
可以看到,输出的形状为SxSx(B*5+C),具体解释如下:
- S 表示将输入图像划分为SxS个网格单元格。每个网格单元格都负责预测一定数量的边界框。
- C 表示类别数,即目标检测任务中需要预测的不同类别数量。
- B 表示每个网格单元格预测的边界框数量。每个边界框通常包括边界框的坐标信息(X,Y,H,W)(4个值)和边界框的置信度(C)(1个值),所以每个边界框需要5个预测值。
- 5*B 表示每个网格单元格预测的边界框相关的5个预测值(边界框的中心坐标、宽度、高度和置信度),乘以 B 的数量得到总的预测值数量。
- x,y就是bounding box的中心坐标,与grid cell对齐(即相对于当前grid cell的偏移值),使得范围变成0到1;
- w,h进行归一化(分别除以图像的w和h,这样最后的w和h就在0到1范围)。
- confidence代表了所预测的box中含有object的置信度和这个box预测的有多准两重信息。如果ground truth落在这个grid cell里,那么Pr(Object)就取1,否则就是0;IOU就是bounding box与实际的groud truth之间的交并比。confidence就是这两者的乘积。
confidence有两种情况,分别是 “0”和“1”,当我们的网格中确实存在目标时,那我们图5中的Pr(Object)就是等于 “1” 的,所以我们预测的confidence就直接等于IOU,如果网格中没有目标落在里面,那么Pr(Object)就是等于“0”的,所以confidence就是等于零的。
①网络输入:
图片大小:448 * 448 * 3 = (64 * 7) * (64 * 7)* 3 = 7 * 7 * (64 * 64 * 3)
也就是说,输入图像大小为448*448的图像,被划分为7*7的网格(grid cell),一个网格负责检测输入图片的64 * 64 * 3个非连续的像素,来判断物体的位置、形状以及分类(即如果某个object的中心落在这个网格中,则这个网格就负责预测这个object)。
②Bounding boxes 预测:
先看 bounding boxes+confidence。显示每个grid cell生成2个bounding box(预测框:每个网格使用两个先验框去寻找是否有目标方框的中心点落在该网格内。分别用B1(Box1)和B2(Box2)表示这个2个框,称为“先验框”。有点类似,每个网格使用两个不同尺寸的渔网去捞鱼(目标),看看能不能捞到目标。)。一共98个bounding box,框的粗细代表置信度大小,框越粗代表框住的是一个完整物体的概率越大。在这一步中,YOLO为每一个网格给出了两个预测框,这里有点像faster rcnn的anchor,但不完全相同。YOLO给出的预测框,是基于网格中心点的,大小自定义。每一个网格预测B个bounding boxes,每个bounding boxes有四个坐标和一个置信度(confidence),所以最终的预测结果是S×S×(B∗5+C)个向量。
再看第二个class probablity map。用不同颜色表示每个grid cell所预测的物体最可能属于分类(这块就是普通的图像分类,用于确定网格中检测到的目标的分类。这个长度决定了YOLO V1最多只能识别20种分类目标。),如蓝色的grid cell生成的最可能bounding box最可能框住的是狗、黄色的grid cell最可能预测自行车……。这一路的工作其实是和上一步是同时进行的,负责的是网格(gird cell)类别的分数,预测的结果一样是放在最后的7×7×30的张量中。
每个网格能预测几个目标?虽然使用了两个先验框去找目标,但是每个网格只选用一个框中的预测结果来定位物体:位置+尺寸,依据就是每个框的置信度的大小,选择一个置信度大的框的预测结果。因此,在YOLO V1中,20分类是针对每个网格的,而不是每个先验框的,即每个先验框只需要检测是否有对象或物体。网格进一步的负责对检测到的目标的各种分类的可能性就行预测,最后选择最大可能性的分类输出。因此, YOLO V1中,对一张图而言,最多能够检测 7 * 7 = 49个目标,目标的分类数最大为20种。
③网络输出:
YOLOv1把30个输出值,结构化成5+5+20。每个预测框有5个参数:x,y,w,h,confidence; Pascal VOC里面还有20个类别;这样的话30=(2×5)+20,也就是说这一个30维的向量就是一个gird cell的信息,那总共是7 × 7个gird cell,一共就是7×7×(2×5+20)=7×7×30的张量(tensor)=1470个outputs。
2、检测原理
从整体上来看,YOLOv1网络接收一张输入图像大小为的RGB图像,经由backbone网络处理后输出一个空间大小被降采样了64倍(即网络最终的stride为64)的特征图,这一特征图在经过全连接层处理和一些维度转换的操作后,得到一个维度为7×7×30的张量。
首先,一张大小为的RGB图像输入进网络,经过一系列的卷积和池化操作后,得到一个经过64倍降采样的的特征图,注意,这当中的卷积操作恰好就体现了one-stage框架的核心检测思想:逐网格找东西。
最后将输出的一维向量经由resize操作转换成7×7×30的三维张量,以便于后面的操作。整个YOLOv1的流程如下图所示。
因此,YOLOv1就相当于是将输入图像划分成的网格,然后在这个网格上去做预测。理想情况下,包含了物体中心点的网格会有很高的置信度输出,而不包含中心点的网格的置信度输出应该十分接近0。
训练过程:
首先将图像分成 S × S 网格(gird cell)、然后将图像送入网络,生成S×S× (B∗5+C)个结果,根据结果求Loss并反向传播梯度下降。
预测过程:
首先将图像分成 S × S网格(gird cell)、然后将图像送入训练好的网络,生成S×S× (B∗5+C)个结果,用NMS选出合适的预选框。
为了评估YOLO在PASCAL VOC数据集上的水平,我们使用S=7,B=2。PASCAL VOC有20个标签类,所以C=20。我们最终的预测是一个7×7×30张量。
每个边界框由5个预测组成:x、y、w、h和confidence。(x、y)坐标表示相对于网格单元格边界的方框的中心。并将其宽度和高度相对于整个图像进行了预测。
在测试时,也就是我们最终预测时,我们对于每个目标的最终概率是将conditional class probabilities 乘上confidence的预测值,对于每个grid cell而言,它有C个类别,那我们就会预测C个类别分数,那么这里的类别分数就是对应的conditional class probabilities,也就Pr(Classi|Object) ,即类别i在它为目标的前提下的概率。
3、制作训练正样本方法
数据集标注:
假设一个20类的数据集,1张图片上有1个物体,也就是1个标注框,其标注文件(.txt)格式应该为:
然后根据标注文件生成编码向量(假设S=7,B=2,C=20):
- 首先是置信度和位置坐标;其中,置信度在数据集当中,每个标注框都置为1,也就是100%可能性的标注框置信度。
- 最后生成一个[5,1]向量:[1,x,y,w,h];
- 然后再对类别需要进行one-hot编码,得到[20,1]向量;
- 整合后生成[25,1],也就是如下图:
其中绿色是置信度1,黄色是xywh坐标,蓝色是类别one-hot编码信息
正样本定义:
由于YOLOv1是预测图像中的物体的中心点,因此,包含物体中心点的网格,我们认为这里是有物体的。YOLOv1定义了一个objectness概念,即表示此处是否有物体,有物体则有,反之无。有物体的网格便是一个正样本(posotive sample),否则的话,是负样本(negative sample)。我们可以用下面的一张图来表示这一正样本定义(黄颜色代表这个网格有物体)。
图中的大的中心点(图中的红点)落在了这个网格内。因此,预测的边界框中的置信度的含义就是该网格是否包含了物体的中心点。置信度越接近于1,表明有物体的概率越大,反之越小。
制作正样本过程:
对于一个给定的真实框,其左上角点坐标为(x,y),右下角点坐标为(x+w,y+h),我们按照以下几个步骤来为制作正样本。
1,计算出真实框的中心点坐标,然后计算得到网格坐标,从而确定正样本的位置;
2,计算出边界框的学习标签;
3,使用one-hot格式制作类别的学习标签。而置信度的学习标签需要在训练过程中确定,方法如下;
3.1,计算正样本处的每一个预测框与真实框的loU;
3.2,保留loU最大的预测框,计算边界框的位置参数损失和类别损失,并反向传播,其余边界框忽略;
3.3,同时,将这个最大的IoU值作为置信度的标签;
3.4,对于不包含物体中心点的负样本处的边界框,置信度学习标签统统设为0,且只计算置信度损失,不参与边界框的位置参数损失计算和类别损失计算。
4、损失函数
在损失函数这里作者每一项都用的平方和误差,将目标检测问题当作回归问题。
坐标损失:(负责检测物体的bbox中心点定位误差)
其中
表示第i个网格中的第j个bbox是否负责预测目标图像,若负责为1,否则为0。
宽高坐标损失:(负责检测物体的bbox宽高定位误差)
损失计算中加上平方根的目的是拉大不同预测位置的得到的损失预测值差距,使小框对误差更敏感一点。这样做是为了更加重视较大的边界框的位置误差,可以使算法更加关注边界框的位置准确性,从而更好地优化它们的预测结果。
置信度损失:(负责检测物体的bbox的confidence误差)
其中
表示第i个网格中的第j个bbox是否不负责预测目标图像,若不负责为1,否则为0。
通过对置信度进行损失计算,可以鼓励模型在包含目标的网格中预测高置信度。
Ci的计算是由IoU构成,IoU计算方式:
网格预测类别损失:(负责检测物体的grid cell分类误差)
其中
表示第i个网格是否包含目标图像,若包含为1,否则为0。
5、前向推理
计算所有检测框的得分:
训练好以后,模型会生成大量的标定框,每一个“网格”都一定会有1个[30,1]向量,故都会有2个标定框(一共就有7x7x2个,S=7,B=2),只不过经过损失函数迭代,网格覆盖到物体的标定框的置信度高,反之小,但是无论概率多小,都不会接近0。假如全部可视化,会产生如下面的第2张图的结果。
得分阈值筛选:
获得所有边界框的得分后,我们设定一个阈值去滤除那些得分低的边界框。很显然,这些得分低的都是背景框,不包含物体的中心点。这个筛选的阈值该设置多少是有些讲究的,跑demo时,常用的是0.1,而计算mAP时,常用的反而是0.01、0.001。当然,到底该设置多么大的阈值往往依赖于具体的任务需求和研究者的经验,需要我们在实际任务中去不断调试的。
计算边界框的中心点坐标和宽高:
筛选完后,利用公式计算出余下的边界框的中心点和宽高。
使用NMS进行第二次筛选:
由于可能会出现同一个物体被多个得分较高的边界框所框选,因此,有必要对这种冗余检测进行抑制,剔除掉不必要的重复检测,常用的手段之一便是非极大值抑制(Non-maximal suppression,NMS)。其思想很简单:对于某一类目标的所有边界框,首先挑选出得分最高的边界框,依次计算其他的边界框与这个得分最高的边界框的IoU,超过设定的IoU阈值的边界框则被认为是重复检测,将其剔除掉。对所有类别的预测框都进行这两步操作,直到无框可剔除为上。非极大值抑制(NMS)包含3个流程:
1.对输入的前向推理结果进行预处理,也就是转换前向推理得到的bbox值,将归一化的bbox恢复到原来的坐标值。
2.根据得到的前向推理结果的置信度,根据设定好的置信度阈值(比如0.25)进行筛选,低于该阈值的过滤。
3.然后进行iou,计算剩下的标注框之间的iou,按照置信度排序,选择置信度最高的边界框作为基准框,并将其加入最终的检测结果中。然后,从剩余的边界框中,移除与基准框的重叠度高于设定阈值(比如0.5)的边界框。最后返回最终结果,也就是第3张图。
步骤1,2为预处理,步骤3是NMS核心,原因是在物体检测任务中,由于使用滑动窗口或锚框等方式生成候选框,可能会导致多个候选框重叠并框住同一个物体。为了避免在最终的检测结果中重复统计同一个物体,需要进行非极大值抑制。
6、模型缺限
- 每个gird cell只能预测 一个物体,那么7×7=49个gird cell最多只能预测49个物体,这也是YOLO v1对小密集物体识别差的原因。YOLO v1对一些群体性的小目标检测效果很差,比如天空中成群结队的鸟儿,如果这 群鸟每个目标都很小,那么YOLO就很难对他们进行预测,因为在我们YOLO v1的思想中,每个cell只预测两个bounding box,而且两个bounding box预测的还是属于同一个类别的。因为我们对每个grid cell都只预测一组classes参数,所以针对每个grid cell预测的是同一个类别的目标,所以说当一些小目标聚集在一起时YOLO v1的检测效果就非常的差。
- 当我们的目标出现新的尺寸或者配置的时候,YOLO v1的预测效果也是非常的差。
- 主要的误差都是由于定位不准。这个问题主要是由于作者选择直接预测目标的坐标信息,而不是像Faster RCNN或SSD那样预测Anchor的回归参数,所以后续YOLO v2开始,作者就采用了Faster RCNN或SSD那样基于Anchor的回归 预测。
参考文章:
yolov1原文地址以及论文翻译_yolo论文原文-CSDN博客
Yolov1-pytorch版 论文、原理及代码实现_yolov1 pytorch-CSDN博客
1.6 YOLO入门教程(新):YOLOv1(6)-制作正样本和损失函数 - 知乎