之前提到的R-CNN,需要先找到可能包含物体的框,然后进行前背景分类,消除重叠框,进行边界框回归和分类,这个过程就十分繁琐,速度很慢,虽然准确率不错,但如果想要实现实时的目标检测就很难了,于是接下来就介绍一下速度较快的YOLOv1(you only look once)系列模型。
首先来简单介绍一下YOLOv1的思想,我们先来想一下,我们看一幅照片的时候,是不是扫一眼,找到感兴趣的地方(目标),然后再从照片的某个位置开始看的,也就是说,其实人类确定目标和确定目标的范围是一个十分迅速且同时进行的过程。当然,回想一下faster R-CNN,其实它也是希望先找出region proposal,再分析region内保不包含目标,可是利用RPN找region的过程更像是学习大量的图片,记住了不同图像的目标可能出现在什么位置,然后遇到了一幅新图像,就去可能出现目标的区域验证一下,这样不是说不行,但是就麻烦耗时间了,所以R-CNN速度就慢了,但是我觉得它的这个方向还是可以借鉴的。
那么YOLOv1是怎么做的呢,第一,最重要的是YOLOv1选择直接输出边界框的信息和分类结果,而不是先分析边界框再分析分类结果,把two stage变成了one stage,这是YOLOv1速度提升的原因,第二,既然YOLOv1的输出是同时输出边界框和分类结果,如果我们的分析对象还是整副图像,那么就要求模型具有十分厉害的特征提取能力,才能分析出一张图像具有多少个目标,每个目标在哪里了,所以YOLOv1就简化了一下,不让模型分析整幅图像,而是把图像分成了s*s个区域,一个一个区域进行分析。
具体我们可以先看看YOLOv1的模型,再分析它是如何做到把图像分成s*s个区域的:
从上图我们可以看到,假设图像输入尺寸为448x448x3,最终特征图变成了7x7x30,通过卷积运算,就把图像分成了7x7个区域,每个区域用一个长度为30的特征向量表示,这时候,我们就可以利用这个特征向量,分析该区域的边界框和分类结果了,比如说,可以利用全连接层分析,最后输出边界框的左上角坐标xy,宽高wh,以及各个类别的概率值。
上面这样做其实是还不够的,回想一下我们把图像分成了7x7个区域,那么每个区域都会预测出边界框以及分类结果,可是我们总不能把这49个结果都输出吧,所以模型还需要学会判断,到底哪个区域的输出是正确的,是包含目标的,就保留,其余的一律舍弃。怎么让模型学会识别呢,就是让计算每个区域的置信度,设置一个阈值,置信度超过阈值就保留这个区域的信息,低于阈值就舍弃。
所以我们再来看看这个置信度是怎么计算的:
c o n f i d e n c e = P r ( c l a s s ) ∗ I o U confidence = Pr(class) * IoU confidence=Pr(class)∗IoU
Pr(class)就是目标落在区域内的概率,训练的时候,这个要么就是1要么就是0,后面的IOU则是预测的bounding box和真实的之间的IoU。
现在再来考虑一个问题,一个目标可能比较大,占据了多个区域,假设每个区域预测一个边界框,然后这个目标占据了五个边界框,可能最终模型就会输出五个十分接近、重叠度很高的边界框,所以我们就需要非极大抑制,去除重复的边界框,然后就可以得到最终的输出了。
最后我们再回顾一下YOLOv1,他把图像分成是s*s个区域再进行分析,每个区域可以预测多个边界框,但是只能分析一个目标类别,也就是说,假如一个区域内存在两个不同类别的目标,它是识别不出来的,这就意味着YOLOv1对小目标的识别效果并不好,所以后期也从这个问题出发进行改进。
另一方面,虽然一开始说把图像分成s * s再进行分析,但其实因为卷积运算的特性,最后得到的s * s的区域之间也是相互联系而不是完全分隔开的,或者说,我们在分析某一个小区域的时候,也附带了整幅图像的信息,这就是YOLOv1最大的优点,正因为能利用全局信息,所以YOLOv1也更不容易在背景上预测出错误的目标信息。
在github写的自然语言处理入门教程,持续更新:NLPBeginner