YOLOv1的结构很简单,和一般的分类网络差别不大。主要是损失函数的设计以及对于训练过程的设计,还有就是网络输出代表的含义。
YOLOv1的输出是一个7*7的矩阵,它假设网络相应index的输出对应于输入图片相应的grid,每个index对应几个b-box,这个b-box是有限定的,它的中心处于grid中,因此我们的目标之一应该是是判断grid中是否包含某个物体的中心,假如中心没有包含在grid中的话,那么对应的index给出的所有b-box也不会准确。
所以,我们的任务应该有:第一:要判断grid中是否有物体的中心。
第二:对b-box进行微调预测。
第三:对b-box所含物体种类进行预测。
但这样,由于一个grid中含有多个b-box,在测试的时候,我们虽然可以根据第一个的概率值得出可能还有物体的grid,却无法判断是哪一个b-box含有物体。所以应该有:
第四:b-box中是否含有物体。如果可以的话,预测出IOU值
在测试的时候,我们根据第一选取出grid(设置一个阈值),根据第四选取出b-box,根据第二和第三获得b-box预测的标签和形状,就完成了目标检测。
在训练的时候,如果grid中有物体中心,对应的index的b-box就有损失,第一也有损失,第三也好办,第四可以通过IOU值来给定是否含有物体的概率。
但是YOLOv1的设计与上面并不一致。它将第三和第一合并,统一为grid包含哪个物体的中心,也就是说,这两个b-box不管如何都是对一种物体的判断,它的任务就是下面三条:
第一:grid包含哪个物体的中心。对应于p(class | object)
第二:对b-box进行微调预测。对应于(x,y,w,h)
第三:b-box中是否含有物体。如果有的话,预测出IOU值。对应于p(object) * predict_IOU(GT, DR)
测试的时候,我们将第一和第三的概率相乘,得到类别概率*IOU,通过阈值来得到b-box。
训练的时候,如果物体中心出现在grid中,对该grid的p(class|object)进行训练。如果物体与某个b-box重合,就对b-box进行训练。
一下我们可以发现它方法的一些问题:
网络结构:
第一个问题:对于一个grid,YOLOv1只能给出一种物体的判断,假如有多种物体的话,就只能识别出一种物体,而且由于存在多个物体,对于各个种类的probobility也会下降, 降低class-specific confidence scores,使得其在测试阶段不被选出,间接的降低了准确率。但是事实上多个物体的中心处在同一个grid的情况并不多见,所以影响可能并不大。它这种将多个b-box的分类都交给grid的原因可能是因为考虑到这些b-box的中心都位于grid中,因此这些b-box很可能对应于同一个物体,这样做能够学习到更多的分类能力,因为共享了分类训练。
第二个问题:对于中心没有在grid中的GT,假如存在着另外的b-box要比中心grid产生的b-box更加准确的话,那么就会让那个b-box进行学习,而实际上是错误的进行了学习。当然这种情况也不多见,因为假如物体的中心都位于grid中了,那么grid中的b-box只要不是过于错误,那么其IOU总是最大的那个。
第三个问题:对于物体的不同形状,YOLOv1虽然将w,h进行了开根号处理来减少尺度影响,让小框损失更大,大框损失更小,从而提高IOU,但是对于中心点却并没有进行考虑,对于大框,中心点偏差的影响依然是小的,而小框的影响是很大的,但是这并没有反映在损失中。这会导致它对小物体的检测结果不好。
第四个问题:在这个网络中,每个grid的学习是分开进行的,这导致我们必须需要大量的样本,才能让损失都能传递给每个grid。
第五个问题:由于最终的feature map只是7*7的map,虽然保留的大量的高层信息(语义),但是却损失了底层信息(主要是空间位置上的),导致对于物体的位置判断不够精确,实际中,定位问题的确占了很大一部分。
损失函数:
第一个问题:如果我们把损失函数的最后一项关于分类的拿掉,我们会发现什么?定位任务是与类别标签无关的,只要出现了一个20类中的物体,检测器就要给出b-box,并且confidence(P(obj) * IOU )就会高,假如它真的能够做到这一点,那说明之前的feature map中出现了与类别无关的部分。但由于实际中,它有较多的错误都是定位引起的,所以这一点并不能肯定。我认为将定位与分类完全分开也并不是一个好主意,因为我们本身就对物体有一个先验的知识,关于它的大小的(或许吧)。