概述
目标检测模型大致分为两类
1、基于region proposal的方法:滑动窗口(R-CNN之前) -> selective search(R-CNN提出) -> RPN(Faster R-CNN提出)
2、基于anchor的方法:如YOLO和SSD
- 基于anchor-free:YOLOv1
- 基于anchor-based:YOLOv5
论文阅读
介绍
Yolov1利用整张图作为网络的输入,将整个类别和位置都作为回归问题;其introduction部分的切入点很好,提到人眼能很快很准确识别周围环境并做出判断,这也使得人类开车能够对环境做出及时的反应,而yolov1恰好达到很快的检测速度,这就给自动驾驶以及各种智能交互系统做出很大贡献。
Yolov1模型十分简洁:
优点如下
1、仅用单一的卷积网络进行多目标识别并分类
2、且yolo并非使用滑动窗口或者RPN,而是纵观整个图像环境
3、Yolo具有极高泛化性。
Dig into YOLO
既然yolo不适用RPN等基于区域提名的方法,那就得有自己独特的方法。实际上,YOLO将图像划分为S * S的网格图,当某个物体的center落在某个网格,那这个网格就对那个物体负有检测的责任。
每个网格预测出B个bounding boxes,并给出confidence score,其反映了有多大可能这个box包含了物体以及这个box的位置标的有多准确。
置信度公式如下:
当无物体时,Pr(Object)为0、IOU为0,则整个置信度也为0;当有物体,我们希望的是置信度恰好等于IOU的值,即准确无误地判断出有物体,Pr(Object)为1(非0即1)。从这里我们也可以看出,YOLO对localization的期望是没那么高的(毕竟IOU最高可以为1),这也直接导致了论文中所述情景:
每个bounding box包含5个预测值:x、y、w、h、confidence。其中x和y代表物体的center,但这个center的参照不是整个图像的边框,而是其所在网格的边框;而w和h就是相对于整个图像的宽高了;由于有目标则Pr(Object)取1,没目标就0,不论取哪个,confidence都直接等于IOU的值(原文中说的是预测框和任意一个ground truth之间的IOU,这里怎么会是任意呢?因为YOLOv1的处理方式是默认每个网格中的物体只有一个类别,即不考虑两个不同类别物体出现在同一个网格内的情况,但作者们也知道,实际上是有可能的,因此当这种情况出现,则只好任意选择一个ground truth,这就直接导致了每个网格只能预测出一个物体)。因此,当鸟畜成群时,检测效果非常差,这是YOLO方法的一个缺陷。
每个网格还要预测C个类条件概率,进行多分类,即该网格内的物体是属于哪个类(当一个网格需要负责的物体大于等于2个,问题就来了,这也是YOLOv1的局限),公式如下:
这个条件概率公式(conditional class probability)是在该网格被认为的确包含物体的前提下进行计算。
在测试阶段,我们计算如下公式:
该公式名为 class-specific confidence scores,每个网格都含有C个(因为有C个类别)。
该图反应了模型detection的过程,输出的predictions为S x S x (5B+C)的一个tensor(其中SS代表网格数;B是bounding box数;5是bounding box中的5个值:x、y、w、h、confidence;C即类别数,也是每个网格要计算的class-specific confidence scores个数,每个类别对应一个)
YOLO原文选择S=7,B=2,数据集用的是PASCAL VOC,因此C=20,最后的prediction tensor为7 * 7 * 30
Network Design
YOLO的网络结构受到GoogLeNet的启发,24个卷积层,2个全连接层。YOLO并不采用inception model,而仅仅简单地采用1 * 1 降维层,其后紧跟3 * 3的卷积层。
1 * 1的卷积有诸多好处:
(1)在相同尺寸的感受野中叠加更多的卷积,能提取到更丰富的特征。该观点来自于Network in Network(NIN, https://arxiv.org/pdf/1312.4400.pdf),NIN结构中每层卷积后都紧跟激活函数,能组合出更丰富的非线性特征
(2)降低了计算复杂度,如下图所示。先降维,使得3*3卷积时计算量大大减少:
上面的情况需要192x256x3x3x32x32=452,984,832次乘法
下面需要192x96x1x1x32x32+96x256x3x3x32x32=245,366,784次乘法
(3)据称:中间的降维层类似于压缩的效果,只要最后输出的特征数不变(256组),不会影响最后训练
YOLOv1整体结构如下:
Training
Training步骤:
1、首先使用了前20层卷积并附上average-pooling 和一个全连接层,训练一周。
2、然后用于detection,作者们受到其他人的启发:增添额外的卷积层和全连接层到pre-trained model后面有助于提升效果,于是他们添加了4个卷积曾和两个全连接层,均随机初始化权重
3、为了获得更好的视野,他们把网络的input resolution从224224增加为448448(调整方式为,对后面的全连接层的输入size进行改变)
最后一层预测类别概率以及bounding box的坐标,他们根据图像的宽和高归一化了bounding box的宽高,使他们为0-1之间的小数;如前所述,bounding box的x和y(center)也为0-1间的数,x和y表示到物体所被负责网格位置的偏移
除了最后一层(用linear activation function),整个网络所有层所使用的激活函数为leaky rectified linear activation:
对于loss函数,采用Sum-squared error,因为很容易optimize,但也有一些问题:
问题一:权重上,localization error等于classification error
对策一:原文给了一个很好的idea:由于大部分图像中,没有物体的单元格远远多于有物体的,因此在初始情况下,模型检测所收到的loss很大程度是因为把没有物体的位置当成了有物体,而只有少部分是因为把有物体的区域识别成了没物体,此时如果我们还让两种错误有相同的loss值,模型的偏向性会很快出现,会导致模型十分不稳定。就像一个小孩经常犯错,我们明知道他以后还要挨的打会很多,那我们一次性就不能打太重,不然打不了多久就废了,或者孩子直接破罐子破摔了。
体现在模型上就是,使得confidence整体性偏向于0,因为这样可以减少loss,但这种减少并不是我们想要的。
基于以上思想,YOLO增加了来自于bounding box位置预测错误的loss权重,而减少了来自于对没有包含物体的网格的confidence预测的loss权重;即前者的λcoord = 5,后者的λnoobj = 0.5
问题二:权重上,大目标的error和小目标的error
对策二:由于小目标的bounding box的小偏差所导致的后果是大于大目标bounding box的小偏差的。为了在一定程度上处理这个问题,作者们预测bounding box宽高的平方根而不直接预测宽高。
显然这种方法治标不治本,只能缓解问题矛盾;通过对宽高进行平方根,由于宽高其实是offset,范围为0-1,因此平方根后会更接近1,那到底如何缓解的呢?这时就得上公式了:
以宽为例,可以看到,原本loss值的计算是计算预测宽和真实宽之间的difference,现在则先进行开根(即sqrt(w)),使其分别增大,再计算difference,那这个difference是不是也增大了呢?我们要分情况来看。
首先我可以合理假设:大目标的宽在0.75 - 1之间,小目标的宽在0 - 0.25之间,其余是中等尺寸目标。
我们再对sqrt(x)函数求导,可知,当x = 0.25时,其导数为1;这就意味着,当x>0.25,sqrt(x)函数的值增长放缓,而在0.25之前,y值增长是加强的,即小目标的宽高开根号后,预测值和真实值差距变大,而大目标的预测值和真实值差距变小。
函数图说明一切(通过在线函数可视化网站生成):
显然,小目标的宽进行开根号后,预测宽和真实宽之间的difference变大了,即loss变大了。
显然,大目标的宽进行开根号后,预测宽和真实宽之间的difference变小了,即loss变小了。
结论来了:此种方法并没有改变大小目标loss的权重,权重还是一样的,但使得小目标的loss值会稍微偏大一些,而大目标的loss值偏小,这就是所谓的缓解。
除了问题以及应对方法,原文还提到bounding box predictor,原文讲的极其隐晦,这个predictor其实就是每个bounding box,哪个bounding box和该ground truth的IOU大,哪个就负责这个物体。
loss
如下是完整的loss function,为了真正弄懂YOLO,损失函数是不得不理解的:
在公式里,表示第i个网格是否有物体出现(这是由ground truth决定的),表示第i个网格中第j个bounding box predictor是对那个网格中的物体预测负责的(当然,每个网格中只会有一个predictor负责)。
Loss function只在物体的确存在于那个网格中时,才对类别预测error进行惩罚;同理,仅当那个predictor是对那个ground truth负责时(在那个网格的所有predictor中与ground truth有最高的IOU),才对bounding box coordinate error进行惩罚。
源码实现
该源码并非我从0开始写,而是借鉴他人的代码(非官方版,官方的是c语言写的,该源码采用python),完全阅读后,修改了其中的bug以及和原文不符的参数后,重新发出的修改版,代码包含详细的注释,目的是为了提升自己对目标检测的理解,也希望帮助到其他愿意深入学习该模型的人~
源码链接click here