深度学习(十六):目标检测 Object Detection
这是一系列深度学习的介绍,本文不会涉及公式推导,主要是一些算法思想的随笔记录。
适用人群:深度学习初学者,转AI的开发人员。
编程语言:Python
参考资料:吴恩达老师的深度学习系列视频
吴恩达老师深度学习笔记整理
深度学习500问
笔记下载:深度学习个人笔记完整版
目标检测 Object Detection
如何通过卷积网络进行对象检测,采用的是基于滑动窗口的目标检测算法。即我们以某个步幅滑动这些方框窗口遍历整张图片,对这些方形区域进行分类,判断里面有没有汽车。
滑动窗口目标检测算法也有很明显的缺点,就是计算成本,因为你在图片中剪切出太多小方块,卷积网络要一个个地处理。如果你选用的步幅很大,显然会减少输入卷积网络的窗口个数,但是粗糙间隔尺寸可能会影响性能。反之,如果采用小粒度或小步幅,传递给卷积网络的小窗口会特别多,这意味着超高的计算成本。
滑动窗口的卷积实现(Convolutional implementation of sliding windows)
为了构建滑动窗口的卷积应用,首先要知道如何把神经网络的全连接层转化成卷积层。如下:
对于编号1对应的全连接层,我们可以用5×5的过滤器来实现,数量是400个(编号1所示),输入图像大小为5×5×16,用5×5的过滤器对它进行卷积操作,过滤器实际上是5×5×16,因为在卷积过程中,过滤器会遍历这16个通道,所以这两处的通道数量必须保持一致,输出结果为1×1。假设应用400个这样的5×5×16过滤器,输出维度就是1×1×400,我们不再把它看作一个含有400个节点的集合,而是一个1×1×400的输出层。从数学角度看,它和全连接层是一样的,因为这400个节点中每个节点都有一个5×5×16维度的过滤器,所以每个值都是上一层这些5×5×16激活值经过某个任意线性函数(一般是RELU)的输出结果。
我们再添加另外一个卷积层(编号2所示),这里用的是1×1卷积,假设有400个1×1的过滤器,在这400个过滤器的作用下,下一层的维度是1×1×400,它其实就是上个网络中的这一全连接层。最后经由1×1过滤器的处理,得到一个softmax激活值,通过卷积网络,我们最终得到这个1×1×4的输出层,而不是这4个数字(编号3所示)。
将全连接层和softmax层都去除,用卷积层代替
如何通过卷积实现滑动窗口对象检测算法:
假设输入给卷积网络的图片大小是14×14×3,测试集图片是16×16×3,现在给这个输入图片加上黄色条块,在最初的滑动窗口算法中,你会把这片蓝色区域输入卷积网络(红色笔标记)生成0或1分类。接着滑动窗口,步幅为2个像素,向右滑动2个像素,将这个绿框区域输入给卷积网络,运行整个卷积网络,得到另外一个标签0或1。继续将这个橘色区域输入给卷积网络,卷积后得到另一个标签,最后对右下方的紫色区域进行最后一次卷积操作。我们在这个16×16×3的小图像上滑动窗口,卷积网络运行了4次,于是输出了了4个标签。
所以该卷积操作的原理是我们不需要把输入图像分割成四个子集,分别执行前向传播,而是把它们作为一张图片输入给卷积网络进行计算,其中的公共区域可以共享很多计算,就像这里我们看到的这个4个14×14的方块一样。
之所以不需要输入四个子集,是因为网络结构全部由卷积层组成,由于卷积对图像没有尺寸限制要求,所以输入图片不用限定尺寸,如果是全连接层,就限定了上一层的输入。
又由于最后的输出由最后一层卷积的filters个数决定,取代了softmax。
Bounding Box预测(Bounding box predictions)
滑动窗口法的卷积实现,这个算法效率更高,但仍然存在问题,不能输出最精准的边界框。其中一个能得到更精准边界框的算法是YOLO算法,**YOLO(You only look once)**意思是你只看一次。
如果你现在要训练一个输入为100×100×3的神经网络,现在这是输入图像,然后你有一个普通的卷积网络,卷积层,最大池化层等等,这样最后就映射到一个3×3×8输出尺寸,对应九个网格的输出y,每个输出y是一个八维向量,如上面示例定义的一样。由于车辆边界可能超出网格框,所以输出的bw和bh可以大于1,这也就是为什么能输出精准边界的原因。
如上,我们给网格标号从左到右,再从上到下,分别标,号1~9,图中有两个对象,YOLO算法做的就是,取两个对象的中点,然后将这个对象分配给包含对象中点的格子。所以左边的汽车就分配到这个格子上(编号4),然后右边这辆分配给这个格子(编号6)。虽然网格5都有两个对象的某部分,但是由于没有对应的中心点,所以网格5输出向量中Pc=0。
只要每个格子中对象数目没有超过1个,这个算法应该是没问题的,一个格子中存在多个对象的问题,我们稍后再讨论。但实践中,我们这里用的是比较小的3×3网格,实践中你可能会使用更精细的19×19网格,所以输出就是19×19×8。这样的网格精细得多,那么多个对象分配到同一个格子得概率就小得多。
可以看出,这和图像分类和定位算法非常像,它显式地输出边界框坐标,这能让神经网络输出边界框,可以具有任意宽高比,并且能输出更精确的坐标,不会受到滑动窗口分类器的步长大小限制。其次,这是一个卷积实现,你并没有在3×3网格上跑9次算法,你使用了一个卷积网络,有很多共享计算步骤,在处理这3×3计算中很多计算步骤是共享的,所以这个算法效率很高,它的运行速度非常快,可以达到实时识别。
交并比(Intersection over union)
交并比(Intersection-over-Union,IoU),目标检测中使用的一个概念,是产生的候选框(candidate bound)与原标记框(ground truth bound)的交叠率,即它们的交集与并集的比值。最理想情况是完全重叠,即比值为1。
如上图,在对象检测任务中,比如你的算法给出这个紫色的边界框,而实际车的边界框是红色框,那么这个结果是好还是坏?所以交并比(loU)函数做的是计算两个边界框交集和并集之比,这个橙色阴影面积,然后除以绿色阴影的并集面积。
一般约定,在计算机检测任务中,如果IoU>=0.5,就说检测正确,结果是可以接受的,看起来还可以。一般约定,0.5是阈值,用来判断预测的边界框是否正确。如果你希望更严格一点,你可以将loU定得更高,比如说大于0.6或者更大的数字,但loU越高,边界框越精确。
非极大值抑制(Non-max suppression)
交并比(IOU)和**非极大值抑制(NMS)**是目标检测任务中非常重要的两个概念。例如在用训练好的模型进行测试时,网络会预测出一系列的候选框。这时候我们会用NMS来移除一些多余的候选框。即移除一些IOU值大于某个阈值的框。然后在剩下的候选框中,分别计算与ground truth的IOU值,通常会规定当候选框和ground truth的IOU值大于0.5时,认为检测正确。
所以当你运行对象分类和定位算法的时候,最后可能会对同一个对象做出多次检测,所以非极大值抑制做的就是清理这些检测结果。这样一辆车只检测一次,而不是每辆车都触发多次检测。
非最大值意味着你只输出概率最大的分类结果,但抑制很接近,但不是最大的其他预测结果,所以这方法叫做非极大值抑制。

所以具体上,这个算法做的是,首先看看每次报告每个检测结果相关的概率Pc,首先看概率最大的那个,然后就说这是最可靠的检测,所以我们就用高亮标记,就说我这里找到了一辆车。这么做之后,非极大值抑制就会逐一审视剩下的矩形,所有和这个最大的边框有很高交并比,高度重叠的其他边界框,那么这些输出就会被抑制。
如果你尝试同时检测三个对象,比如说行人、汽车、摩托,那么输出向量就会有三个额外的分量。事实证明,正确的做法是独立进行三次非极大值抑制,对每个输出类别都做一次。
Anchor Boxes
到目前为止,对象检测中存在的一个问题是每个格子只能检测出一个对象,如果你想让一个格子检测出多个对象,你可以这么做,就是使用anchor box这个概念。
假设你有上述图片,按照上面思路,我们继续使用3×3网格,注意行人的中点和汽车的中点几乎在同一个地方,两者都落入到同一个格子中,所以这时候的输出不再是八维向量。
anchor box的思路是,预先定义两个不同形状的anchor box,你要做的是把预测结果和这两个anchor box关联起来。一般来说,你可能会用更多的anchor box,可能要5个甚至更多,这里只用两个,那么输出将是16维向量。所以行人更类似于anchor box 1的形状,所以对于行人来说,我们将她分配到向量的上半部分,车会被分配到向量的下半部分。
我们建立anchor box这个概念,是为了处理两个对象出现在同一个格子的情况,实践中这种情况很少发生,特别是如果你用的是19×19网格而不是3×3的网格,两个对象中点处于361个格子中同一个格子的概率很低,确实会出现,但出现频率不高。
那么应该怎么选择anchor box呢?人们一般手工指定anchor box形状,你可以选择5到10个anchor box形状,覆盖到多种不同的形状,可以涵盖你想要检测的对象的各种形状。还有一个更高级的版本,后期YOLO论文中有更好的做法,就是所谓的k-平均算法,可以将两类对象形状聚类,如果我们用它来选择一组anchor box,选择最具有代表性的一组anchor box,可以代表你试图检测的十几个对象类别,但这其实是自动选择anchor box的高级方法。如果你就人工选择一些形状,合理的考虑到所有对象的形状,你预计会检测的很高很瘦或者很宽很胖的对象,这应该也不难做。
融会贯通:YOLO 算法(YOLO algorithm)
已经学到对象检测算法的大部分组件了,现在,把所有组件组装在一起构成YOLO对象检测算法。
构建训练集:假设你要训练一个算法去检测三种对象,行人、汽车和摩托车,你还需要显式指定完整的背景类别。这里有3个类别标签,如果你要用两个anchor box,那么输出 y就是3×3×2×8,或者3×3×16。要构造训练集,你需要遍历9个格子,然后构成对应的目标向量y。(简单起见,我在这里用的是3×3网格,实践中用的可能是19×19×16,或者需要用到更多的anchor box)。
预测:输入图像,你的神经网络的输出尺寸是这个3×3×2×8,对于9个格子,每个都有对应的向量。
最后要运行一下这个非极大值抑制,以下面的测试图片为例:
你使用两个anchor box,那么对于9个格子中任何一个都会有两个预测的边界框(下图编号1所示)
接下来你抛弃概率很低的预测(编号2所示)。
最后,如果你有三个对象检测类别,你希望检测行人,汽车和摩托车,那么你要做的是,对于每个类别单独运行非极大值抑制,处理预测结果所属类别的边界框,用非极大值抑制来处理行人类别,用非极大值抑制处理车子类别,然后对摩托车类别进行非极大值抑制,运行三次来得到最终的预测结果。所以算法的输出最好能够检测出图像里所有的车子,还有所有的行人(编号3所示)。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)