符号约定:
对目标定位任务,神经网络除了需要识别图像中的目标以外,还需要定位,所以神经网络的输出除了对图像的分类,还有图像的位置参数 dx、dy、dh、dw d x 、 d y 、 d h 、 d w 。
位置参数的理想值:
dx=0.5、dy=0.7、dh=0.3、dw=0.4 d x = 0.5 、 d y = 0.7 、 d h = 0.3 、 d w = 0.4
网络现在有8个参数:
那么,标签 y y 的第一个参数 pc p c 表示:是否存在目标。
可以将 pc p c 理解为被检测图像属于某一分类的概率(分类1:存在目标,分类2,不存在目标)。
损失函数分为存在目标和不存在目标两种情况。
因为在不存在目标时,其他七个参数没有意义。只需要考虑 pc p c 的准确度。
上图中,采用平方误差来说明损失函数在不同情况下的区别之处。
实际上,可以不用对softmax层输出的 c1、c2、c3 c 1 、 c 2 、 c 3 使用对数似然损失函数。通常做法是对坐标 dx、dy、dh、dw d x 、 d y 、 d h 、 d w 应用平方误差或者类似方法。对 pc p c 应用像逻辑回归算法的损失函数,或者平方误差也可以。
神经网络可以通过位置 dx、dy、dh、dw d x 、 d y 、 d h 、 d w 对目标进行定位,即给出图片中对象的边界框。
神经网络也可以通过输出图片上特征点的(x, y)坐标,来实现对目标特征的识别。
比如人脸表情检测,通过在人脸上标注一些特征点标签,来训练神经网络,达到检测人脸表情的能力。或者定位人脸上的具体部位,达到能给人带诸如皇冠、食品的能力。
比如人体姿态检测,通过在人体上标注一些特征点标签,来训练神经网络,神经网络的输出即为是否存在目标以及目标的特征点坐标。假设有32个特征点,那么神经网络的输出为1+32 × × 2 = 65个。
ps:标签在所有图片中必须保持一致,比如人脸检测,特征点1一开始标注的是人的左眼外侧眼角,那么在整个数据集中,特征点1都应该只标注左眼外侧眼角。
知道了目标定位和特征点检测,接下来开始构建目标检测算法。
基于滑动窗口的目标检测算法(sliding windows detection algorithm):
构建一个汽车检测算法。
第一步先创建一个数据集,这个数据集中的图片应该适当裁剪,以使得整张图片几乎都被汽车占据且汽车要居于中心位置。
那么存在汽车的图片标签为1,不存在则为0。
第二步训练神经网络,输入这些适当剪切过的图像,网络输出 y y 。
第三步用这个训练好的神经网络来实现滑动窗口目标检测算法。具体步骤如下:
这种做法的结果是,不论汽车在哪里,总有一个窗口可以检测到它。
这就是滑动窗口目标检测。
缺点:计算成本高。因为截取出了太多的小方块,都需要卷积网络一个一个地处理。
如果选择的步幅大,会减少输入卷积网络的小图像个数。但粗粒度可能会影响性能。
如果选择的步幅小,细粒度导致小图像特别多,这个时候就有着超高的计算成本。
在卷积神经网络之前,通常使用的是更加简单的分类器进行目标检测。因为每个分类器的计算成本都很低,所以滑动窗口目标检测算法表现良好。
但卷积神经网络运行单个分类任务的成本高,采用滑动窗口太慢了。
现在,计算成本问题有了解决方案,提高了在卷积网络上应用滑动窗口目标检测的效率。
用卷积层替换FC层:
之前网络是通过400个权重转换到第一个FC层(有400个单元),但是现在,用了400个5 × × 5 × × 16的过滤器,生成了一个1 × × 1 × × 400的卷积层。
同理,第二个FC层用400个1 × × 1 × × 400的过滤器生成一1 × × 1 × × 400的卷积层。
最后的softmax层为4个输出,也用4个1 × × 1 × × 400的过滤器生成1 × × 1 × × 4的卷积层。
这就是用卷积层代替全连接层。
卷积实现滑动窗口:
思路来自论文:
ps:
卷积:s=1、p=0−−−>卷积后的高度和宽度=n−f+1 卷 积 : s = 1 、 p = 0 − − − > 卷 积 后 的 高 度 和 宽 度 = n − f + 1
最大池化:s=2、p=0−−−>卷积后的高度和宽度=⌊n−fs+1⌋ 最 大 池 化 : s = 2 、 p = 0 − − − > 卷 积 后 的 高 度 和 宽 度 = ⌊ n − f s + 1 ⌋
上图是卷积层代替全连接层的网络。
如果现在需要这个网络来实现目标检测,怎么样提高效率呢?
可以看到,将图像截取成四幅14 × × 14图片输入,有一部分像素点是重复计算的。
而将整副图像卷积到最后,结果相同,因为共享重复像素点,提高了计算效率。
上图中,输出的8 × × 8的每一个像素点,都是输入图像中相应的一块14 × × 14的区域卷积的结果。
卷积实现类似滑动窗口给目标定位的效果,可以提升算法的效率,减少运算。但仍然没有解决的问题是,不能输出精准的边界框。
你的预测是蓝色框,甚至都没有完全包含整个汽车。
理想的框不但要完全包含汽车,还应该是个长方形框(恰好包含,不多不少),而不是正方形。
用什么办法输出精准的边界框呢?
YOLO:you only look once(只看一次)。
YOLO算法:
把图像分为3 × × 3的网格。在每一个网格内逐一应用图像分类与定位算法。
将要进行分类并定位的图像用3 × × 3的网格划分成9份。每一份都有自己的标签。每个标签的维度为8,那么整个图像的标签为3 × × 3 × × 8。
目标属于哪一个网格的小图像?
比如图中的汽车,汽车的中心点被划分到了哪一个网格,那么目标就属于哪一个网格。
下图中,虽然中心区域的小网格内有汽车的一部分,但是因为没有中心点,所以,视为没有汽车。
有了标签以后,就可以设计卷积神经网络,将这个100 × × 100 × × 3的图像输入,输出3 × × 3 × × 8的结果。
ps:每一个网格中最多只允许出现一个目标,比如上图一个网格内不能有两个汽车的中心点。 所以实际中,一个100 × × 100的图像可能使用19 × × 19的网络,标签为19 × × 19 × × 8。这么精细的网格,多个目标分配到同一个格子的概率就小的多。
YOLO和图像分类和定位算法很像,即显式的输出边界框坐标。但这种算法可以让神经网络输出具有任意宽高比的坐标,且更精确。不会受到滑动窗法分类器的步长大小限制。
其次,并没有在3 × × 3网格上跑9次算法。这是单次卷积实现。使用的卷积神经网络有很多共享计算步骤(在处理3 × × 3网格的计算中很多计算步骤是共享的)。所以算法的效率很高。
YOLO 的好处,也是它受欢迎的原因,就是:这个一个卷积实现(而不是多个或者多次)。所以它的运行速度非常快,可以达到实时识别。
YOLO论文:
这篇论文比较难,后续加油看。
关于坐标的细节:
每一个小方块的左上角坐标为(0,0),右下角为(1,1)。那么, bx、by b x 、 b y 必须介于0到1之间。而 bh、bw b h 、 b w 必须大于0,有可能会大于1。
IoU:用来判断预测的边界框是否正确。即评价目标定位算法的定位是否精准。
计算预测的框和实际目标的框的交集和并集之比。
一般比值大于0.5视为比较好的预测结果。也可以设置成0.6甚至0.7。
如果预测器和实际边框完美重叠,那么IoU=1。
除了可以判断预测的边界框是否正确以外,也可以判断两个边界框是否相似。
到目前为止,学习到的算法都会对同一个目标进行多次检测。非极大值抑制可以做到对每个对象只检测一次。
如果有多个类别的目标,比如图像中有人、车、摩托,那么分别对这三个类别进行独立的非极大值抑制。
到目前为止,算法还只能做到一个格子中只检测一个目标。如果要做到一个格子中检测到多个目标,需要使用 Anchor Boxes.
左下图,左侧图像的行人和汽车的中心点在同一个格子中,标签 y y 无法检测是人还是汽车,只能从车和人中选择一个。
anchor box的思路是:预先定义两个不同形状anchor box。把预测结果和这两个anchor box关联起来。一般来说,需要不止两个anchor box,可能要5个甚至更多。为讲解方便,使用两个anchor box。
之前的目标是被分配到了格子中(包含目标中心点的格子)。
现在,目标被分配到格子、以及和目标形状有最高IoU的anchor box。即目标的编码方式成为(中心点所在的格子,anchor box)
ps:
如果只有两个anchor box,但是同一个格子有三个目标(形状不一样),这种情况算法处理不好。
如果两个目标都分配到了一个格子中,且它们的anchor box形状也一样,这种情况算法也处理不好。
出现上述情况的次数不多,对算法性能的影响一般也不大。
anchor box 是为了处理两个目标出现在一个格子里的情况。但一般网格分的细致时,出现这一情况的频率不高。
anchor box的好处:使得更有针对性。如果 数据集中不同类型目标的形状很不同的话,算法就更够更有针对性的处理。
一般手工指定anchor box形状 ,YOLO 算法有更好的实现,可以将两类目标的形状聚类。
划分格网,以及anchor box,这里划分为3 × × 3,两个anchor box。那么每一个小格子就有16个数据或者说标签 y y 是2 × × 8。那么整副图像的标签是3 × × 3 × × 2 × × 8。
实际操作中,格网的划分会很细致,比如19 × × 19。anchor boxes的类型也会有多个(比如5到10个)。那么整副图像的标签是19 × × 19 × × 5 × × 8。
anchor box是对应到标签 y y 的,比如上图中,anchor box 1 和 y y 的前8个数据对应。anchor box 2 和 y y 的后8个数据对应。
如果某一个格子里不存在目标,那么对应的标签 y y 的所有 pc=0 p c = 0 ,其他值无所谓。
如果某一个格子里存在一个目标,那么,接下来会检测目标的bounding box(也就是目标的框)和预先给出的anchor box的IoU。选择具有最大IoU的ahchor box,这个anchor box对应部分的标签值的 pc=1 p c = 1 ,其他值 dx、dy、dw、dh。。。 d x 、 d y 、 d w 、 d h 。 。 。 都具有意义。这里注意, dw、dh d w 、 d h 是可以大于1的。其他的anchor对应的标签 y y 的相应位置的 pc=0 p c = 0 。比如上图,汽车所在格子,检测到目标的bounding box 和 anchor box 2的IoU最大,所以,标签如图像最右侧所示。
如果一个格子中存在多个目标(anchor box为此而生,且一个萝卜一个坑,萝卜不能比坑多):