yolo官方网站:https://pjreddie.com/darknet/
YOLOv3论文全文完整理解翻译
目标检测中anchor box(先验框)的理解
先验框的个人理解
Faster RCNN与YOLOv3先验框以及其他方面的区别
在Faster RCNN中,先验框的大小是人为设定的。在YOLOv3中,先验框的大小是通过kmeans聚类算法得到的,对训练样本的groundtruth box的宽高分别进行聚类。
Faster RCNN属于两阶段算法,先对先验框做回归,再把框对应的原图中的区域和原图输入到一个网络中预测类别同时再次修正框的大小位置。YOLOv3属于一阶段算法,预测的结果同时包含框的位置大小和类别概率分布。
YOLOv3输出的结果是[batch_size, feature_map_w, feature_map_h, n_anchor * (n_class+1+4)]
yolov3网络结构图来源:yolo系列之yolo v3【深度解析】
yolov4网络结构图来源:YOLOv4原文翻译 - v4它终于来了!
yolov5网络结构图来源:深入浅出Yolo系列之Yolov5核心基础知识完整讲解
学习地址:一文看懂YOLO v1
这个作者写的残差块也挺好的:残差网络学习心得
最开始是从江大白那里看的:深入浅出Yolo系列之Yolov5核心基础知识完整讲解
算法思想
作者在YOLO算法中把物体检测(object detection)问题处理成回归问题,用一个卷积神经网络结构就可以从输入图像直接预测bounding box和类别概率。
算法首先把输入图像划分成S×S的格子(S是指图像的划分系数),然后对每个格子都预测B个bounding boxes,每个bounding box都包含5个预测值:x,y,w,h和confidence。
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里,那么 P r ( O b j e c t ) Pr(Object) Pr(Object)就取1,否则就是0。 I O U IOU IOU就是bounding box与实际的groud truth之间的交并比。所以confidence就是这两者的乘积。 c o n f i d e n c e = P r ( O b j e c t ) ∗ I O U pred truth confidence = Pr(Object)*\mathrm{IOU}_{\text {pred }}^{\text {truth }} confidence=Pr(Object)∗IOUpred truth (这个Pr(Object)=1或者0,是不是就是下面标亮的那个怎么判断一个grid cell中包含object的方法?)
在yolov1中作者将一幅图片分成7x7个网格(grid cell),由网络的最后一层输出7×7×30的tensor,也就是说每个格子输出1×1×30的tensor。30里面包括了2个bound ing box的x,y,w,h,confidengce以及针对格子而言的20个类别概率,输出就是 7x7x(5x2 + 20) 。
(通用公式: SxS个网格,每个网格要预测B个bounding box(这个bounding box应该就是后面的先验框的个数吧?)还要预测C个categories,输出就是S x S x (5×B+C)的一个tensor。 注意:class信息是针对每个网格的,confidence信息是针对每个bounding box的)
==所以如何判断一个grid cell中是否包含object呢?==答案是:如果一个object的ground truth的中心点坐标在一个grid cell中,那么这个grid cell就是包含这个object,也就是说这个object的预测就由该grid cell负责。
(所以这个object只是在判断有没有某一个检测目标但是没不在意到底是哪个类别的目标吗?)
每个grid cell都预测C个类别概率,表示一个grid cell在包含object的条件下属于某个类别的概率。
Pr ( Class i ∣ Object ) ∗ Pr ( Object ) ∗ IOU pred truth = Pr ( Class i ) ∗ IOU pred truth \operatorname{Pr}\left(\text { Class }_{i} \mid \text { Object }\right) * \operatorname{Pr}(\text { Object }) * \operatorname{IOU}_{\text {pred }}^{\text {truth }}=\operatorname{Pr}\left(\text { Class }_{i}\right) * \operatorname{IOU}_{\text {pred }}^{\text {truth }} Pr( Class i∣ Object )∗Pr( Object )∗IOUpred truth =Pr( Class i)∗IOUpred truth
损失函数设计
这里详细讲一下loss function。在loss function中,前面两行表示localization error(即坐标误差),第一行是box中心坐标(x,y)的预测,第二行为宽和高的预测。这里注意用宽和高的开根号代替原来的宽和高,这样做主要是因为相同的宽和高误差对于小的目标精度影响比大的目标要大。
第三、四行表示bounding box的confidence损失,就像前面所说的,分成grid cell包含与不包含object两种情况。这里注意下因为每个grid cell包含两个bounding box,所以只有当ground truth 和该网格中的某个bounding box的IOU值最大的时候,才计算这项。(应该是这两项吧?)
第五行表示预测类别的误差,注意前面的系数只有在grid cell包含object的时候才为1。
图解YOLO - 大雄的机器梦的文章 - 知乎
损失函数的设计目标就是让坐标(x,y,w,h),confidence,classification 这个三个方面达到很好的平衡。简单的全部采用了sum-squared error loss(平方误差求和)来做这件事会有以下不足:
a) 8维的localization error和20维的classification error同等重要显然是不合理的;
b) 如果一个网格中没有object(一幅图中这种网格很多),那么就会将这些网格中的box的confidence push到0,相比于较少的有object的网格,这种做法是overpowering的,这会导致网络不稳定甚至发散。
解决方案如下:
测试
Test的时候,每个网格预测的class信息( P r ( C l a s s i ∣ O b j e c t ) Pr(Class_i|Object) Pr(Classi∣Object))和bounding box预测的confidence信息( P r ( O b j e c t ) ∗ I O U pred truth Pr(Object)*\mathrm{IOU}_{\text {pred }}^{\text {truth }} Pr(Object)∗IOUpred truth )相乘。(上面已经出现过一次了)
Pr ( Class i ∣ Object ) ∗ Pr ( Object ) ∗ I O U pred truth = Pr ( Class i ) ∗ I O U pred truth \operatorname{Pr}\left(\text { Class }_{i} \mid \text { Object }\right) * \operatorname{Pr}(\text { Object }) * \mathrm{IOU}_{\text {pred }}^{\text {truth }}=\operatorname{Pr}\left(\text { Class }_{i}\right) * \mathrm{IOU}_{\text {pred }}^{\text {truth }} Pr( Class i∣ Object )∗Pr( Object )∗IOUpred truth =Pr( Class i)∗IOUpred truth
等式左边第一项就是每个网格预测的类别信息,第二三项就是每个bounding box预测的confidence。这个乘积既encode了预测的box属于某一类的概率,也有该box准确度的信息。
对每一个网格的每一个bbox执行同样操作: 7x7x2 = 98 bbox (每个bbox既有对应的class信息又有坐标信息)
得到98bbox的信息后,首先对阈值小于0.2的score清零(这个阈值是啥啊?随便设定的一个值一个变量名吗?),然后重新排序,最后再用NMS算法去掉重复率较大的bounding box(NMS:针对某一类别,选择得分最大的bounding box,然后计算它和其它bounding box的IOU值,如果IOU大于0.5,说明重复率较大,该得分设为0,如果不大于0.5,则不改;这样一轮后,再选择剩下的score里面最大的那个bounding box,然后计算该bounding box和其它bounding box的IOU,重复以上过程直到最后)。最后每个bounding box的20个score取最大的score,如果这个score大于0,那么这个bounding box就是这个socre对应的类别(矩阵的行),如果小于0,说明这个bounding box里面没有物体,跳过即可。
缺陷
YOLO对相互靠的很近的物体(挨在一起且中点都落在同一个格子上的情况),还有很小的群体 检测效果不好,这是因为一个网格中只预测了两个框,并且只属于一类。
测试图像中,当同一类物体出现的不常见的长宽比和其他情况时泛化能力偏弱。
由于损失函数的问题,定位误差是影响检测效果的主要原因,尤其是大小物体的处理上,还有待加强。
YOLO2 - 大雄的机器梦的文章 - 知乎 https://zhuanlan.zhihu.com/p/25167153
YOLO(v1)使用全连接层数据进行bounding box预测(要把1470 * 1的全链接层reshape为7 * 7 * 30的最终特征),这会丢失较多的空间信息定位不准。YOLOv2借鉴了Faster R-CNN中的anchor思想: 简单理解为卷积特征图上进行滑窗采样,每个中心预测9种不同大小和比例的建议框。由于都是卷积不需要reshape,很好的保留的空间信息,最终特征图的每个特征点和原图的每个cell一一对应。而且用预测相对偏移(offset)取代直接预测坐标简化了问题,方便网络学习。
总的来说就是移除全连接层(以获得更多空间信息)使用 anchor boxes 去预测 bounding boxes。具体做法如下:
Dimension Clusters(维度聚类)
使用anchor时,作者发现Faster-RCNN中anchor boxes的个数和宽高维度往往是手动精选的先验框(hand-picked priors),设想能否一开始就选择了更好的、更有代表性的先验boxes维度,那么网络就应该更容易学到准确的预测位置。解决办法就是统计学习中的K-means聚类方法,通过对数据集中的ground true box做聚类,找到ground true box的统计规律。以聚类个数k为anchor boxs个数,以k个聚类中心box的宽高维度为anchor box的维度。
如果按照标准k-means使用欧式距离函数,大boxes比小boxes产生更多error。但是,我们真正想要的是产生好的IOU得分的boxes(与box的大小无关)。因此采用了如下距离度量:
d ( b o x , centroid ) = 1 − I O U ( b o x , centroid ) d(b o x, \text { centroid })=1-I O U(b o x, \text { centroid }) d(box, centroid )=1−IOU(box, centroid )
上面左图: 随着k的增大,IOU也在增大(高召回率),但是复杂度也在增加。所以平衡复杂度和IOU之后,最终得到k值为5。上面右图:5聚类的中心与手动精选的boxes是完全不同的,扁长的框较少瘦高的框较多(这就是统计规律的力量)。