文章目录
- 引言
- 目标定位
- 特征点检测
- 目标检测
- 卷积的滑动窗口实现
- 边框预测
- 交并比
- 非极大值抑制
- 锚框
- YOLO算法
- 参考
引言
本文是吴恩达深度学习第四课:卷积神经网络。本次课程将会告诉大家如何构造卷积神经网络并应用到图像数据上。从中你会学到如何构建一个卷积神经网络、如何应用卷积神经网络到图像识别和目标检测上、学习如何使用神经风格转换去生成艺术作品、能将这些算法应用到更广泛的图像应用上,比如2D、3D数据和视频。
第四课有以下四个部分,本文是第一部分。
- 卷积神经网络基础
- 深度卷积模型:实例分析
- 目标检测
- 特殊应用:人脸识别&神经风格转换
目标定位
在实现目标检测(对象检测)之前,我们先了解一下目标定位。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SNxITM3AzY2EjZ2YmN4U2YyYzX0UDO0YTMzEzLcdDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
在图像分类中我们可以知道这张图片中有没有汽车。
而定位分类问题不仅要判断图片中是否有汽车,如果有的话还要在图片中标出它的位置。
而检测问题是,当图片中有多个对象时,应该如何检测它们并确定出位置。
在对象检测问题中,图片中可以含有多个对象。先看下图像分类
图像分类问题我们已经很熟悉了,可以用卷积神经网络来做,这里比如有四个类别,分别是行人、汽车、摩托和背景。
那如果还想定位图片中汽车的位置,应该如何做呢
我们可以改变上面分类网络的输出,让它输出一个边框(bounding box)。
具体的就是输出四个数:。
左上角的坐标定为,右下角定为。
边框的中间点坐标为,边框的高和宽为和。
然后就可以使用监督学习算法输出一个分类标签,还有这四个数值,从而给出被检测对象的边框位置。
在这个例子中约为,因为它在x轴方向中间位置,约为,表示汽车位于距离图片底部的位置。
表示边框高度是图像高度的倍,同理表示宽度为图片宽度的倍。
下面定义下输出向量,第一个元素表示是否含有目标对象,如果图片中含有行人、汽车或摩托则,否则。
接下来是边框的四个数值。
然后如果,那么还要输出图片中包含3个类别的概率:
这里我们先假设图片中只含有一个对象。
下面我们来看几个例子。
这个图片中有汽车,所以,然后是边框值,汽车属于第二个类别,因此,其他都为零。那如果图片中没有要检测的类别呢?
此时,那么其他值就无意义了,因此我们不关心其他元素值。
我们可以根据这样的方式定义训练集。
最后介绍一个训练神经网络的损失函数。
如果采用平方误差,若,就有下面的式子:
因为我们输出的有8个元素,比如第一个元素是,最后一个元素是。此时用平方误差可以减少这8个元素值与实际输出值结果之间的差值平方。若,那么损失为
因为这种情况下,我们不考虑其他元素。
以上就是利用神经网络解决对象分类和定位问题的过程,结果证明,利用神经网络输出批量实数来识别图片中的对象是个非常有用的算法。
下节和大家分享另一种思路,把神经网络输出的实数集作为一个回归任务。
特征点检测
神经网络可以输出图片上特征点的坐标来实现母特征的识别。
(这是吴恩达夫人)
假设你希望算法可以给出四个眼角的具体位置,你可以让神经网路多输出8个值,代表眼角的坐标,从左到右。
也许除了这四个特征点,你还想得到更多的特征点输出值,
比如眼睛和鼻子嘴巴的特征点。这样可以判断人物是在微笑还是皱眉。
你可以设定特征点的个数,这里假设有64个。可以包括更多的信息,比如脸颊的位置。
选定特征点的个数,并生成包含这些特征点的标签训练集,然后利用神经网络输出脸部关键特征点的位置。
用卷积神经网络来做的话,也是输出是否含有人脸,接着是这64个特征点的坐标。这个例子中有个输出。
由此可以实现对图片的人脸检测和定位。
检测脸部特征点也是计算机图形效果的一个关键构造模块,可以实现头戴皇冠和脸部扭曲等特效。
显然要训练这样一个网络,需要训练数据集,训练集中的特征点都是人为辛苦标注的。
如果对人体姿态感兴趣,还可以标出人体姿态的一些关键特征点。
值得一提的是,所有图片中的特征点要保持一致,比如第一个特征点是左眼的左边眼角,第二个特征点是左眼的右边眼角坐标。
目标检测
现在我们来构建一个目标检测算法。我们要用卷积网络进行目标检测,采用的是基于滑动窗口的目标检测算法。
假设你想构建一个汽车检测算法,首先你需要创建一个标签训练集。其中表示适当剪切的汽车图片样本,
对于这个训练集,你一开始可以使用适当剪切的图片,就是整张图片几乎都是汽车。
有了这个训练集,你就可以开始训练卷积神经网络了。
输入是适当剪切了的图片,输出就是是否为汽车。训练完这个卷积网络,就可以用它来实现滑动窗口目标检测。
假设这是一张测试图片,首先选定一个特征大小的窗口(滑动窗口),比如上图那个红框。然后将这个红框输入到这个卷积神经网络中,然后只取这个小框内的图像。把这个小框内的图像输入到上面学习的卷积神经网络中,让卷积网络预测这个小框内是否有汽车。
接下里要做的是移动小框的位置,输入第二个小框内的图像。用卷积网络判断其中是否含有汽车。
以此类推,知道滑动窗口遍历了图像中的所有位置。
现在用这个滑动窗口遍历完图像之后,再用更大的窗口来遍历一次。
遍历完了之后还可以用一个更大的窗口再遍历一次。
我们希望,只要图像汇总某处有一辆车,就会有某个窗口输入到卷积神经网络中得到。比如希望这个窗口输出
这样就检测到这里有一辆汽车。这就是滑动窗口算法。
不过,滑动窗口检测算法有一个很大的缺点,就是它的计算成本。因为你裁剪出了很多不同的正方形图像。并让每个图像都单独通过卷积神经网络进行运算,如果你使用一个很大的步长,那么窗口数就会减少。
但是比较粗的粒度可能会影响算法的表现。如果你用了较小的步长,就会得到很多窗口。将它们全部通过卷积神经网络意味着很高的计算成本。
幸运的是,这个计算成本的问题有一个很好的解决方案。我们下节介绍。
卷积的滑动窗口实现
我们先看下如何将卷积网络中的全连接层转化为卷积层。
假设有一个这样的卷积神经网络,这里用softmax输出四个类别。
现在来展示如何将上图红线中的这些层转换为卷积层。
这是一个卷积神经网络,前几层和之前相同。现在实现这一层全连接层的一个方式是用步长为1大小为(400个)的过滤器代替之前的全连接层。
拿的图像和的过滤器做卷积操作,所以输出大小为。
从数学上来讲,这和一个全连接层是一样的。
因为这400个节点中每个节点都有一个的过滤器,所以每个值都是上一层这些激活值经过某个任意线性函数的输出结果。
接着再添加另一个(400个)的卷积层,在这400个过滤器的作用下,下一层的大小是。
最后通过过滤器的处理,得到一个softmax激活值。
以上就是用卷积层代替全连接层的过程。
我们再看看如何通过卷积实现滑动窗口对象检测算法。
内容借鉴了 OverFeat: Integrated Recognition, Localization and Detection using Convolutional Networks
假设像滑动窗口卷积网络输入的图片,为了简化。
假设你测试集图片是。
在最初的滑动窗口算法中,你会把红框这部分蓝色方块输入到卷积网络,得到0或1分类。
接着滑动窗口,步长为2,得到下面这个绿框方块,让后将其输入到卷积网络中得到输出。
继续滑动,接着输入下面黄框方块到卷积网络,得到输出。
再一次向右移动,得到紫框方块,输入卷积网络得到分类输出。
所以我们在这个的图像上滑动窗口,让卷积网络运行了4次,输出了4个标签。
但是,这4次卷积操作中的很多计算都是重复的,滑动窗口卷积方式的实现是让这4次卷积神经网络的前运算共享计算过程。
具体的你可以这么做,你可以运行这个卷积神经网络,用同样的参数和相同的16个的过滤器,得到一个的输出。
然后像之前一样,做最大池化,得到。接着使用相同的400个的过滤器得到一个的卷积输出。
再经过一个的过滤器得到另一个的输出,再做一次同样的操作就可以得到的输出。
最终在输出层这4个子方块中,蓝色的是图像左上部分(红框方块)的输出。
同理其他3个方块对应不同颜色区域的输出。
如果具体想看某一块方块的运算过程,比如绿框方块,它就是下面这样的:
所以该卷积操作的原理是,我们不需要把输入图片分割成四个子集,分别执行前向传播,而是把它们作为一张图片输入给卷积网络进行计算。
其中公共区域可以共享很多计算。
再来看一个输入图像更大的例子。
最终输出矩阵的最左上子方块对应着输入的这块区域。
然后以步长为2不停的移动,就可以得到整个输出。
以上就是在卷积层上应用滑动窗口算法的内容,它提高了整个算法的效率。
不过这个算法仍然有一个缺点,就是边框的位置可能不够准确。
下节来学习如何解决这个问题。
边框预测
在滑动窗口中,你取这些离散的位置集合,此时这些边界框没有一个能完美匹配汽车位置。
也许上图这个框是最匹配的了。
但是它的真实值可能不是一个方向,而是一个矩形。那有没有办法让这算法输出更精准的边框呢其中一个能得到更精准的边框的算法是YOLO(you only look once)算法。该算法是这么做的,
假设你的图像是的,在上面放一个(这里只是为了演示,实际上可能取)的网格。然后使用图像分类和定位算法应用到这9个格子中。
此时你需要这样定义训练标签,对于9个格子中的每一个,指定一个标签,
像前面介绍的一样,顶一个一个8维向量。
这张图有9个格子,每个格子都有这样一个向量。
我们看下左上方这个格子,里面没有要检测的对象,所以它的输出是
我们直接来看有对象的格子,这张图里面共有两个要检测对象。YOLO算法做的是取这个对象的中点,然后将这个对象分配给包含对象中点的格子。
这两辆车的中点分别在绿色和黄色格子里面,它们中间的那个格子即使同时包含两辆车的一部分,也不会说它有要检测的对象。
所以每个格子都有一个8维的输出向量,总的输出大小为。
这个算法的优点是可以输出精确的边框,所以测试的时候,只要喂入测试图像,然后正向传播就能得到输出。
我们现在学习的还是一个格子中只有一个对象的问题。
YOLO算法和图像分类和定位算法非常像,即能显示地输出边框坐标,但是可以具有任意高宽比,并且能输出更精确的坐标。
并且这是一个卷积实现,使用卷积网络可以有很多共享计算步骤,所以这个算法的效率很高。
如何编码实现呢,
以黄框里面的格子为例,它的输出会是右边这样的。还是指定左上角的坐标为,右下角的坐标为。
这里(在之间)说的是目标对象中点位置左边,而(可能大于)是相对格子大小的比例。这里只是一种编码约定,其实还有其他更加复杂的方式。
交并比
在对象检测任务中,我们希望也能同时定位到对象。
如果对象的实际边框是红色,我们的算法给出的是紫色。那么如何评价这个结果的好坏呢。可以用交并比来做。交并比(IoU,intersection over union)做的是计算两个边框交集和并集之比。
这两个对象的并集是绿色填充的这一区域。
而交集是黄色较小的区域。那么交并比就是计算交集的大小除以并集的大小。
一般约定交并比的结果不小于就是检测正确的。如果预测结果和实际边框完美重叠,则交并比取最大值。
IoU越大说明定位越精确。
非极大值抑制
现在为止我们学到的对象检测中的一个问题是,我们的算法可能对同一个对象作出多次检测。
而最大值抑制这个方法可以确保算法对每个对象只检测一次。
假设我们要在这张图里面检测行人和汽车,我们放一个的网格,这张图里面有两辆车,每辆车都只有一个中点。
假设中点如上图所示,理论上应该只有两个格子作出有车的预测。但实际当你跑分类和定位算法时,可能会有多个格子预测有车,如下图,每个对象区域内都有3个格子预测有车。
现在我们看一下非最大值抑制是怎么生效的,因为要在个格子上都跑一次图像检测和定位算法,那么可能很多格子都会说它这个格子里面有车的概率很高。
而实际上这幅图应该只有两个格子能检测到对象。
所以当你的算法对同一个对象作出多次检测时,此时应用非最大值抑制做的就是清理这些检测结果。首先看每个格子报告有目标的概率是多大,这里上图中的数字就是这个概率。
然后找到概率最大的那个,然后非最大值抑制就会一一检测剩下的矩形,所有和这个最大的边框有很高交并比(高度重叠)的其他边框都会被抑制,
所以分别是和的两个暗蓝色矩阵和的矩阵重叠程度很高,都会被抑制。
同理左边的车,概率为的矩形就会被抑制(变暗)。此时如果抛弃变暗的矩形,最后就得到了两个预测结果。
所以这就是非最大值抑制,意味着只输出概率最大的结果。
下面来看一下这个算法的细节。首先在这个的网格上跑一下算法,就会得到的输出尺寸。
这个例子我们简化一下输出,假设只做汽车检测,也就是去掉了。
现在要实现非最大值抑制,做的第一件事情是去掉所有不大于某个阈值的边框,这里阈值假设是。
接下来在剩下的边框中,
只要还有剩余边框(循环):
- 重复地选择概率最大的边框,当成输出边框,预测结果
- 丢掉其他剩余边框,这些边框都和输出边框有很高的的IoU(上面介绍的变暗的那些边框)
直到每个边框都判断过了,它们有的作为输出结果,有的被丢掉了。
锚框
到目前为止,对象检测中存在的一个问题是,每个格子只能检测出一个对象。
如果你想让一个格子检测出多个对象,那么就要使用锚框(anchor box)。
还是从例子开始介绍,假设你有张这样的图片:
行人的中点和汽车的中点几乎处在相同的位置。所以对于中点所在的这个格子,
将不知道输出哪一个,因为必须从两个结果中选一个。
而anchor box的思路是预先定义两个不同形状的anchor box形状:
你要做的就是将预测结果与这两个anchor box关联起来。此时的输出定义成这样,即同时输出两个边框信息:
使用anchor box后,每个对象都被分配到对象中点所在的格子中,和一个IoU值最高、具有对象形状的anchor box中。
比如你有个对象时红框形状的,你有两个anchor box,此时IoU值最高的anchor就是竖着的那个。下面举个实际的例子,
这个格子有两个对象,它的输出如上图右边那个向量所示,首先是行人形状的anchor box1,下面接着一个汽车形状的anchor box2。
那假设这个图像中只有汽车,没有行人,那输出会是怎样的呢,还是假设汽车的形状是anchor box2那样的。
就是anchor box2的输出还是一样的,但anchor box1的,我们不关心其他值的输出了。
虽然我们把anchor box当成处理两个对象中点都一样的情形,但实际上出现这种情形的概率并不高,尤其你用了的格子的时候。
YOLO算法
利用上面所学的知识来介绍一下YOLO算法,先来看下如何定义训练集。
如果是一个的格子,两个anchor box的话,那么就有的输出。
要构造训练集,需要遍历9个格子,每个格子都会输出。
第一个格子里面啥都没有,因此它的输出应该是上图右边这个向量这样的。
这张图中大部分格子里面都没有物体,除了绿框的这个格子。
假设这两个anchor box是这样的,并且anchor box2的交并比更高,因此得到的输出就是和输出向量下半部分有关的。
所以遍历所有的格子,最终得到的输出大小是
所以训练集就是这样的,然后你可以训练一个卷积神经网络。
接下来看这个算法是如何进行预测的,
对于左上角这个格子,期望的输出是两个都是,此时我们不关心其他值的输出。而对于绿框的这个格子,期望的输出是:
第二个anchor输出的,并且刚好是红框那个位置。
下面说明一下非最大值抑制,我们看另外一张图片。
假设有两个anchor box,这样每个格子都会有两个边框输出,其中有个更低
假设所有输出的边框是这样的,注意上面有些边框的大小可以超出所在格子的高度和宽度。接下来要抛弃所有概率低的预测,
得到了上面这样的结果,假设你要预测行人、汽车和摩托这三种类别。那么要做的是,对每个类别,单独运行非最大值抑制,来处理预测结果是那个类别的边框。
参考
- 吴恩达深度学习 专项课程