课程来源:吴恩达 深度学习课程 《卷积神经网络》
笔记整理:王小草
时间:2018年6月8日
明确下目标定位与检测的定义。
识别一张图片的类型(比如猫狗分类)叫做图像分类image classification,比如下面这张图篇是分类到汽车:
不仅识别出图片的类型,还将目标物体的位置标出来叫做分类定位classification with localization
检测出图片中所有目标物体中的位置叫做目标检测detection
比如给出一张交通图片,检测并标记出里面的车辆,行人,自行车,交通灯等等。(注意,detection与classification with localization的不同在于单张图片中有不同分类的对象)
本节要讲述的是以上第二种情况,即给图片分类,并定位和标记出出目标物体的位置
标准的图像分类问题,假如如下输入一张图片,通过卷积神经网络卷啊卷,最后经过softmax层,分成4类:行人,汽车,摩托车,啥都没有
如果你还想定位图片中汽车的位置,该咋办呢?你可以让上面这个神经网络再多加几个输出,输出汽车的边框。
汽车的边框信息只需要4个数字来表示:b_x,b_y,b_h,b_w,分别表示边框的中心点的横坐、,纵坐标,边框的高,边框的宽。
因此在标注训练数据时,除了给出类别的标签,还要给出表示边框的4个数字。然后通过有监督的训练模型,输出一个分类标签和四个边框参数值。
(1)定义标签y
y是8*1的向量(注意这里我们只限定讲解图像中只有一个目标物体的情况)。
Pc表示概率:是否有目标物体,若有车辆,摩托车,行人目标物体,则Pc=1,若这三个都没有则Pc=0;
bx,by,bh,bw分别表示目标物体边框的中心点横纵坐标与高宽
c1,c2,c3分别表示当Pc=1时,图片属于车辆,摩托车,行人的类别的概率。
因此上面这个例子的标签y可以写成图左,而什么都没检测到可以写成图右。
(2)定义损失函数
分别将y向量中的8个元素写成y1,y2,…,y8,其中Pc=y1,以此类推。
对于单个样本的损失:
当y1=1时,就是这把个元素对应的平方差损失之和;
当y1=0时,就只是y1的平方差,后面7个元素都不用考虑
在实际中,也可以不这样定义,可以将y1的输出用逻辑回归的损失函数定义,bx,by,bh,bw的输出用平方差和来定义,而c1,c2,c3用softmax的Log损失来定义.
神经网络可以通过对特征点(x,y)的输出来识别目标特征。来举2个例子。
例子1:
假设要识别人脸左眼角的特征点,则只需要让神经网络的最后一层输出(Pc,lx,ly)3个值即可,Pc表示是否是人脸,lx,ly是人脸上眼角的坐标点。
假设想定位两只眼睛的4个眼角的位置,那就将输出改为4组坐标对应的数字(l1_x,l1_y),…,(l4_x,l4_y)
假设想定位两只眼睛的一圈,则可能需要10几个特征点,同样,将输出增加到10几坐标即可,这样就可以识别出人脸上眼睛的形状等特征从而做一些后续的判断。同理,可以输出脸部的更多特征点,比如嘴唇,从而可以根据这些特征点预测任务的表情,是伤心还是开心。
假设总共有128个特征点,则输出有129维,y={Pc, l1_x,l1_y,…l128_x,l128_y}
通过特征点检测,想想我们平时用的美颜相机(哦,对了,笔者是女生),可以在脸上头上加一些装饰,比如猫胡子啊,皇冠啊,帽子啊,发饰啊,并且无论怎么动都能加在正确的位置上,者也是用了特征检测,检测出某些特征点的位置,然后将这些额外的装饰添加在对应的特征点位置上。
例子2:
若将身体的关键点作为特征点,则可以识别任务的动作与形态:
目标检测实则分为两步。
假设要检测图片中所有汽车
第一步:图片分类
先收集图片,将有汽车的图片中的汽车挖出来作为图片的中心,然后进行标记汽车与非汽车,并利用卷积神经网络学习出汽车分类模型。
第二步:滑动窗口检测
设定一个指定大小的窗口,从图片的左上角开始,以指定的步长进行从左往右,从上往下的滑动,每滑动一次,都将窗口内的图像截取出来,输出第一步训练好的分类模型中预测是否是汽车,若是,则输出该窗口当前的左边信息,若不是,则继续滑动寻找。
若滑动完所有区域还是没有找到汽车,则将窗口增大一点点,继续从新滑动寻找。
这样做的缺点很明显:每滑动一次都要用神经网络预测一次,计算量非常大。
上一节讲了通过窗口滑动来进行目标检测,但效率低计算量大,本节来讲一讲如何在卷积上实现窗口滑动,从而提升效率与速度。
来自论文[Sermanet et al.2014,Overfeat:Integrated recognition, location and detection using convolutional network]
首先了解一下如何将全连接层转变为卷积层,接下去的滑动窗口的实现会用到它。
传统的图像分类结构如下,输入图片,经过卷积和池化,然后经过全连接层和softmax层,最终预测分类类别的概率。
将最后两层的全连接层修改为卷积层。将第二层的输出556经过400个556的卷积核,得到11400的输出,代替原来的全连接层的输出400,同理第二个全连接层也改成经过400个11400的卷积核,得到11400的输出,将最后的全连接层也改成经过4个11400的卷积核,得到114的输出。
于是后面3层的全连接都变成了卷积层的模式。
将上面全连接转变成卷积层后的如下显示(注意,其实是立体的,只是为了方便直观理解接下去的讲解,现在以平面的视角展示)
假设我们已经训练好上面这个4分类的模型了。
现在给出一张16163的图片,滑动窗口的大小为14143。
以传统的做法:滑动窗口以2个像素的步长进行从左到右,从上到下的滑动,会得到4张截图,分别依次输给分类卷积神经网络进行预测,得到分类的类别。总共做了4次卷积预测,但这样当图片很大,滑动窗口又比较小的时候,会带来巨大计算量
实际上,4次卷积操作中有很多计算都是重复的。
我们将16163的图片也同样进行如上卷积,与11400对应的,会有22400的输出结果。在最终输出的4个自放款中,左上角蓝色那一块实则对应了左上角14143的蓝色区域。
因此,实际上,无需通过滑动窗口依次取出截图去执行前向传播进行分类预测,只需要直接将原图像进行卷积,其中的共有区域可以共享很多计算。
也就是说,给出一张图片,比如汽车:
无需滑动n次,并进行n次分类预测,而是直接把整张图片进行卷积后,一次性得到每个区域的分类结果。
上一节的方法大大降低了目标检测的计算量,但仍有缺陷:检测的边框不够精确。本节来解决边框预测不精确的问题。
要解决这个问题,常用的解决办法是yolo算法,优点是只要看一次。
来自论文[Redmon et al.,2015, You Only Look Once:Unified real-time object detection]
给出一张100100的图片,为了方便讲解,此处粗粒度地分为33的格子。
一般情况下,对每个格子对应的图像进行分类预测,分类的方式与第1节讲述的一样,因此在训练数据中药现将每个格子都进行标记:
因此,对于最左上角的格子,什么东东都没有,得标记成:
而有大部分车体的两个格子(yolo算法将物体的中心点所在的格子算作是有该物体的格子)的标记为:
因为有33个格子,且每个格子的预测label向量有8个元素,总共输出的吃春是33*8.
yolo的整个过程是,输入图片1001003,若以33的根子为划分,经过卷积神经网络,输出338
若一个格子中存在多个对象,我们稍后讨论。但在实践中一般会用更小的格子网络,比如1919,那么多个对象分配到同一个格子上的概率就会小很多
yolo的优点:
(1)输出更精确的坐标,不收滑动窗法分类器的步长限制
(2)使用卷积实现的过程,可以一次性得到结果
在yolo算法中,每个格子的左上角是(0,0),右下角是(1,1),以下图右车为例:
车的中线点坐标为(0.4,0.3),即bx=0.4,by=0.3
宽和高是相对于格子的百分比,车子的宽大概占了格子宽的90%,因此bw = 0.9,车子的高占了格子的50%,则bh = 0.5
其中bx,by肯定是0-1之间的坐标,因此其值在0-1之间;
而bw,bh可能超过1,因为可能车子的长度超过了格子长度,有一部分跑到了另一个格子去。
如何判断对象检测算法运作良好呢?我们可以使用并交比函数来评价对象检测算法。
假设下图,红框是正确的检测边框,紫框是模型预测出来的检测边框
要评价模型预测的效果,就用两者相交的面积/两者相并的面积,这个占比就是交并化函数输出的指标,在0-1之间,一般指定一个阀值0.5,若占比>=0.5则模型的预测是可以接受的。当然严格一点的话,你也可以提高阀值。
Non-max suppression可以有效保证在图像中只对物体检测一次,避免重复检测加大计算量。
假设用Yolo算法,把图像分成19*19的网格,这两辆车只会属于其中心点所在的网格,但是实际上车子覆盖的其他网格,也都会去想我这里是不是一辆车,造成了重复计算。
直观得来了解下Non-max suppression是如何起作用的。
首先会有多个框框检测出自己里面都有汽车,每个框框都会得到一个并交比系数;
对于同一个目标物体的多个框框,比较它们的并交比,选出最大的那个框框颜色加深,将其他的比值小的框框都减弱颜色使其变暗,最终目标物体会得到1个较好的边框。
深入得来理解下Non-max suppression的算法过程
仍然将图像分割成19*19的网格:
假设只识别汽车这一个类别,每个网格的输出就是:
1.首先抛弃掉pc<=0.6的box
2.对剩下的boxs(边界框):
若同一张图片中检测n个目标物,则要对每个物体都进行以上步骤。
以上所有,有个缺点,就是每个网格只能检测出一个对象。如果想让一个格子能检测出多个对象,那么久可以用Anchor Boxes。
假设这样一张图片:
人和车重叠,其两个物体的中心点都在同一个网格内,此时若还是用这样的输出:
就不行了,因为一次只能输出一个类别。
Anchor Boxes的做法是预先定义两个不通过形状的anchor box(实践中可能会用更多个)
然后将预测结果将这两个anchor box关联起来。
重新定义标签y:
前面8个元素是针对行人的预测,后面8个元素是针对汽车的预测。
训练的时候,不仅仅关注与标注的边框一样,还要关注预测的边框与anchor box的并交比。
因此又有人又有车的网格的标签应该是y:
若检测到的边框与Anchor Boxes1的并交比很大,则将预测值写在y的上面8个元素,若与Anchor Boxes2的并交比较大,则将预测值输出再y的下面8各元素,以此来区分检测出来的边框到底是人呢还是汽车。
Anchor Boxes算法有两个缺点:
(1)当两个目标物图的边框很相似或一样的时候,就失效了,比如检测电视机和电脑,都是差不多方方的形状。
(2)当数据集中出现了3个目标物体,则失效了,需要重新定义模型,定义新的输出y的形式才行了。
至此,我们已经讲述了对象检测算法的大部分零件,这一节,将将所欲零件组装构成完整的yolo对象检测算法。
假设要检测一张图片中的3个类别:pedestrain, car, motocycle,分成33的网格(实践中一般为1919)。
训练集的标签y为3328:(28分别是2个Anchor Boxes对应的类别)
训练集的特征x是遍历网格中的9个小格子,分别给他们都标记一个y.
其实这个图片中只有1个格子里有车,其余8个格子里都没有车,因此没有车的标记为
有车的标记为
其中bx,by,bh,bw就是这辆车在该格子中的边框
因此向卷积神经网络中输如图像为1001003,若分割成33的网格,则输出的大小为33*16
###9.3 使用Non-max suppression
为了让例子更有趣,我们用一张新的美女图。
若使用2个anchor box,则针对每个网格都会输出2个预测边框,其中一个概率pc很低(注意,有些边框可能会超出所在格子的宽度和高度)
然后,如果你有3个类别(行人,车,摩托车),则你要分别对这3个类别单独进行Non-max suppression,运行3次来得到最终的预测结果
如果你读了对象检测的论文,你会发现有一个概念叫Region proposals候选区域,在计算机视觉里很有影响力。
回归上文的算法(非yolo),会对一张图片中的滑动窗口,都过一遍卷积神经网络,但问题是一张图片中其实只有少量窗口有目标物体,其他吃昂口是完全没有任何用的,因此对于完全没有目标物体的窗口去计算也显得耗时耗力。因此,论文[Girshik et,al,2013,Rich feature hierarchies for accurate object detection and semantic segmentation]提出了一种叫做R-CNN的算法,即带区域的卷积神经网,只是选择某些有意义的窗口运行卷积神经网络进行预测。
运行图像分割算法,得到如下结果:
然后将每个色块作为一个整体跑一下分类器去进行检测(加入有2000个色块),因此上图在蓝色区域进行检测,可能能检测出一个人,淡蓝色区域可能能检测出一辆车
通过图像分割,从而针对性得对一些整体去检测,比在图像的所有位置都跑一边要大大减小计算量。
R-CNN的速度还是不能使研究者们满意,于是有了一系列研究工作对该算法进行改进。
基本的R-CNN:
利用图像分割求出候选区域,对每个候选区域进行分类,输出类别标签和边框。
Fast R-CNN:
[Cirshik,2015.Fast R-CNN]
与R-CNN的区别是,Fast R-CNN使用了滑动窗口的卷积实现来进行分类(本文第4节),而不是对每个窗口都进行分类。
Faster R-CNN:
[Ren et.al, 2016. Faster R-CNN: Toweards real-time object detection with region prposal network]
但Fast R-CNN还是有缺点,即图像分割的时候,色块的聚类特别慢。于是另一个研究组提出了Faster R-CNN,利用卷急神经网络来获取候选区域色块。
但实际上,大部分更快的R-CNN,都还是比yolo算法慢。