卷积神经网络之定位检测

简单的来复习一下卷积神经网络,我们分解了那些层次并花费了大量的时间来理解卷积算子的工作原理,并且学习如何把一个特征图像转换到另一个,这是通过滑动特征图上的窗口来计算内积,然后把这些表现通过许多层的处理来转化。如果你还记得这些较低的学习边界和颜色的卷积层,而高层则学习更加复杂的物体部分。我们还讲到了池化,池化用于抽样,并且缩小网路内的特征表现,这是我们看到的一个很普通的层级结构。我们还对特定的网络架构进行分析,这样你就能看到这些事物是如何在实践中被连接到了一起。

再简单复习一下经典模型,LeNet,他是一个很小的5层网络(98年)用于数字识别。AlexNet,是他拉开了深度学习的火爆序幕,之后是ZFNet,是一个图像分类网络。我们现在明白在分类中,更深一般会更好,例如表现良好的VGG和GoogLeNet。接下来我们讲到的是ResNet的新的神奇的网络,它深达152层,没有强大GPU的还是不要去轻易尝试使用这个。正如你们所见,这些网络都在变得更深,也随之表现的更好。

定位

但是这些都仅仅为了分类,所以我现在介绍下定位,这是在计算机视觉另一个很大很重要的问题。正如我刚才所说的,网络越深结果可能越好这个结论,在这两个任务中一样成立,所以到目前为止我们一直在讲分类。其实就是对于一张图片,我们要对不同数量上的物体类别进行分类。这是一个在计算机视觉中很好也很基础的问题,我们用它来理解CNN。

但人们在研究过程中也遇到了许多其他的问题。这其中就有分类和定位。现在,除了仅仅把图像和类标签进行分类,我们还希望把框框放在图像中,表明这就是分类发生的区域。还有一个人们正在解决的问题就是检测。所以这里还是一些对象类别的数量,但实际上我们希望选中在图像内所有该类别的目标以及它们周围的选框。在一个最近人们才开始着手研究的项目中有一个令人着魔的东西,他叫做实时图像分割,其原理就是你有一定数量的类别,你想在图像中找到所有类别对应的目标,但是相比于用框框选,实际上更希望圈出围绕该目标的轮廓,并识别所有的属于每一个目标的像素。图像分割是有一些疯狂,所以我在这里不去讨论他,但是你们也要了解他。

我们今天则要着重关注定位和检测的内容。这两者的区别就是我们所找到的目标的数量。在定位中,一般是有一个或一种对象;但在检测中,会有很多个或多种对象。这看起来是个很小的区别,但是他对最终的架构起很重要的作用。所以我们会先讲分类和定位。因为这两个是最简单的。

概括一下我刚才所讲的,分类是一张图片中只有一种给定类别标签的对象,定位则是在图像中给对象圈上框框,而分类定位就是指我们要同时符合这两者的要求。

介绍一下人们目前用此达成的任务会给你们一些启发。我们讲到了ImageNet分类的挑战,ImageNet还有分类+定位的挑战。相似与分类,这里有1000个类,在这些类中,每一个训练目标都有一个类和许多的在图像内部对应该分类的位置选框。那么现在有一个用于测试的更小的算法,这个算法会得出五个猜想,与其说这些猜想仅是类标签,不如说他们是与位置框框在一起的类标签。为了得到正确的猜想,你要得到正确的类标签和正确的位置框框。如果得到了正确位置,那就代表你的结果很接近分割的准确率(loU: intersection of union)了,不过你现在不必去考虑loU的事情。

所以重复一遍就是,只要你五个猜想中的一个是正确的,你就会得到正确的imageNet。所以这就是人们一直研究的分类+定位的最主要数据集。

回归的使用

当研究定位时,有一个特别有用的很基础的范式:回归。我不知道在回想机器学习的课程当中,你能不能想起分类算法,比如SVM,还有回归算法;当我们讨论定位的时候,我们可以把它视作回归问题。

比如说我们有一张图片,这张图片要经过一系列的处理过程,并最终生成四个代表框框大小的实数。有许多不同的参数来描述框框,人们常用的是用XY坐标定位框框的左上角、宽度和高度,不过也有其他的变量,但对于框框来说这些变量都只能是四个数。还有一些真实准确(ground truth)的选框,也是用四个变量描述的。

我们还可以计算损失,比如欧式损失,欧式损失是一个很标准的选择,是我们所生成的数字与正确的数字之间的差额。那么现在我们就可以同样训练他就像我们训练分类网络那样:我们用ground truth边框对许多批数据进行抽样,并向前传播,我们所做的预测与正确的预测只差所带来的计算机损失则往回传播,一次为方法来升级网络。

这个范式很简单,也使得定位的实行也变得简单。这里有一个简单的秘诀,这个秘诀会告诉你怎样来实时分类+定位。首先你要下载现有的前训练模型。如果你对自己的技术感到自行的话,你可以自己进行训练,训练模型可以使AlexNet,VGG,GoogLeNet等。那么我们就可以得到训练后生成class scores的全连接层.

但我们先暂且不去管他,现在我们在这个网络里再接上一些新的FC。我们把这称之为回归网络(regression head)。但我认为这实际上跟FC是一个意思,只不过输出一些实数。

现在我们训练它就像训练我们自己的分类网络,唯一区别就是我们把class cores和classes替换成L2 loss和ground truth框框。除了以上的区别,我们使用训练原来网络的方法来同样训练这个新的网络。当测试的时候,我们就用这斜来实现分类和定位。

我们找了一些照片,并且训练了分类网络和定位网络,我们将图片进行处理就能得到class scores和框框,就这样任务完成了,按照步骤做就能在你们的项目中进行分类和定位。

在这个方法中还有个细节要注意,在进行回归时一共有两种主要方式,不定类回归(class-agnostic regression)和特定类回归(class-specific regression)。

不定位回归是无论我使用什么类别,全连接层中都使用相同的结构和权值来得到边界昂狂框(bounding box),得到的结果总是4个数字,无论是什么类别他们表示的都是那个框。另外一种选择是特定类回归,输出的结果是C承上4个数字,相当于每种类别有一个边界框,很多人发现这种方法在很多情况下效果会更好。直观地说这种方法确实是有意义的,试着思考一下,对一只猫猫确定其边界和对火车确定边界总是有一些不同的,所以你需要在网络中有不同的处理来应对这个问题。他稍微改变了计算损失的方式,不仅仅是使用ground truth class来计算损失,除此之外在其他方面这两种基本属于同一思想。

另一个需要选择的地方是在网络的那个位置进行回归。这也不是很重要,不同的人有不同的方式。这个比较常见的选择是将回归层(regression head)放在最后一次卷积层后,这就像是你对全连接层重新做了初始化,像Overfeat、VGG网络就是这种方式。另一种选择是将回归层放在FC之后,像deepPose和RCNN就是这种方式工作的。这两种方式效果都不错,你可以按照自己的喜好去设置。

顺便提一下,我们可以用这个框架对不止一种物体来划定其边界框。通过这个分类和定位,我们输入一张图片,然后关注他所产生的这个图片的边界框。但是在一些情况下,你提前知道要对固定数量的物体进行划分边界框,在这里总结起来很简单,回归层输出了每个物体对应的边界框,然后你用同样的方式对网络再次进行训练。

同时对多个物体进行定位是非常通用而且功能强大的。例如,这项技术在人类姿势判定中得到应用。当你输入一个人的特写镜头时,人们想知道这个人的姿势是什么。人体都有着固定数量的身体关节,像手腕。我们需要去找到所有的关节,所以当我们输入这张图片时通过一个卷积网络,然后我们能够在XY轴上找到每个关节的位置,从而能够让我们对这个人的姿势进行预测。

总的来说,定位的思想和通过回归定位固定数量的物体是非常简单的。我知道有时你想在项目中进行检测,而不是定位和分类,如果你们向更深入的理解图像,并在进行项目时能够考虑到这些方面的话,我希望你们能够考虑一下这个定位的框架:如果在每个图像中都有固定数量的物体需要定位的话,你可以将它看成是定位问题,这样会使问题更简单一点。

所以这个通过回归定位的方法确实很简单,他确实有用,但是如果你想在imageNet这样的比赛占有一席之地的话,你需要一些新的东西。所以人们定位是考虑到的方法还包括了滑动窗口(sliding window)。在这个方法中你依然要在网络中进行分类和定位的操作,但是你不只是运行了一次,而是在不同的位置多次进行,再讲不同位置进行聚合,事实上有一种高效的方法来做这个事情。

Overfeat

为了更具体的了解滑动窗定位方法的工作过程,我们先了解一下Overfeat的结构。

Overfeat是在imageNet定位挑战赛中的优胜者,这个结构看上去和我们之前讲过的很相似,开始是一个AlexNet,然后是分类层和回归层。分类层输出产生类的分数,因为这是一个ALexNet类型的结构,期望的输入图片大小是 221 * 221,但是实际上我们可以输入更大的图片,此时滑动窗的方法能够起到作用。

比如说 257 * 257 的图片,然后在图片左上方进行分类和定位,从而得到类的分数和相应的边界框。重复这个操作,使用相同的分类和定位网络,在这个图片四个角落都运行了一次,最终我们会得到四个边界框,对于每个位置都有一个边界框和类的分数。但是事实上我们只需要一个边界框,所以使用了一些方法对这些边界框和分数进行了合并,这部分很复杂,我目前也不是很懂。反正通过组合和聚集不同位置的边界框可以帮助这个模型进行错误修正,他的工作效果很好。

(当你进行回归时,输出的是(表示边界框的)四个数字,这个数字理论上可能出现在任何地方,他甚至不一定在图片内部,当你再用滑动窗方法进行训练的时候,你对不同位置进行操作时坐标轴也会进行一些改变,这也是需要注意的一个地方)

但是在实际操作中要使用远多于四个的边界框,使用的输入图片的大小也有多种,你可以看到这是从论文中摘取的图像,在左边的图像中,你可以看到在不同的位置对这个网络进行评估,在中间的图像中你可以看到的是对每个位置输出响应的边界框,在图像底部你可以看见是对于这些位置分数的映射。这看上去有点乱,但是采用这个聚合方法,他们最终能得到那个熊的最终边界框,然后确定这个图片是一只熊。

全连接层与卷积层的转换

一个你能够预料的问题是对每个类别都运行这个网络的花费是非常昂贵的,事实上有个高效的方法。我们通常将网络看成由卷积网络和链接网络构成的,但是换一种角度看,一个全连接网络是有4096个数字构成是一个向量,如果不把他看成一个向量,而是将它看成另一个卷积的特征映射。(下图为原结构)

我们将它进行转换成 1 1 维的,所以这个方法是将全连接层转换成卷积层,我们得到了这个卷积特征映射,通过这个特征映射我们产生4096维向量的每一个元素,我们考虑通过一个 5 5 的卷积层,而不是对特征映射进行直接的变换。这看上去有一些怪异,但是思考以后你会发现这很有意义。所以我们将这个全连接层进行一个 5 5 的卷积运算,然后我们通过另一个全连接层,从4096维到4096维,这是一个 1 1 的卷积运算。如果你认真思考用数学公式演算,你就能理解了。(下图为转换后结构)

现在我们要做的是使用卷积层来组合原来的网络的全连接层,这样效果很好因为我们的网络就完全只由卷积层与池化层和元素操作了。我们实际上可使用不同尺寸的图片来运行网络,这种方法可以通过一个非常节约计算资源的方法来给我们一个等价的、与位置无关的结果。

下面看看他的原理。

在训练环节你用的是一个 14 14 的输入图片进入卷积层,然后是这个全连接层,我们现在把它视为卷积层,在这里我们有个 5 5 的卷积核,通过这个卷积核把之前的结果变成一个 1 1 的元素。在这里我们没有展现深度,这里的 1 1 其实是 1 1 4096,这样我们就把这个层转化成了额卷积层。

下面这一行,我们的卷积层运行在了一张更大尺寸的图片上,你们可以看到我们加了一些额外的像素,然后我们在运行一次同样的卷积池化过程,最后得到了一个2*2的输出。这样最大的好处就是我们现在可以在不同大小的图片上使用相同的计算过程,这样能够大大提高我们的效率。

现在我的输出是原来的四倍大,但是我们计算消耗的时间远远小于四倍,因为如果你考虑两次计算中不同的地方,其实额外的计算量只发生在黄色的这一部分,所以现在我们十分高效的计算了神经网络在不同位置上的结果,在这同时并没有带来特别大的额外计算量。

补充

  • 你可以使用同一个网络进行分类和定位,也可以使用不同的网络分别进行分类和定位
  • 尽量不要选择没有使用反向传播的网络