美文网首页
YOLO思路理解

YOLO思路理解

作者: 赤色要塞满了 | 来源:发表于2022-09-08 15:20 被阅读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。

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

  • grount truth为真实值,简称gt,是真实的目标物体的框子,所以,感觉也可以说成是objecttarget
  • label是标号,范围比gt大。gt只是正值,而在没有目标的区域,也是一个label
  • prediction是预测,detection是检测,infer是训练完了最后用于测试集的推理预测。其实意思差不多少。
  • 说到测试集test,一般这样理解:来了一批带label的数据,可以将其划分为训练集train和验证集validation,如果训练后的模型参数在验证集的表现还不错,那就把模型用在没有label的测试集test上预测推理,进行实践应用,所以test只用一次,且你不知道结果是否正确。不过,现在不少文章、代码所说的测试集其实是验证集,得自行分辨。

目标类别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。总结一下:

  • 如果一个cell包含了gt的中心点,那么label最后一维的张量类似这样:[0,0,0,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, x, y, w, h, 1, 0,0,0,0,0],最后5个0为补足;该cell的训练值为[c0,... c19, x1, y1, w1, h1, Conf1, x2, y2, w2, h2, Conf2, ],如果bbox1的定位[x1, y1, w1, h1]与目标值[x, y, w, h]IoU更大,那么[c0,... c19, x1, y1, w1, h1, Conf1]会向label靠拢。至于bbox2[x2, y2, w2, h2, Conf2],可能是自生自灭吧?这30个量的顺序不关键,有一些不同的排列法。
  • 如果一个cell没有包含了label_box的中心点,那么最后一维的张量全是0,也就是torch.zeros(25),也补足至torch.zeros(30)。该cell的两个bbox的训练值的Conf1Conf2都会向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

  • 问题1:如果两个目标中心戳中同一个cell,会发生什么事?
    超纲了,YOLOv1只能考虑一个cell一个object
  • 问题2:如果是同一类,但是是不同的目标呢?NMS怎么处理?
    这两个目标如果在同一个cell,见问题1;否则,这两个目标的bboxIoU会很小或者为0,所以NMS会都保留。
  • 问题3:如果置信度>1,或预测种类的概率之和>1,会怎样处理?
    对于置信度,数值看起来不合理,但应该也不影响最终结果的呈现,训练中可以试试用torch.clamp进行限制。预测种类的话,可以直接取最大值。另外,同一个目标属于两个种类,也不算离谱吧,比如正在播放猫和老鼠的电视机?后续再研究吧。
  • 问题4:如果两个bbox初始化后,与label_boxIoU都是0呢?
    IoU相同,代码默认取第一个值,所以第一个bbox会进行学习。

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

旷世开源,效果不错。

总结

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

相关文章

  • YOLO思路理解

    看了不少讲YOLO的文章,总感觉没有把关键细节说清楚,看了好像懂了,但细想到操作层面,又没完全懂。尝试简单总结捋一...

  • darknet-YOLOv3配置文件解析

    reference yoloV3参数理解及注释 yolo filters = 3*(classes+5) yolo...

  • Yolo知识整理,摘自网络

    Yolo 基本原理 滑动窗口与CNN 在介绍Yolo算法之前,首先先介绍一下滑动窗口技术,这对我们理解Yolo算法...

  • YOLO源码理解

    源码: 在网上挑了一个资料比较详细的源码入手:github地址:https://github.com/hizhan...

  • YOLO9000读书笔记

      YOLOv2作为YOLO的第二个版本,在思想上仍然延续了YOLO的总体思路,还是单阶段检测。其实,作者主要是结...

  • detection_layer层的实现

    detection_layer对应Yolov1的实现,理解detection_layer的实现主要需要理解Yolo...

  • [yolo] - 如何理解yolo(Darknet)的cfg文件

    yolo的cfg文件内容比较丰富,可以用于配置很多网络参数,暂时我还未发现有特别详细的介绍,根据网络上零星的描述,...

  • 目标检测YOLO系列——YOLO v3

    阅读本文之前,请先阅读前两代YOLO文章目标检测YOLO系列——YOLO v1目标检测YOLO系列——YOLO v...

  • YOLOv3代码分析(Keras+Tensorflow)

    前面(YOLO v3深入理解)讨论过论文和方案之后,现在看一下代码实现。YOLO原作者是C程序,这里选择的是Kea...

  • 深度学习知识点汇总-目标检测(6)

    8.6 YOLO 9000 YOLO 9000可以检测9000个类别?这么牛逼。 构造WordTree。 YOLO...

网友评论

      本文标题:YOLO思路理解

      本文链接:https://www.haomeiwen.com/subject/hjxynrtx.html