吴恩达深度学习课程笔记-11
04. 卷积神经网络
第三周 目标检测
3.1 & 3.2 分类定位和特征点检测
目标检测(detection)其实是一个非常困难的问题,一幅待检测图片中可能包含许多目标,这些目标的类别多种多样,同一类别的目标数目可能也不唯一。
可以从一个简化的问题去入手,那就是分类定位(classification with location)。这个问题只在图像分类任务上更进一步,不仅要分类,还要框出主要目标,且一张图片只有一个目标。
解决上面这个问题最直接的思路就是设定神经网络同时输出类别和位置的多个实数(\( b_x, b_y, b_h, b_w \))。
比如目标的类别有四种:行人、汽车、摩托车和背景。可以这样设置网络的输出和样本的标签:\( \begin{bmatrix} P_c \\ b_x \\ b_y \\ b_h \\ b_w \\ c_1 \\ c_2 \\ c_3 \end{bmatrix} \)
\( P_c \)表示是否存在物体,如果为0后面的值都没用了;\( c_1, c_2, c_3 \) 表示类别。
有了上面的经验,可以继续想,我们想要的神经网络输出的也可以是别的东西,比如特征点(landmark)。对于人脸来说,可以是眼角或者脸颊上的一些关键点:
比如要确定64个特征点,可以这么设置网络的输出:\( \begin{bmatrix} face \\ l_{1x} \\ l_{1y} \\ \vdots \\ l_{64x} \\ l_{64y} \\ \end{bmatrix} \),其中\( c \)表示是否是人脸。
3.3 滑动窗口
经过前面的铺垫,下面要正式讨论目标检测这个问题了,首先是传统做法:
我们训练分类器的数据是酱婶的:
所以在进行目标检测任务时,可以用滑动窗口滑过整个图像,对每一个窗口中的图像进行分类。可以选择不同大小的窗口,不同的步长:
这样做主要的问题就是计算代价,早期的分类器都是很简单的分类器,可能影响不大,但进入深度学习时代后,神经网络的速度其实相对比较慢的,这样的做法不再合适。
3.4 全卷积网络
在介绍检测方法之前,我们先看如何将之前讲的卷积神经网络转换为全卷积网络。
我们知道卷积神经网络其实是全连接网络的稀疏连接版本,又或者说全连接网络可以看作卷积神经网络的一种特殊情况(没有稀疏性)。所以全连接层可以用卷积表示:
可以看到全连接层用一个包含400个\( 5 \times 5 \times 16 \)的卷积核的卷积层代替。
滑动窗口方法的一个问题就是大量的重复计算。比如训练分类网络时的输入尺寸是\( 14 \times 14 \times 3 \),而待检测的图像尺寸是\( 16 \times 16 \times 3 \),如果采用滑动窗口需要对4个\( 14 \times 14 \times 3 \)的窗口进行分类,这其中有大量重叠区域重复计算,索性我们直接把\( 16 \times 16 \times 3 \)的图像直接输入到原网络(全卷积版本),可以得到最后的输出是\( 4 \times 4 \times 1 \),那么这4个输出就可以看作原来的4个窗口分别通过卷积网络计算的结果,但是这样节省了很多计算。换成更大的图片也同理。
这样做减少了计算量,但是还有一个问题,就是目标的边框不够准确。这点显然,因为输出的每个值都对应原图像中固定大小的一块区域,但是实际的物体可能有大有小,形状也或长或方。
3.5 Bounding Box预测
下面再介绍一种方法,也是著名的YOLO算法采用的方法。
回想最开始讲的分类定位问题思路:输入一张图片,网络直接输出物体的类别、检测框的位置和大小。因为检测框是用输出的一组实数来表示,所以准确度会更高,而不是像滑动窗口或全卷积网络那样固定大小的检测框。这是一个非常好的思路,问题在于这是一个过度简化的问题,假设了图片中只存在一个物体,而如果存在数量不定的多个物体,那么网络的输出维度就没办法确定。
然后我们就开始思考:如果将待检测图片进行切分,划分成网格状的图片块,然后对每个图片块都采取分类定位的方法,输出一个物体类别和检测框,这样就可以将输出维度确定下来了!
以上图为例,如果将一张图片分成9个小图,每个小图的输出和训练标签都是\( 8 \times 1 \)的向量,各个维度的含义:\( \begin{bmatrix} P_c \\ b_x \\ b_y \\ b_h \\ b_w \\ c_1 \\ c_2 \\ c_3 \end{bmatrix} \),\( P_c = 0 \)表示这个小图中没有检测目标,否则将给出检测框和类别。
所以这一张图片经过网络之后应该输出一个\( 3 \times 3 \times 8 \)的矩阵,我们将这个矩阵看作每个小图的检测结果。
注意:关于图像切分后分别进行分类定位的做法纯是我们的想法,是我们美好的愿望,我们希望神经网络这么干,但实际网络是怎么想的只有上帝知道!我们输入网络的不是切分的图片,而是完整的图片,通过标签和损失函数对网络进行约束,训练它输出每个网格上目标检测框的参数,它实际怎么学到的不清楚,只需要知道它的输出满足了我们这种网格化设计的要求即可。所以每个网格上预测的检测框尺寸并不局限于所在的那个网格,这点要理解!
还有一些细节:
- 这种方法是通过划分网格来解决多目标的问题,显然当网格划分的足够密时,每个格子中出现多个目标的概率就越低;
- 一个物体可能会被划分到多个格子中,因此这里规定物体归属于其中心点所在的格子,而其他格子虽然也有一部分,但处理时忽略;
- 表示检测框的\( b_x, b_y, b_h, b_w \)都是\(0 \sim 1\)间的数,是以对应格子的位置和尺寸为基准的比例表示法;
3.6 & 3.7 交并比和非极大值抑制
我们通常用交并比(Intersectioni over union, IoU)来衡量物体检测的效果,顾名思义,就是算法输出与实际标注的检测框交集与并集之比。
一般取IoU > 0.5算作正确检测,当然也可以选择更高的阈值。
非极大值抑制(Non-max suppression, NMS)是一种常用的方法,很简单,从字面理解就是:不是极大值的都会被抑制。
注意两点:第一,是极大值而不是最大值;第二,抑制就是抛弃。
做个不是特别恰当的类比,期末考试后老师给班上的同学发奖状,但是只发给单科状元,这就叫极大值抑制。每一科我只承认第一名,其它的都是垃圾不算数。
对于目标检测来说,当检测结果出来之后,首先抛弃\(P_c\)值低于一定阈值的结果,然后开始处理各个极大值。非极大值抑制就是指当检测结果出现单个目标有多个检测框重叠时,先取\( P_c \)最大的框(置信度最高),然后将其它和这个框高度重叠的检测结果抛弃。
图片中存在多个目标类别时,要对每个类别都独立的采取极大值抑制。
3.8 Anchor Boxes
如果再仔细思考,就会发现前面的算法还是有问题:每个网格只能预测一个目标。如果不幸的,两个目标的中心恰好落在了一个网格中,网络就无能为力了。
解决方法是引入 Anchor Boxes.
简单的说,上面的问题是由于我们前面规定网络的输出比如\( 3 \times 3 \times 8 \)只能表示一个检测框,如果我们事先规定一些检测框并按形状进行分类,这样对于每个网格就可以用多种不同的检测框进行检测,这样就可以输出多个检测结果。比如规定两种检测框的网络输出可以是\( 3 \times 3 \times 2 \times 8 \)或\( 3\times 3\times 16 \),每个网格对应的16个分量就可以表示两个目标了。
这种预设的框就叫做anchor box。
以前我们只需要将目标分配到其边框中心点所在的网格,现在还要计算其边框与该网格不同anchor box的交并比大小,并依此进一步分配到网格的某个achor上,也就是上图中那个长向量的某一段。
3.9 YOLO算法
将前面所介绍的组合起来就是YOLO算法了。
首先你要准备训练集,要按照前面的要求准备每个网格的向量,训练网络;
然后做出预测,过滤掉那些置信度低的框,再对每个类别的框进行非极大值抑制,的到最后的结果。
3.10 RPN网络
我以为会讲R-CNN路径的一些方法,其实只是粗略的提了一下。
关于R-CNN和YOLO之争,其实就是目标检测领域的两步法和一步法之争。R-CNN等需要先想办法提出目标的一些候选框,然后再进行后面的工作,准确率更高;而YOLO等强调一步完成,速度更快。
吴恩达老师看好一步法。