美文网首页
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思路理解

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