图像分割、定位、检测(CV任务)
引言
目前我们谈论最多的是分类问题,今天基于计算机视觉的主题讨论一些其他的话题,讨论图像中的像素,我们会看到分割、定位、检测,以及其他的计算机视觉任务,以及通过卷积神经网络应该如何完成这些任务。
之前我们谈论的是图像分类,所以这里选择以图像作为输入,图像会通过深度神经网络,这个网络会提供一些特征向量,按照AlexNet三通道模型衡量的话,应该有4096维度。从最后一个特征组成的向量中,我们会得到全连接的最终链接层,会给我们1000个类的预测概率,这里的1000类指的是ImageNet的类别数。在结束阶段,神经网络会实现输入图片后,我们输出分类类标,表述这整幅图像的内容。这是一个比较基本的计算机视觉例子,另外还有更有趣的例子对应更多的任务,我们会想用深度学习来解决。
这节课聊聊图像目标检测和图像分割,以及其他一些很有趣的有关于计算机视觉的核心课题。
下面我们看看深度学习如何解决它们。下面详细谈论这些模型,以及它们能解决什么问题。开始讲语义分割,然后是分类和定位,最后会讨论目标检测,并简单说一些实例分割。
语义分割
我们希望输入图像,并对图像中每个像素做分类,对于每个像素,用这个图像做例子,是一只可爱的猫在草地上散步,输出结果应该是,对于每个像素,确定它属于猫、草地或者天空,或者背景,亦或是其他分类。我们首先确定分类,就像我们做图像分类一样,不过现在我们不能简单地分一类给整个图像,我们希望能为每个像素产生一个分类类标,这个就叫做语义分割。
在这里有一件有趣的事是,语义分割并不区分同类目标,所以在下面这个例子中的右方图像有两头牛并排战立,我们在解决这个问题时,是为每个像素分类。在之前的例子中输出并不能区分结果,也就是说不会区分这两头牛,相反我们拿到的是大量像素全部标记为牛。这是语义分割的一些不足,之后我们开始学习实例分割时,我们会看到如何处理其中的缺陷。
基本上可以认为用类别来做切分,这带来的问题是,语义分割可能仅通过分类实现,这就是问题所在。你可以用滑动窗口来实现语义分割。可以想象,我们用输入图像将其打碎为许多小的、局部的图像块,在这个例子中可能三个小块包含牛的头部,你可以用这些小块做分类。就这块来说,它的中心像素属于哪类呢?我们可以用相同的机制区分整个数据集,但现在只用这些小块去分类,而不是整张图像,不过这只在一定程度上有用,并不是完美的解决方案,而且这个方案计算复杂度很高,因为我们想标记图像中的每个像素点。我们需要为每个像素准备单独的小块,这种方法计算复杂度很高,尤其是对正向传播和反向传播来说。
另外,如果你仔细考虑,我们可以共享各小块间的计算,所以当你打算区分两块彼此相邻,甚至重叠的图像时,这些小块的卷积特征最终通过同样的卷积层。实际上当用此去进行区分,我们可以共享很多计算过程,或使用这类方法来做区分。所以开始说的那种方法其实并不好,你也不应该那么做,不过如果你开始考虑图像语义分割至少你可以明白一件事。
下一个表现更好的模型是全连接卷积网络,不光是从图像中提取各个图像块并且分类,我们可以把网络当成很多卷积层堆叠在一起,这里只有卷积层,比如3*3的卷积网络,用补零的方式,这样便可以保持输入图像的原有尺寸,现在如果我们让图像通过巨大的卷积神经网络来运算结果,比如一个张量,尺寸是C*H*W,其中C是类的数量,这个张量会为每个像素进行预测,给出评分,对每个像素这么做,我们可以用堆叠的卷积层一次性完成所有计算,这样的话,训练这个网络就是对每个像素分配损失,并且平均化损失,用反向传播来进行训练。
上面这个模型相对简单,可以这样理解,假设你把所有超参数调对了,这里边会遇到问题,在这个情景中我们应用了批次性的卷积,同时保持原始输入图像同样的尺寸,这样做代价超级昂贵。如果你想做卷积,比如有64或128甚至256个卷积通道,这种配置比较常见,这样的话,运行卷积层在这样高的清晰度逐层训练,可想而知计算量很大,会很耗内存,所以在实际运用中,你不要这样配置模型。
你反而会见到下面这样的神经网络,我们在图像内做下采样,之后对特征做上采样,所以与其做全部卷积,基于整个图像的全维度,我们仅仅对一部分卷积层做原清晰度处理,之后下采样特征,用的方法包括最大池化或跨卷积,结合一些下采样技术。总而言之,就是卷积结合下采样,下采样式卷积,很像一些基于分类的网络。不同点是,不采用全连接层,像是你处理图像那样,我们希望增加清晰度,在后半部分网络中,所以我们的输出可以维持现有尺寸,这种方法更加方便计算,因为你可以让网络很深,每层的清晰度降低,但是有很多层叠加。
我们之前已经见过下采样用于神经网络,你也可以做跨卷积,或者各种池化来减少输入图像的尺寸,但是我们没有讨论过上采样。你会问这是什么,它们在网络中是怎么存在的,我们用什么方法来增加网络特征图的尺寸。
怎么做上采样?
其中一个方法就是去池化,之前定义池化是下采样,我们讨论过平均池化或最大池化,平均池化很像取平均。针对每个池化(合并)区域,上采样做的是最近距离去池化(展开),看下面左边的例子,输入是2*2矩阵,输出是4*4矩阵。输出是输入的去池化或者上采样,在去池化区域中我们重复每个元素。另外你看到的关于钉床函数(bed of nails)去池化,或者钉床函数上采样,是我们现在有2*2方格对应于去池化区域,在这种情况下,你把所有值设为0,除了在去池化区域的元素为1,我们取输入,并将它们放到左上元素里,其他设为0,这种去池化方法叫钉床函数。因为区域中的0是扁平的,就像扑克牌平铺一样。
对于非0区域,可以想到,回忆一分钟之前提的最大去池化的想法,许多这样的神经网络是对称的,尤其是下采样的神经网络之后进行上采样,这两个过程对称。所以最大去池化对于去池化区域来说,对于每个上采样层,它们和池化层相关。在神经网络前半部分,我们在下采样时用最大池化,我们会记住区域中的哪个元素,在最大池化过程中被使用,之后我们继续网络的后半部分,我们会执行类似钉床函数的操作,并不是总把元素放在相同位置,我们会把它们放在对应的池化过程的位置。最后填0就可以,全部填0,只保留低清晰度时的元素,在最大池化发生的区域将各个小块合并成高清晰度图像。
Q:上面这个方案有什么优点?
我们为什么要做分割?我们希望基于像素预测结果尽可能好,我们想要找到边界,让这些细节体现在预测中,如果我们做最大池化,这种不均匀性会凸显出来,在特征图中由于最大池化,在低清晰度中你看不到,你会丢失一些空间信息,在最大池化后你不知道这些信息属于哪里, 所以将向量去池化,同时你可以认为它帮助我们很好处理细节,帮助我们存储在最大池化时丢失的那些空间信息。
Q:这会使反向传播容易么?
讲师不认为它改变太多,因为存储这些索引不太耗费空间,和别的比较他们占用空间不大。
另外要关注的是卷积转置的概念,举一个卷积转置的例子,对我们谈到的各种去池化方法,比如钉床函数、近邻法、最大去池化法,所有的这些都是使用固定方程,并不是真的在学习如何上采样。可以想象,比如跨卷积就是一种可学习的层,可学习如何下采样,针对某一层来做。类比一下这种层叫卷积转置,我们可以用它来做上采样,既上采样特征图,又能学习权重来做上采样,这就是另一种卷积方式。
为了了解这是怎么工作的,可以想一下正常的3*3卷积是如何工作的,这是一种我们之前见过多次的卷积,输入是4*4,输出也是4*4,现在我们用3*3的卷积核做内积,我们把小方块中心和图像最开始元素重叠做内积,结果就是卷积的结果,作为左上的输出。
我们为每个像素重复这一过程,得到最后结果。
跨卷积的结果看起来比较相似,但是我们的输入是4*4,输出为2*2区域,概念是一致的,都有3*3的过滤器或卷积核,放置在输入对应的每个元素做内积,计算卷积的输出。
跨卷积的定义是,我们不依次向下放置过滤单元,对每个位置都这样做,我们做的是,每隔两个像素单位做一次,在输入中,过滤器(卷积核)每次移动一格,输出也这样,每次移动一格,所以每次相差两个单位,给了我们一个比值,是输入中移动距离和输出中移动距离的比。当你做跨卷积,步进是2时,就做到了下采样图像或特征池,以步进为2去实现。
转置卷积则相反,我们的输入是2*2,输出便是4*4,转置卷积做的有些不同,不做内乘,而是取特征池的输入值,在左上方是一个标量,我们会用这个值乘以过滤器(卷积核),以3*3的区域的方式复制这些值作为输出,所以这里不做输入和卷积核的内乘,我们用输入做权重处理过滤器(卷积核),这样输出是带有权重的过滤器的叠加,用输入做权重。
同样地,可以定义一个比值,为了实现过采样,我们移动输入的一个单元,然后以相同的技巧移动输出卷积核的两个单元,输入中的蓝色像素是一个标量,我们用标量乘以过滤器(卷积核),复制这些加权的过滤器(卷积核)的值,叠加于新的输出。微妙的部分是,有时输入中的感受野可以与输出中的感受野重叠,这种情况我们直接在输出中对结果取和即可,然后重复这个过程。不断重复,最后你会得到一个可学习的过采样网络。我们用习得的权重去过采样图像,增加空间尺寸。顺便提一下,这个操作在不同地方叫法不同,有时称为去卷积,从信号处理的角度看,去卷积意味着对卷积求逆,实际不是这样。
你会常常见到这种训练层称为去卷积层的,尤其在深度学习论文中,注意这个说法。有时你会发现这个叫重卷积、小步长卷积。如果我们把跨出的步长看做比值,输入比输出,这就像跨一半的卷积一样,因为这种比值是1:2。有时也称作反向跨卷积,原因是用数学验算会发现结果一样,前向转置卷积最后成为相同的数学操作,就是反向卷积。
再举一个例子,从一维的角度看,如果我们做3*1的一维转置卷积,我们的卷积在这里就是三个数字,输入是两个数字,你可以看到输出是对输入做加权,依次去下移输出中的加权过滤器(卷积核),跨度为2,最后对输出中的感受野重叠部分进行叠加。
Q:转置卷积这个名字是怎么来的?为什么叫这个?
对这个运算来说,这个名称来自于卷积的直接解释,如果你做卷积,你可以把卷积写成矩阵相乘形式,这更便于理解。用一维的例子,我们有一些权重做一维的卷积,用x表示卷积向量,有三个元素,输入向量有四个元素ABCD,我们做3*1的卷积,尺度是1,这个过程就是矩阵相乘的过程,我们用输入卷积核x,转变成矩阵形式X,X包含很多卷积核x,不同的卷积核由不同区域决定,我们用这个大的权重矩阵X做矩阵向量乘法,输入a,结果等价于做卷积。
转置卷积的意思是,我们用相同的权重函数乘以转置矩阵,也就是相同权重的矩阵,这相当于同一个例子,左侧步长为1的矩阵和其转置,在右侧如果你仔细推导,结果就是步长为1的转置矩阵变为步长为1的正常矩阵做卷积,这里涉及了很多补零以及补宽的技巧,但是基础的操作是一致的。
这个例子有些不同,当你处理步长为2的情况,左边我们做步长为2的卷积,表示为矩阵相乘的形式,对应的转置矩阵却不再是卷积。如果你仔细看权重矩阵,卷积最后会成为这种形式,这样的话,步长为2的转置矩阵和原来的正常卷积有所不同,推导的过程就是原因,这也就是转置卷积名称的由来。
所以,图像分割这个术语也变得更加自然,现在有个这个巨大的卷积网络,使用了降采样和过采样,降采样通过带步长卷积或池化实现,过采样通过转置卷积或各种去池化、过采样实现,我们用反向传播端对端训练这个网络,用交叉熵损失衡量表现,基于像素,这个还是不错的。
我们已经学了很多相近的有关于图像分类的想法,现在只是用他们可以很简单地引申至一些新的问题中,所以这个工具还是不错的。
Q:如何得到数据集?
这样处理数据集,我们需要给每个像素标记,这样的工具可以在网上找到,可以用它在图像上画轮廓线,并填充区域。不过获取这样的数据集挺贵的。\
Q:损失函数是什么?
在这里,我们解决分类问题,所以我们用交叉熵损失函数,对每个像素进行分析,我们会有一个真值表,匹配输出的像素,然后计算输出的每个像素与真值像素之间的交叉熵损失,之后再计算总和或平均,之后对每一个小批次做总和或平均计算。
Q:是否需要假设我们知道类别?
我们确实是这样做的,就像是在图像分类中一样,在图像分类中开始时,基于数据集可能有10或者20,或者100,甚至1000类,就这个数据集而言,我们要先锁定类,才能锁定数据集。
图像分类和定位
之前已经讨论过图像分类,我们做的是给分类分类标。对于输入图像,有时想知道更多关于图像的事,在猫这个例子中,除了预测分类,还想知道猫在哪里。所以不只想预测猫,还想画一个边界,这个边界可以把猫包裹进来。
分类和定位,与目标检测不同,定位的情况是你提前知道会有一个物体是你要找的,或者不止一个,但是你预先知道我们要对这个图像做分类决策。我们只产生一个边界,这个边界告诉我们物体在图像的哪里,有时我们称这个为基于分类和定位的任务。
再一次强调,我们可以复用相同的机理。这些我们已经在图像分类中学过,为了处理这个问题,处理这种问题的框架一般是下图显示的这样。所以我们有输入图像,用巨大的卷积神经网络做输入,下面这个是AlexNet网络,用它举个例子,这会给我们一些向量总结图像的内容。这就像之前我们做的全连接层,从最终向量到我们的类的得分,但现在我们有另一个全连接层,从那个向量到四个数字。这四个数字可能是高度、宽度、xy坐标,这是边界的参数,现在我们的网络会产生两个不同的输出,一个是类的分数,另一个是这四个参数给定输入图像的边界框坐标。现在在训练阶段,当我们训练这个网络时我们实际有两组损失。我们会假设用一个全监督的设定,假设输入图像和分类类标,以及图像分类的真值对应,所以我们现在有两个损失函数,我们有softmax损失,用实际值计算与预测的类的得分。还有一种损失来衡量我们的预测坐标和实际值的不同,针对于边界的坐标,对照于我们的实际坐标,所以可以采用的一种做法就是用L2损失,这个是最简单的。实际中会用L1或者平滑化L1损失,或者他们参数化边界,思路有些不同,但大体一致。你有一些回归损失衡量预测坐标和实际坐标。
Q:同时做分类和定位,是一个好主意么?
举个例子,如果你误分类,是否应该查看边界坐标去验证。有些情况下人们很喜欢这样,一般来说这种方法表现不错,不是个大问题,可以训练一个神经网络同时做这些事情,不过有些时候会微妙些。从误分类角度来看,举个例子,现在不仅要预测单个边界,你可能要分别预测每一类的边界,仅仅对某类边界针对实际值评估损失,人们有时对这个会感兴趣,实际来看有一些帮助,但是这种基本的假设不是完美的,并不能最优化,但是有效,能做一些东西。
Q:这些损失有不同的单位吗?会控制梯度吗?
这就是我们说的多重任务损失,不论何时求导,我们基于我们的参数对网络参数求梯度,用这个求导结果做梯度,但是现在我们有两个标量,我们想同时最小化。你实际生活中想做的是,在这两种损失上加上一些给出权重的超参数,所以你可以对两个损失函数做加权求和来确定最终损失,这样你可以针对加和求两损失加权总和的梯度,这不好处理,因为这个加权超参数需要你来设定,但是它和我们见过的其他超参数有所不同,因为这种加权化参数会改变损失函数的值,一般在设定超参数时,你会取不同的参数值,对之后输出的损失值进行比较,看看它们发生了怎样的变化,但这里的超参数会影响损失值,做这种比较就要一些技巧了,所以合理选择参数也是一种挑战。
实际应用中,为了解决问题,你需要根据不同情境进行这样的超参数取值,我一般会采取的策略是,用你关心的性能指标组成的矩阵来取代原本的损失值,这样一来,实际上是在用最终性能矩阵做交叉验证,而不是仅盯着损失值来选择参数。
Q:为什么我们要一口气做完这些,而不是分开做?
为什么不先固定网络中的所有参数,再分别用两个任务中的全连接层数据进行学习?
确实会有人这样做,并且这会是你首先尝试的方法,但其实一般在迁移学习中,对整个系统进行联合调试会得到更好的结果,因为有可能会出现特征的误匹配。若你将在ImageNet上训练过的神经网络用于自己的数据集,对整个网络进行更新会得到更优的表现。实际中有一些小技巧,可以冻结你的网络,之后分开训练这两个网络直到收敛,之后你回到你的网络,最后回来联合调试整个系统,这是实际应用中经常用到的技巧。
延申——姿态估计
之前我提到的大型网络,通常是在如ImageNet等数据平台上预训练过的网络。
延伸一点,这种预测图像中固定几个点的位置的想法,还可应用到除分类与定位以外的其他问题上,其中一个很酷的例子就是姿态估计。这里我们拿一张人像作为输入图片,想输出的是这个人的关节在图中的点位,这样一来,网络就能预测出这个人的姿态,比如胳膊、腿的位置等。一般来说,人的关节数量是相同的,这个简化了假设,虽然不是恒成立的,但是对于深度学习足够了。其中一个参数化的例子就是,用14个关节点的位置来定义人的姿态,他们的脚、膝盖、臀部诸如此类,当我们训练神经网络时输入这张人像后,将输出14个参数,逐一给出这14个关节点的xy坐标,然后用回归损失来评估这14个点的预测表现,运用反向传播方法再次训练这个网络。通常见到的都是L2损失,但回归损失也会被用在这里。
Q:上面说的回归损失指的是什么?
这里指的并不是交叉熵损失或softmax损失,这里说的回归损失一般指L2欧几里得损失,或L1损失,有时称作平滑L1损失。一般而言,分类与回归的区别在于,你的输出是间断的还是连续的,如果希望输出一个间断的实例,正如在对固定几个类别进行分类决策那样,这样你会考虑交叉熵损失、softmax损失或向量机的边界损失,我们之前已经讨论过这些。但如果你期望输出的是连续值,正如本例中这些点的位置,因为输出是连续的,这时你会倾向用其他类型的损失,典型的如L2、L1等。
但重点是,一旦需要网络输出的是固定数量的实例。举个例子,你会用一些猫和狗的图片来预测这两类对象的边界,这时每张输入对象所含的对象是固定数量的,因此,回归分类与定位策略也可以被用来解决这类问题处理问题,这种固定化回归预测的概念可以应用于包括姿态估计在内的多类问题中。
下一节将要讨论的是对象识别(目标检测)。
目标检测
目标检测,这是一个内涵相当丰富的话题,可以说在计算机视觉领域占据核心地位,可能一整个学期的课也只够用来教授对象识别的历史,以及各种方法论,我会简要介绍并尽量提炼过去几年内最重要的目标检测方法,以及深度学习在该领域的应用。
物体识别主要研究的是,一开始有固定几个类别,比如猫、狗、鱼或其他我们感兴趣的种类,我们的任务是根据输入的图像,每当在图像中出现其中一类对象时,围绕对象划定一个框,并预测该对象从属的类别。这和分类与定位不同,因为对应每一张输入图像,对象的数量是不定的,无法预估每张输入图像含有多少个对象,问题因此非常具有挑战性。
我们已经多次见过这张图,展现的是ImageNet分类表现关于年份的函数,性能水平是逐年提升的,对象识别也有类似的趋势。因为对象识别作为计算机视觉中的核心领域,已经被研究了相当长的时间,下面这张图展示了基于PASCAL VOC数据库的对象识别的发展进程。这个数据库在对象识别领域的应用由来已久,可以看到,至2012年性能的提升出现了停滞,到2013年当深度学习开始应用于图像识别时性能水平迅速提高,一年比一年好,这个图到2015年就结束了,之后还在进步。如今基于这个数据的识别技术已达到超过80%的准确率,事实上最近的文献已经不会展示基于该数据集的成果了,所以现在不能确定现在它的准确率达到多少,但已经超出这张图的上限了。
基于PASCAL VOC数据库的对象识别的发展进程(来自cs231n)
这不同于定位,因为每张图包含的对象数量不固定,举个例子,下图中左上方的这只猫只有一个对象,因此只需要预测4个参数,但中间这张图中有三只动物,网络就需要输出12个参数,4个坐标来框定边界。或是下面这张图有很多鸭子,那么神经网络就要输出大量参数。
目标检测对于不同的图片有不同的输出,等同于回归问题考虑会非常棘手(来自cs231n)
这与定位很不一样,因为在对象识别中,每张图像中的对象数量是不定的,并且你无法预先得知具体的个数,因此把对象识别等同于回归问题考虑会非常棘手,因此人们尝试用另一种方案来解决对象识别问题,其中一个已经被广泛应用在计算机视觉领域的想法就是滑动窗口。类似于图像分割方法中将图像切分为小块一样,我们也可以将其应用到对象识别中去。我们将输入图像切分为小块,比如这张图左下角这块,我们将它输入到卷积神经网络中进行分类决策,结果是没有狗和猫。现在除了我们关心的类别外,还新增了一个背景分类,这样如果网络没有见过既定范畴之外的其他对象,它就会将其识别为背景。这样一来,当输入左下角这个图块后,网络会将它识别为背景输出没有对象。
如果换另外一块如下,网络做出的预测将会是:狗对、猫错、背景错。
选另一块,结果是狗,不是猫,不是背景。
再换一块,不是狗,是猫,不是背景。
上面的方法有什么问题?问题在于,你该如何选择图块。
这是个大问题,因为图像里的对象数量不固定,并且它们可能在任何位置,拥有任意尺寸,以任意比例出现。如果你想用蛮力用滑动窗口法可能需要测试成千上万次,才能处理这个问题。另外每一块都要输入到一个巨大的卷积神经网络进行训练,计算复杂度过高,所以实际中,人们并不会用这样费力的方法来解决基于卷积神经网络的对象识别问题。相反的,人们会采用一种叫做候选区域的方法。
这种方法在深度学习中并不常见,而更像传统的计算机视觉方法,候选区域网络更多的采用了类似于信号处理、图像处理等方法来建立候选清单,所以对给定的输入图像,候选区域网络会在对象周围给出上千个框,这时我们就可以进行定位,也就是寻找图像的边界,划定闭合的限定框,正如很多图像处理方法所做的那样,但是区域选择网络会在输入图像中寻找点状的候选区域,也就是对象可能出现的区域,这样算法跑起来很快,一个常见的候选区域方法就是,目标检测会给你2000个备选区域,不是这页上写的1000个,你运行这个算法,CPU处理2秒时间,输入图像会被切分成2000个候选区域,其中会有很多噪点。他们中的大部分不是你要的,召回率比较高,如果图像包含你要找的物体,那么它大概率在会在目标检测所设定的这些候选区域之中。不同于我们用分类网络在图像的各个位置和范围内进行搜索,首先采取候选区域网络找到物体可能存在的备选区域,再应用卷积神经网络对这些备选区域进行分类,这样做比穷尽所有可能的位置和范围要来的更容易一些。这些观点在这篇论文中有解释,叫做R-CNN,是几年前发的,做的就是这些事情。
给定我们的输入,我们运行一些区域选择网络去找到备选区域,有时也叫兴趣区域或ROI。选择查找可以给你大概2000个兴趣区域,其中一个问题是这些输入中的区域可能有不同尺寸,但是都要在卷积神经网络中运行做分类,这样的话,我们希望所有输入尺寸一致,因为全连接层的特性,所以我们需要处理这些区域调整为固定尺寸,使之与下游网络输入相匹配,所以我们需要对输入做切分。根据备选区域的要求切分至固定尺寸,之后经过卷积神经网络运行这些算法,然后使用支持向量机算法基于样本做分类,预测对应的组别。
另外提一下,基于区域选择的卷积神经网络可以做回归,可以用来校正包围盒。除了输入的问题,另外的问题是,你的输入图像中物体的位置,你可能会感觉不错,实际不是完美的,所以算法会考虑这个,不只对这些区域分类,也预测边界的补偿和修正值。在确定备选区域时,再一次强调这个是多任务损失,你需要对这些进行训练。
Q:有必要让备选区域为长方形吗?
是的,因为很难对不规则的物体进行划分,但是如果你谈及即时切割,你不一定用长方形,如果你想预测一些不是长方形的区域。
Q:区域选择会不会学习?
这种算法是很传统的,不是自学习的,这是种固定算法,有人写下来的。不过一会我们会尝试做改动、
Q:校正是否在兴趣区域内?
不是,不一定,举个例子,假设兴趣区域是围绕人的,但是没包括人的头部。你可以想象网络会推断这是人,但是人有头。所以网络应该把边界提高一点,所以最终预测会比之前的区域要大。
Q:如果有很多兴趣区域,不属于你要找的物体。
我们之前说过,除了你感兴趣的类,你可以添加其他背景类,所以你的类可以预测背景。说那里没有物体。
Q:我们需要什么数据?
这是一个监督学习问题,考虑到我们的训练集由图像组成,每个图像由包含,并标记出所有目标的类别,绝对有尝试实现这个的论文。如果你没有数据,只有一些图片的数据,或者如果图片清晰度不够,通常情况下,在训练阶段可以假设图像中所有目标都是监督学习。
上面所提到的R-CNN框架有很多问题,如果你仔细看右边的图,你可以看见包围盒多出来的头部。我将把它放回去,这种算法的实现仍旧要许多计算力。如果我们用2000个备选区域,我们就要独立训练这些区域,需要耗费大量资源。这里有个问题,用固定的选择模型,我们并不学习参数,这是个问题,实际上这会使算法变慢。所以原来的R-CNN会将所有特征存入硬盘,这会耗费数百G的硬盘空间来存储这些特征,这使得训练变得很慢,考虑到你要大规模正向反向训练参数。有一次他们曾经花了84个小时来完成训练,这很慢。在测试阶段这个算法也很慢,大概30秒完成一幅图,因为你要运行数千个正向传播来训练卷积网络。对于一个备选区域,结果就是很慢。
幸好我们有改进版本Fast R-CNN,做了很多优化。
看起来和R-CNN差不多,我们从输入开始讨论。现在不再按兴趣区域处理,而是通过一些卷积层整个图像去运行,得到整个图像的高分辨率特征映射,我们仍旧要用一些备选区域,但不是固定算法,比如选择搜索,而是针对备选区域切分图像的像素,我们现在考虑基于备选区域投影到卷积特征映射,之后从卷积特征映射提取属于备选区域的卷积块,而不是直接截取备选区域。通过对整个图像进行处理,当我们有很多小块我们可以重用很多卷积计算。
再一次强调,如果我们在下游有很多全连接层,这些全连接层的输入应该是固定尺寸的,所以我们需要对从卷积映射提取的图像块进行整形,用可微的方法,用兴趣区域池化层。当你通过卷积特征映射得到这些小块,你可以通过全连接层运行这些输入,预测分类结果,以及对包围盒的线性回归补偿。
当我们训练这个的时候,在反向传播阶段,我们有一个多任务损失。要在这两个约束之间做取舍,我们可以基于全局反向传播,同时学习。
这种兴趣区域池,有点像最大池化,现在不过多讨论细节。
Faster R-CNN RoI Pooling(来自cs231n)
从速度上说,Fast R-CNN的表现比原先模型强,SPP网络介于两者之间。在训练阶段,改进模型大概快10倍,因为我们在不同特征映射之间共享了训练结果。在测试阶段,改进模型非常快,它的时间耗在计算备选区域上。所以我们说,计算这2000个区域用选择搜索大概要两秒,当备选区域准备好之后,因为处理过程是共享的,共享复杂的卷积计算,基于全图,我们可以1秒内完成这些计算。改进模型的瓶颈在找备选区域上,幸好我们解决了这个问题。
R-CNN .vs. SPP .vs. Fast R-CNN(来自cs231n)
解决方法是,问题是用固定函数计算备选区域成为瓶颈,我们让网络自身去做这个预测。用同样的方法,我们在卷积层中运行整个输入图像去获取特征映射,来表示整个高清晰度图像。
这里再看一个分离备选区域网络,工作于卷积特征的上层,在网络内部预测自己的备选区域。当我们有了这些备选区域之后,这就像一个Fast R-CNN,我们从这些备选区域以及特征映射中取出块,作为输入传至下一层,现在我们讨论多任务损失,以及多任务训练网络,去一次性做完这些。我们告诉神经网络同时做完四件事,如何平衡这些事情有些麻烦。因为区域选择网络需要做两件事,对于每个备选区域,它们是否是待识别物体,同时要对包围盒进行校正。最后网络还需要再做这两件事来做最终分类决定,也可以进行第二轮包围盒回归,也可以进行第二轮参数校正,改正之前来源于区域选择阶段的错误。
Q:有时多任务学习可以视为正则,这怎么理解?
我不确定是不是有更好的对照试验来说明这个,在原来的版本的Faster R-CNN论文他们做了一些试验,比如如果我们共享区域选择网络会怎么样?反之如何?如果我们通过分离卷积网络来学习区域选择网络,效果会不会比分类网络好?这之间有些小小的不同,但是并不显著。实际上,只学一种更好,计算复杂度会低一些。
Q:如何训练区域选择网络?
因为你不知道样本的真值,这个有些复杂,这里不讲太多。解决方法是,设置区域选择网络和真值重叠的阈值,当大于这个阈值时判断为正,如果与真值重叠,你可以拿这个做区域选择。小于这个阈值则被预测为负。但是这里涉及很多玄妙的超参数,还是蛮复杂的。
Q:什么是区域选择模型的分类损失?
二分类损失,这里不说太多的架构细节,这个比较复杂,就是做简单的二分类。对于你的潜在的区域,它进行二分类,这是一个目标吗?所以它像是一个二分类损失。
当你完成模型训练时,Faster R-CNN的结果会令人吃惊的快,因为我们避免了由计算网络外区域引起的空间浪费。和其他模型比较,Faster R-CNN模型收敛很快。有趣的是,因为通过了区域选择,你会想固有的比较区域选择算法和我的数据之间是否不匹配,在这个情况下,一旦你学习了你自己的区域选择模型,你可以克服这种不匹配。如果你的备选区域有些奇怪,和其他数据集不太一样。基于候选框的目标检测模型。
R-CNN .vs. SPP .vs. Faster R-CNN(来自cs231n)
还有一类模型用于目标检测的,是一种前馈模型。其中一个模型是YOLO(You Only Look Once的简称),还有一个模型是SSD(Single Shot Detection的简称)。
这两个模型差不多是在同一时间段被提出的,但这类模型的思想不是对这些候选框分别进行处理,而是尝试将其作为回归问题处理,借助于大型卷积网络所有预测一次完成。
给出输入图像,你可以将输入图像分成网格,这个案例中是7*7个网格,在每个单元里你可以想象一系列的基本边界框,这里我画了三个基本边界框,高的、宽的、正方形的,在实际应用中你可能不止用3个,你想对每个网格和每个基本边界框预测几种目标物体。
第一,你要预测边界框偏移,从而预测出边界框与目标物体的位置的偏差。你还要预测目标对应类别的分数,所以每个边界框都会对应一个类别分数,就是某类目标物体出现在边界框中的可能性有多大,然后我们就完成了预测。
从输入图像中,我们预测出这个7*7*(5B+C)的张量,我们有B个基本边界框,每个边界框对应5个值,分别对应边界框的差值和我们的置信度,C对应C类目标类别的分数,我们可以把这种目标检测看做输入一张图像,输出一个3维张量,你可以使用一个巨大的卷积网络来训练这整个过程,这就是这个SSD算法的过程。
这个过程将使用真实类标去匹配,这些潜在的基本框虽然有点麻烦,但就是这么做的。另外基于候选框的网络,正如在Faster R-CNN中所使用的,最终会寻找出一系列比较接近图像网格的边界框。另外一些基于候选框的网络出了预测类别之外,还会对预测框做回归。这些概念有些重叠,在Faster R-CNN中,我们将目标区域的提出看做是一个端到端的回归问题,然后我们对提出的区域分别进行处理,但是在SSD方法中我们只做第一步,通过一个前馈网络一次进行所有的目标检测。
Yolo 或者 SSD,没有使用候选框方法论(来自cs231n)
因此物体检测有很多变量,这些方法中使用的基本网络会有所不同,比如有VGG、ResNet。我们已经看过目标检测方法所使用的不同的策略,这些方法包括Faster R-CNN这类基于候选框的方法,以及SSD这类方法,还有一类混合方法我没有提到,叫做R-FCN,是介于以上两种方法之间的,有很多的超参数,比如图像尺寸,你会用多少候选区域。
像Faster R-CNN这类基于区域的算法,更容易得到更高的精度,但是比SSD这类方法要慢一些,后者不需要对每个区域分别进行处理。
该论文结合了目标检测和图像说明来解决这种成为密集说明的问题,这个方法不只是预测每个区域的类别,而是想要预测每个区域的说明,我们有一些这样的数据集,数据中包含了对应的区域和文字说明,然后训练这个端到端的模型,对这些文字说明一起进行预测。这个和Faster R-CNN模型比较像,有提出候选框这一步骤,然后是预测目标检测框,然后是对目标检测框分别进行处理,论文方法的最后一步不是使用SVM或者softmax loss,而是使用了一个RNN语义模型来对每个候选框分别进行处理,预测其对应的文字说明,因此看起来和Faster R-CNN很像。
这个方法就是这样,一旦你理解了,你就可以把许多这类方法都结合起来,如果你有一些新的比较感兴趣的问题,比如密度说明,你可以复用很多从其他问题中学到的模块,比如目标检测和图像内容说明,将这些模块组合成一个端到端的网络,输出你所关心的问题的结果。
实例分割
最后一部分谈论的是物体分割的方法。
Instance Segmentation(来自cs231n)
物体分割,就像以上这四类问题,给定一张输入图像,我们想预测出一个位置和在图像该位置的物体对应的类别,就像目标检测,但不是只预测出每个目标的边框,而是想要预测出整个分割区域。对于每个物体,预测输入图像的哪些像素对应着预测物体,这个有点像是一种混合了语义分割和目标检测的方法。因为就像在目标检测中,我们可以处理多种物体并区分不同物体的类别,在这个例子中图像里有两只狗,物体分割方法将会识别出这两只狗,像是语义分割,我们可以得到逐像素的精确度。在这个方法中,对于每个物体,我们都想要明确哪些像素是属于它的,现在也已经有很多不同的方法已被人们实现,用来解决物体分割问题。最近效果最好的是下面这篇新论文中的方法,叫做Mask R-CNN。
这篇文章是在arXiv上发布的,这是很新的方法。这个和Faster R-CNN很像,也包含了多步处理,我们取整张输入图像,将整张输入图像送进卷积,网络中和训练好的候选框生成网络,和Faster R-CNN十分相似。得到训练好的候选框后,我们把这些候选框投射到我们的卷积特征图上,就像Fast R-CNN和Faster R-CNN中所做的那样。
但现在不是进行分类或回归预测边界框,而是对于这些框,我们想对每一个候选区域,每个边界框预测出一个分割区域,这像是一个微型的,像是一个语义分割问题,在每个我们从候选框生成网络中得到的候选框中,在我们将候选框对齐到特征后,对应的候选框就有了正确的尺寸,然后我们有两个分支,一个分支看起来和Faster R-CNN很像,该分支将会预测类别分数,告诉我们对应的候选框属于哪个类或者这是不是背景,我们也预测边界框的坐标,通过回归预测候选框的坐标。
另外我们还有下面的分支,基本看起来像语义分割的微型网络,会对输入候选框的像素进行分类,确定这是不是属于某个物体。这个Mask R-CNN问题,这个Mask R-CNN结构综合了我们今天说的所有的不同问题,整合成了一个端到端的训练模型,这真的很棒,而且它的效果真的很好。
论文里的结果令人惊讶,预测结果和真实类标看起来难以区分,所以在左边这个例子中有两个人站在机车前,这些人被周围的框标记了出来,而且模型比较详细地标记了那些人们的像素,真的非常精细,但是在左边的图像的背景中,同样有一群人,在背景里显得很小,这些人也都被框选了出来,每个人对应的像素也都被标记了出来。你可以看到最终表现真的很棒,这是在已有Faster R-CNN框架的基础上做的简单的添加。正如我告诉你们的,Mask R-CNN集合了我们今天谈到的所有模块。此外Mask R-CNN也可以做姿态估计。
通过预测人的每一个关节点的这些坐标,你可以用Mask R-CNN一起做物体识别、姿态估计和物体分割,我们唯一需要添加的部分是,对每个候选框额外添加一个分支,用来预测当前候选框中物体的关节点坐标,这算是另一个需要设置的loss。就像多加了一层是网络的另一个输出,是多任务loss中的一个附加项,一旦我们添加了这一个小小的分支,你就可以同时去解决这些不同的问题了。你会得到下面这样的结果。
Mask R-CNN 效果展示(一起做物体识别、姿态估计和物体分割)(来自cs231n)
这个单一的前馈网络会预测图像中有多少人,检测他们的所在位置,指出这些人中的每个对应的像素,并且可以画出骨架估计这些人的姿势,这表现的非常好。即使在教室这么人群拥挤的场景中有大量坐着的人,而且他们互相交错着,但模型最终的表现好的让人难以置信。因为这个模型是在Faster RCNN框架的基础上设计的,它的运行速度接近实时。在GPU上,它每秒可以预测5帧,因为这些问题相当于是通过单次前向传播解决的。
Q:需要多少训练数据?
所有这些物体分割的结果,都是在微软COCO数据集上训练得到的,微软的COCO数据集大约有200000张训练图像,一共有80个类别,200000张训练图像的每一张里都有80类中的物体,而且已被标记出来,所以大约是有200000张训练图像,平均每张图像有5到6个物体,所以它确实有很多的数据。对于微软COCO数据集,对于使用微软COCO数据集的人们,他们还有所有被标注出来的关节点信息,所以他们确实有相当多的数据用于监督学习训练。
一个值得我们推进的有趣话题是,如果你有很多数据可以用来解决一些问题,这样我们很确定,你可以通过搭建一些卷积神经网络来解决这些合理的问题,但是想出一个使用更少的数据达到这样表现的方法是一项非常有趣的研究。讲师认为这是在接下来的几年里花费大量精力去研究的内容。
总结
总结一下,今天快速讲了不同计算机视觉研究主题的大量工作,我们也看了大量结构,这些结构来源于图像分类任务,可以很容易地被应用于解决这些不同的计算机视觉任务中。







































