吴恩达卷积神经网络章节笔记(三)——目标检测
视频课程链接:
https://www.bilibili.com/video/BV1FT4y1E74V?
笔记参考链接:
https://blog.csdn.net/weixin_36815313/article/details/105728919
1. 目标定位 (Object Localization)
1.1 基本概念
对于图像分类和定位问题,通常只有一个较大的对象位于图片中间位置,我们要对它进行识别和定位。而在目标检测问题中,图片可以含有多个对象,甚至单张图片中会有多个不同分类的对象。因此,图片分类的思路可以帮助学习分类定位,而目标定位的思路又有助于学习目标检测,我们先从分类和定位开始讲起。
对于解决图像分类问题的步骤,可简单描述为输入一张图片到多层卷积神经网络,它会输出一个特征向量,并反馈给softmax单元来预测图片类型。假设分类的对象包括以下几类:行人、汽车、摩托车和背景,则softmax函数会输出这四个分类的预测结果。
上述内容是标准的分类过程,要想再定位图片中汽车的位置,则可以让神经网络多输出4个单元,分别标记为
b
x
b_x
bx,
b
y
b_y
by,
b
h
b_h
bh和
b
w
b_w
bw,即输出一个被检测对象的边界框(Bounding Box)的参数化表示。这里的
b
x
b_x
bx和
b
y
b_y
by表示边界框的中心点坐标,
b
h
b_h
bh和
b
w
b_w
bw表示边界框的高度和宽度。
1.2 标签定义
接下来具体讲讲如何为监督学习任务定义目标标签
y
y
y。假如上图的汽车图像是一张训练集图片,标记为
x
x
x,经过神经网络输出的是边界框参数和一个分类标签,或分类标签出现的概率。目标标签
y
y
y的定义如下:
y
=
[
p
c
b
x
b
y
b
h
b
w
c
1
c
2
c
3
]
y=\begin{bmatrix} p_c \\ b_x \\ b_y \\ b_h \\ b_w \\ c_1 \\ c_2 \\ c_3 \end{bmatrix}
y=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡pcbxbybhbwc1c2c3⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤
它是一个向量,其中第一个组件
p
c
p_c
pc表示是否含有对象,如果对象属于前三类(行人、汽车、摩托车),则
p
c
=
1
p_c=1
pc=1;如果是背景,即图片中没有要检测的对象,则
p
c
=
0
p_c=0
pc=0。第二到第五个组件
b
x
b_x
bx、
b
y
b_y
by、
b
h
b_h
bh和
b
w
b_w
bw表示边界框的各项参数。第六到第八个组件
c
1
c_1
c1、
c
2
c_2
c2和
c
3
c_3
c3分别表示该对象属于1-3类中的哪一类,是行人,汽车还是摩托车。如果该对象为行人,则
c
1
=
1
c_1=1
c1=1,其余为0;如果该对象为汽车,则
c
2
=
1
c_2=1
c2=1,其余为0;如果该对象为摩托车,则
c
3
=
1
c_3=1
c3=1,其余为0。
如果检测到对象,则
p
c
=
1
p_c=1
pc=1,同时输出被检测对象的边界框参数
b
x
b_x
bx、
b
y
b_y
by、
b
h
b_h
bh、
b
w
b_w
bw以及该对象类别
c
1
c_1
c1、
c
2
c_2
c2和
c
3
c_3
c3。如果图片中没有检测对象,则
p
c
=
0
p_c=0
pc=0,此时
y
y
y的其它参数将变得毫无意义。
1.3 损失函数
这里将标签 y y y的预测输出定义为 y = [ y 1 y 2 y 3 y 4 y 5 y 6 y 7 y 8 ] y=\begin{bmatrix} y_1 \\ y_2 \\ y_3 \\ y_4 \\ y_5 \\ y_6 \\ y_7 \\ y_8 \end{bmatrix} y=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡y1y2y3y4y5y6y7y8⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤。损失函数可以定义为 L ( y ^ , y ) = { ( y 2 ^ − y 2 ) 2 + ( y 3 ^ − y 3 ) 2 + ( y 4 ^ − y 4 ) 2 + ( y 5 ^ − y 5 ) 2 y 1 = 1 ( y 1 ^ − y 1 ) 2 y 1 = 0 L(\hat{y},y)=\begin{cases} (\hat{y_2}-y_2)^2+(\hat{y_3}-y_3)^2+(\hat{y_4}-y_4)^2+(\hat{y_5}-y_5)^2 & y_1=1 \\ (\hat{y_1}-y_1)^2 & y_1=0 \\ \end{cases} L(y^,y)={(y2^−y2)2+(y3^−y3)2+(y4^−y4)2+(y5^−y5)2(y1^−y1)2y1=1y1=0通常做法是对边界框坐标应用平方差或类似方法,对 p c p_c pc应用逻辑回归函数,甚至采用平方预测误差,而不需要对 c 1 c_1 c1、 c 2 c_2 c2、 c 3 c_3 c3和softmax激活函数应用对数损失函数。
2. 特征点检测 (Landmark Detection)
上一节讲了如何利用神经网络进行目标定位,即通过输出四个参数值
b
x
b_x
bx、
b
y
b_y
by、
b
h
b_h
bh和
b
w
b_w
bw给出图片中对象的边界框。更概括地说,神经网络可以通过输出图片上特征点坐标
(
x
,
y
)
(x,y)
(x,y)来实现对目标特征的识别。
以人脸识别为例,假设你希望算法可以给出眼角的具体位置坐标
(
x
,
y
)
(x,y)
(x,y),你可以让神经网络的最后一层多输出两个数字
l
x
l_x
lx和
l
y
l_y
ly,作为眼角的坐标值。假设你想知道两只眼睛的四个眼角的具体位置,那么从左到右,依次输出四个特征点坐标来表示这四个眼角,例如输出第一个特征点
(
l
1
x
,
l
1
y
)
(l_{1x},l_{1y})
(l1x,l1y),第二个特征点
(
l
2
x
,
l
2
y
)
(l_{2x},l_{2y})
(l2x,l2y),以此类推,这四个脸部特征点的位置就可以通过神经网络输出了。
除了以上所述的特征点,你还可以根据嘴部的特征点输出值来确定嘴的形状,从而判断人物是在微笑还是皱眉。如果你对人体姿态检测感兴趣,你还可以定义一些关键特征点,如胸部的中点,左肩,左肘,腰等,然后通过神经网络标注人物姿态的关键特征点,再输出这些标注过的特征点,就相当于输出了人物的姿态动作。
3. 目标检测 (Object Detection)
以构建一个汽车检测算法为例,大致的步骤如下:
-
创建一个标签训练集, x x x表示汽车图片样本, y y y表示对应的图片标签(建议可以适当剪切图片,使汽车居于中间位置并基本占据整张图片)
-
利用这个标签训练集训练卷积网络,即输入这些适当剪切过的图片,经过卷积神经网络输出预测结果 y ^ \hat{y} y^,0和1分别表示图片中有汽车或没有汽车。
-
训练完这个卷积神经网络,就可以用它来使用滑动窗口法实现目标检测。
- 选定一个特定大小的窗口,将这个窗口内的图像输入到卷积神经网络,神经网络判断方框内是否有汽车。
- 然后窗口向右滑动一定步长,并将窗口内的图像输入给卷积神经网络,再次运行神经网络进行判断,依次重复以上操作,直到这个窗口滑过图像的每一个角落。
- 选择一个更大的窗口,截取窗口区域并输入给卷积神经网络进行判断,再以某个固定步幅滑动窗口,重复以上操作,遍历整个图像。
- 继续扩大窗口大小,重复以上操作,这样不论汽车的大小以及在图片的什么位置,总有一个窗口可以检测到它。
滑动窗口的目标检测算法具有明显的缺点,就是计算成本。你需要在图片中剪切出很多的小方块,并且一个个输入给卷积神经网络进行处理。如果选用的步幅很大,则会减少输入卷积网络的窗口个数,但是粗粒度可能会影响检测性能。反之,如果采用细粒度或小步幅,传递给卷积网络的小窗口会特别多,但这意味着超高的计算成本。
4. 滑动窗口的卷积实现 (Convolutional Implementation of Sliding Window)
为了构建滑动窗口的卷积应用,首先要知道如何把神经网络的全连接层转化成卷积层。
假设输入一个
14
14
14×
14
14
14×
3
3
3的图像,使用16个大小为
5
5
5×
5
5
5的过滤器进行卷积操作后,输出大小为
10
10
10×
10
10
10×
16
16
16的图像,经过一个窗口大小为
2
2
2×
2
2
2的最大池化层,图像尺寸减小到
5
5
5×
5
5
5×
16
16
16。然后将其展开成一个一维数组,接着再添加一个具有400个单元的全连接层,最后通过softmax单元输出4个分类的概率,这4个分类分别对应是行人、汽车、摩托车和背景。
接下来将全连接层转化成卷积层。前面的卷积层部分保持不变,输出图像的尺寸为
5
5
5×
5
5
5×
16
16
16,使用400个维度大小为
5
5
5×
5
5
5×
16
16
16的过滤器对它进行卷积操作,其输出维度为
1
1
1×
1
1
1×
400
400
400。这里我们不再把它看作一个含有400个节点的集合,而是一个
1
1
1×
1
1
1×
400
400
400的输出层。从数学角度看,它和全连接层是一样的,因为这400个节点中每个节点都有一个维度为
5
5
5×
5
5
5×
16
16
16的过滤器,所以每个值都是上一层这些
5
5
5×
5
5
5×
16
16
16激活值经过某个任意线性函数的输出结果。
然后使用400个
1
1
1×
1
1
1的过滤器进行卷积操作,则下一层的输出维度是
1
1
1×
1
1
1×
400
400
400。最后再通过4个
1
1
1×
1
1
1的过滤器处理,得到一个softmax激活值。经过卷积神经网络的作用,最终得到这个
1
1
1×
1
1
1×
4
4
4的输出层。
假设输入给卷积神经网络的图片大小是
14
14
14×
14
14
14×
3
3
3,测试集图片是
16
16
16×
16
16
16×
3
3
3。在最初的滑动窗口算法中,首先将这片蓝色区域输入到神经网络中,输出预测的分类结果0或1,然后向右滑动2个像素,将这个绿框区域输入到神经网络,得到另外一个分类标签0或1。接下来继续将这个橘色区域输入给神经网络,卷积后得到另一个分类标签,最后对右下方的紫色区域进行一次卷积操作。最终,在输出层这4个子方块中,左上角子方块对应的是输入图像左上部分
14
14
14×
14
14
14区域的输出(红色箭头标识),右上角子方块对应的是输入图像右上部分
14
14
14×
14
14
14区域的输出(绿色箭头标识),左下角子方块对应的是输入图像左下部分
14
14
14×
14
14
14区域的输出(橘色箭头标识),右下角子方块对应的是输入图像右下部分
14
14
14×
14
14
14区域的输出(紫色箭头标识)。
结果发现,这4次卷积操作中很多计算都是重复的,即在执行滑动窗口的卷积过程中,卷积网络在这4次前向传播过程中共享了很多计算。因此我们不需要把输入图像分割成四个子集,分别执行前向传播,而是把它们作为一张图片输入给卷积神经网络进行计算,其中的公共区域可以共享很多计算。这样一来就提高了整个算法的效率,但是这种算法仍然存在一个缺点,就是边界框的位置可能不够准确。
5. Bounding Box 预测 (Bounding Box Predictions)
假设输入图像的尺寸是
100
100
100×
100
100
100,将其划分成
3
3
3×
3
3
3网格。如果定义训练标签,需要对9个格子逐一定义一个训练标签
y
=
[
p
c
b
x
b
y
b
h
b
w
c
1
c
2
c
3
]
y=\begin{bmatrix} p_c \\ b_x \\ b_y \\ b_h \\ b_w \\ c_1 \\ c_2 \\ c_3 \end{bmatrix}
y=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡pcbxbybhbwc1c2c3⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤,其中
p
c
p_c
pc表示这个格子中是否有对象,如果这个格子里有对象,那么就会给出边界框坐标
b
x
b_x
bx、
b
y
b_y
by、
b
h
b_h
bh和
b
w
b_w
bw,
c
1
c_1
c1、
c
2
c_2
c2和
c
3
c_3
c3表示识别的三个类别,不包括背景类别。YOLO算法的做法是,取两个对象的中点,然后将这个对象分配给包含对象中点的格子。即使中心格子同时有两辆车的一部分,也假装中心格子没有任何我们感兴趣的对象。
如果训练一个输入为 100 100 100× 100 100 100× 3 3 3的卷积神经网络,将图像输入给神经网络,因为这里划分成 3 3 3× 3 3 3网格,每一个格子都会得到一个8维输出向量,因此最终得到一个 3 3 3× 3 3 3× 8 8 8的特征向量。
6. 交并比 (Intersection over Union)
交并比(loU)函数做的是计算两个边界框交集和并集之比,其中两个边界框的并集就是图中的绿色阴影部分),而交集就是图中的橙色阴影部分,因此交并比的计算就是把橙色阴影面积除以绿色阴影面积。
一般来说,在计算机检测任务中,如果
I
o
U
≥
0.5
IoU\geq0.5
IoU≥0.5就算检测正确,如果预测器和实际边界框完美重叠,即交集等于并集,loU就是1。人们定义loU这个概念是为了评价你的目标定位算法是否精准,这是衡量定位精确度的一种方式,你只需要统计算法正确检测和定位目标的次数,就可以用这样的定义来判断对象定位是否准确。
7. 非极大值抑制 (Non-max Suppression)
假设在上面这张图片里检测行人和汽车,将其划分成
19
19
19×
19
19
19的网格,理论上每辆车只有一个中点,即只有一个格子做出有车的预测。但实际上每个格子都运行一次图像检测和定位算法,神经网络可能会认为这辆车的中点在1号格子内部,也可能在2号或3号格子内部,因此可能会对同一个对象做出多次检测,而非极大值抑制的作用就是清理这些多余的检测结果。
实现非最大值抑制的步骤大致如下:
- 去掉所有预测概率 p c p_c pc小于或等于某个阈值(假设阈值为0.6)的边界框;
- 在剩余的的边界框中,选择概率 p c p_c pc最高的边界框。
- 遍历剩余的的边界框,如果和当前最高分框的交并比(IOU)大于一定阈值,则将这个边界框删除。
- 接下来在剩余的边界框中选择概率 p c p_c pc最高的边界框,重复上面的步骤2。
8. 锚框 (Anchor Boxes)
Anchor Box是为了解决同一个网格中有多个目标对象的情况。而现实情况中,你的网格划分越细,这种情况发生的就越少。
以上图为例,仍然使用
3
3
3×
3
3
3网格对图像进行划分,可以看到行人的中点和汽车的中点几乎在同一个网格中,而原先定义的标签
y
y
y无法同时输出两个预测结果。
因此重新定义一个类别标签(如上图),其中
p
c
p_c
pc表示这个格子中是否有对象,
b
x
b_x
bx、
b
y
b_y
by、
b
h
b_h
bh和
b
w
b_w
bw表示标记对象的边界框坐标,
c
1
c_1
c1、
c
2
c_2
c2和
c
3
c_3
c3分别表示识别的三个类别,不包括背景类别。绿色方框标记的元素与Anchor box 1对应,橙色方框标记的元素与Anchor box 2对应。
Anchor Box的思路是,首先根据对象形状定义多个不同形状的Anchor Box,然后找出与每个Anchor Box交并比最大的实际边界框,将实际边界框的标签作为Anchor Box的标签,并且计算Anchor Box相对于真实边界框的偏移量。在本例子中Anchor Box的个数为2,输出标签
y
y
y的维度是
3
3
3×
3
3
3×
16
16
16或
3
3
3×
3
3
3×
2
2
2×
8
8
8。
目前Anchor Box的选择主要有如下三种方式:
- 人为经验选取
- k-means聚类
- 作为超参数进行学习