YOLO思路理解

2022-09-08  本文已影响0人  赤色要塞满了

看了不少讲YOLO的文章,总感觉没有把关键细节说清楚,看了好像懂了,但细想到操作层面,又没完全懂。尝试简单总结捋一下,主要是v1,后面的不定期补充吧。

YOLOv1

整体思路是通过一些技巧,把目标检测转化为一个回归问题,一步到位,提高检测速度。原论文网络结构叫做darknet,各种卷积块+两个全连接层,当时还没发明批量归一化batch normalization,现在可以加上,中间的激活层选用Leaky ReLU,当然也可以使用其它深度网络,比如ResNet等。

首先看训练。将448*448(目标检测的分辨率要高于图像分类)的图片平均分成7*7=49cell,或叫grid。每个cell预测2个框bounding box,简称bbox,类似锚框anchor。这个bbox尺寸最小为0,最大为整个图片。每个bbox的定位localization只需要4个值,有不同的格式,如两点式(左上角和右下角坐标:x1, y1, x2, y2)、左上角式(左上角+宽高:x, y, w, h)、中心点式(中心点+宽高:x, y, w, h),原论文是中心点式。每个bbox还有1个置信度Conf,这就一共(4+1)*2=10个值。除了预测bbox,还要从比如20个物体种类里预测1个类别,每个类别给出一个概率,一共20个值,最后输出N*7*7*30N为图片数。这些数值可以随机初始化,两个bbox可以一大一小初始化,提高效率。

因为是回归任务,所以x, y, w, h都要进行归一化,x, y为相对于cell左上角的坐标,其值为0~1之间,w, h要除以图片的宽高,也就是448*448,其值也为0~1之间。有的文章将其除以cell的宽高,这导致w, h的值为0~7之间,也能计算,但感觉不合适。

刚才提到了置信度Conf。虽然1个cell预测了2个bbox,但YOLOv1里,1个cell只预测1个object,两个bbox其实是竞争关系,最终只有一个bbox得到了更新。训练计算损失时,看谁的Conf大,谁才被考虑进损失函数进行更新。而Conf=Pr(Object)*IoUIoU为预测的bboxground_truth_box的交并比。再看Pr(Object),如果ground_truth_box的中心坐标落在某cell里,那么Pr(Object)=1,否则为0。所以当Pr(Object)=1时,就是比谁的IoU大,当Pr(Object)=0时,label_Conf也为0。可以认为,最终预测输出的也是Pr(Object)IoU的乘积,只不过预测的Pr(Object)是一个连续值,而不是label的非1即0。

插一些闲话,这里有几个单词术语让人头大,试着自己理解下,不一定对:

目标类别label_classes采用onehot编码,比如某个label_box是第5类,且中心在某个cell,那么label_classes就是[0,0,0,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0],否则全为0。训练或推理时,输出就没这么干净了,每一个都是0~1之间的概率值,这个概率值其实是条件概率Pr(Class-i|Object),所以最终还要将这个概率值Pr(Class-i|Object)乘以Conf,然后取这20个中的最大值为最终预测种类,这样更保险,意思是你必须先有目标,再来谈这是个什么类别。

每个cell只有1个label_box,所以label形状其实应该是N*7*7*25,但为了与训练的N*7*7*30一致,会在后面补0。总结一下:

可以看到,输出N*7*7*30中会有一些值自生自灭并不进行更新,那最终呈现结果时,会对输出进行筛选整理,比如筛掉低Conf、进行NMS等。

再看看原论文的损失函数。

image.png
其中S=7, B=21obj(i)表示如果label_box中心戳中了第i个cell,则值为1,否则为0。1obj(i,j)表示如果label_box中心戳中了第i个cell,且第j个bboxlabel_boxIoU较大,则值为1,否则为0。1noobj(i,j)与其相反。
第1行,1obj(i,j)bbox坐标与label_box的方差,一般权重λcoord=5
第2行,类似第1行,但宽高必须开方参与计算,避免大尺寸偏差重要性大于小尺寸的偏差。
第3行,类似1/2行,1obj(i,j)bboxConf的方差,label_Conf一般为1。
第4行,没有被目标中心戳中的cell的2个bboxConf的方差,一般权重λnoobj=0.5label_Conf为0。
第5行,1obj(i)cell的类别概率的方差损失。

推理时,预测了7*7*2=98bbox,首先筛掉低Conf的,比如小于0.4的,然后使用非极大值抑制NMSNMS一般是按照预测类别分别独立计算的(也有所有类一视同仁的做法),比如都是预测猫,那么选择一个Conf最大的bbox,如果其它也预测猫的bbox与这个最大ConfbboxIoU超过了一个阈值,例如0.5,那么就筛掉。这一部分不只是针对Yolo,而是目标检测通用做法。

怎么评价预测结果呢?这里引入一个全类平均正确率mAP,也是先按类计算,首先看预测框的IoU是否超过了阈值(比如0.5),超过了为TP,否则FP。然后将这些框按Conf倒序排列,每个gt最多一个框与之对应,开始统计Recall=TP/(TP+FN)Prec=TP/(TP+FP),然后求出Recall-Prec关系图的面积,即为AP,最后对所有种类求平均,则为mAPmAP越大越好,0.9就很不错了。更详细的做法是针对多个阈值进行计算再取平均,记为mAP@0.5:0.05:0.95

YOLOv2(Yolo 9000)

主要改进:

  1. 加入了batch normalization
  2. 448*448ImageNet上进行预训练。
  3. grid变成13*13,且每个cell预测9个bbox,并给出先验的大小。再根据COCOVOC的数据进行聚类,最后选择K=5,效果还可以。聚类时用1-IoU做为距离。
    image.png
  4. 摒弃全连接层,全用卷积。
  5. 优化bbox的坐标和宽高公式: bx = σ(tx) + cxby = σ(ty) + cybw = pw * exp(tw)bh = ph * exp(th)Pr * IoU = σ(to)t为需要学习的参数,bx, by, bw, bhbbox的定位,cx, cycell的左上角坐标,pw, ph为先验框的尺寸。为啥用指数,可能为了限制为正值?
  6. passthrough层将上一层一拆四(尺寸降半),与上一层的卷积结果(刚好也尺寸降半)直接叠加进行输出,从而保留上一层的小尺寸细节。有点残差的意思。
  7. 分层分类,采用WordTree,在分类数据集和检测数据集上联合训练,提高识别种类到9000+。

YOLOv3

主要改进:

  1. 基础网络升级至darknet53,之前是19。
  2. 分类损失采用二分类交叉熵损失binary cross-entropy loss,因为目标可能属于多个分类。
  3. 使用3个尺度预测,引入FPN (Feature Pyramid Network),特征图大小分别是8*816*1632*32

分隔线,pjreddie退出YOLO,后续版本重在工程应用。

YOLOv4

主要各种调参、缝合、数据增强。

YOLOv5

小而快,打比赛推荐。

YOLOX

旷世开源,效果不错。

总结

纸上得来终觉浅,试试吧!

上一篇 下一篇

猜你喜欢

热点阅读