在此之前,我们讨论了对象检测,关于它是什么以及最近如何使用深度学习解决它。 如果您还没有阅读我们之前的博客文章,我们建议您在继续之前先看一下它。(深度学习之对象检测的概念、现状与挑战)
去年,我们决定涉足Faster R-CNN,阅读原始论文和所有参考论文(以此类推),直到我们清楚地了解它是如何工作以及如何实现它。
我们最终在Luminoth中实施了Faster R-CNN,这是一个基于TensorFlow的计算机视觉工具包,可以轻松训练,监控和使用这些类型的模型。 到目前为止,Luminoth已经引起了极大的兴趣,我们甚至在ODSC Europe和ODSC West谈到了它。
基于开发Luminoth的所有工作并基于我们所做的演示,我们认为最好有一篇博文,其中包含我们在研究中收集的所有细节和链接,希望能成为对该主题感兴趣的人们的未来参考。
背景
Faster R-CNN最初发布于NIPS 2015。在发布之后,它经历了几次修订,我们稍后会讨论。 正如我们在之前的博客文章中提到的,更快的R-CNN是R-CNN论文的第三次迭代 - 其中Ross Girshick是作者和合着者。
一切都始于2014年的“用于精确对象检测和语义分割的丰富特征层级”(R-CNN),其使用称为选择性搜索的算法来提出可能的感兴趣区域和使用标准卷积神经网络(CNN)对它们进行分类和调整。 它迅速演变为2015年初发布的Fast R-CNN,其中一种称为兴趣区域池化的技术允许共享昂贵的计算并使模型更快。 终于推出了Faster R-CNN,其中提出了第一个完全可微分的模型。
架构
Faster R-CNN架构很复杂,因为它有几个移动部件。 我们将从高级概述开始,然后逐一介绍每个组件的详细信息。
这一切都始于一幅图像,由此我们想要获得:
- 边界框列表。
- 分配给每个边界框的标签。
- 每个标签和边界框的概率。
Faster R-CNN完整的架构
输入图像表示为 tensors(多维数组),它们通过预先训练的CNN,从一个中间层输出,最后得到一个卷积特征图,我们将其用到下一部分。
该技术在转移学习的上下文中非常常用,尤其是使用在较大数据集上训练的网络权重来训练小数据集上的分类器。我们将在以下部分深入研究这一点。
接下来,我们有一个所谓的区域提议网络(简称RPN)。它基于CNN提取的特征图,来查找预先设定数量的区域(边界框),这些区域可能包含对象。
将深度学习(DL)用于对象检测的最困难的问题可能是生成一个可变长度的边界框列表。在对深度神经网络进行建模时,最后一个块通常是一个固定大小的张量输出(除非使用RNN)。例如,在图像分类中,输出是形状的张量,其中
是类别的数量,其中位置
中的每个标量代表该图像属于某个类标记的概率。
在RPN中通过使用锚点解决可变长度问题:固定大小的参考边界框,其均匀地放置在整个原始图像中。我们不是检测对象的位置,而是将问题分为两部分。对于每个锚,我们都会问:
- 这个锚是否包含相关对象?
- 我们如何调整此锚以更好地适应相关对象?
这可能会让人感到困惑,但不要担心,我们将在下面深入讨论。
在获得一个原始图像上的可能对象及其位置的列表后,下面的将成为一个更直接的问题: 使用由CNN提取的特征和具有相关对象的边界框,我们应用感兴趣区域(RoI)池化并将与对象相对应的那些特征提取到新的张量中。
最后是R-CNN模块,它使用该信息来实现:
- 对边界框中的内容进行分类(或将其丢弃,若使用“背景”作为标签)。
- 调整边界框坐标(以使它更适合对象)。
显然,缺少一些主要的信息,但这基本上是关于R-CNN如何工作的一般概念。接下来,我们将详细介绍每个组件的体系结构和损失/训练。
基础网络
如前所述,第一步是使用预训练的CNN进行分类(例如使用ImageNet)和使用中间层的输出。 对于具有深入学习背景的人来说,这听起来非常简单,但重要的是要了解它的工作原理和原因,以及可视化中间层输出的样子。
关于哪种网络架构最优,这个问题没有达成真正的共识。 最初的Faster R-CNN使用了在ImageNet上预训练的ZF和VGG,但从那时起,有许多不同的网络具有不同数量的权重。 例如,MobileNet是一种针对速度优化的小型高效网络架构,具有大约3.3M的参数,而ResNet-152(152层),曾经是ImageNet分类竞赛中的最先进技术,大约有60M。 最近,像DenseNet这样的新架构既改善了结果又降低了参数数量。
VGG
在我们讨论哪个更好或更糟之前,让我们尝试使用标准VGG-16作为示例来理解它是如何工作的。
VGG架构
VGG的名字来源于在ImageNet ILSVRC 2014竞赛中使用它的团队,发表在Karen Simonyan和Andrew Zisserman的论文“应用非常深的卷积网络于大规模图像识别”中。按照今天的标准,它不会被认为是非常深的,但是当时它通常使用的层数增加了一倍以上,并且启动了“更深→更多容量→更好”的波浪(当可以进行训练时)。
当使用VGG进行分类时,输入为 3224×224×3的张量(即224x224像素RGB图像)。这必须保持固定以进行分类,因为网络的最后一块使用全连接(FC)层(而不是卷积),这需要固定长度的输入。这通常通过在使用FC层之前平坦化最后一个卷积层的输出,获得秩1张量来完成。
由于我们将使用中间卷积层的输出,因此输入的大小不是我们的问题。至少,这不是该模块的问题,因为只使用卷积层。让我们进一步了解底层细节,并定义我们将要使用的卷积层。该文件没有具体说明使用哪一层;但在官方实施中,您可以看到他们使用conv5 / conv5_1图层的输出。
每个卷积层基于先前信息创建抽象。第一层通常学习边缘,第二层在边缘找到图案以激活更复杂的形状等等。最终我们得到了一个卷积特征图,其空间尺寸比原始图像小得多,但深度更大。由于卷积层之间应用了池化层,并且深度由于卷积层学习的过滤器数量而增加,因此特征图的宽度和高度减小。
从图像输出卷积特征图
在其深度中,卷积特征图已经编码了图像的所有信息,同时保持了它相对于原始图像编码的“物体”的位置。 例如,如果图像左上方有一个红色方块并且卷积层为其激活,那么该红色方块的信息仍将位于卷积特征图的左上角。
VGG vs ResNet
如今,ResNet架构大多成为取代VGG作为提取特征的基础网络。 Faster R-CNN(Kaiming He,Shaoqing Ren和Jian Sun)的三位合着者也是“图像识别的深度残差学习”的共同作者,这是描述ResNets的原始论文。
ResNet相对于VGG的明显优势在于它更大,因此它具备更强大的能力来实际了解所需内容。 这对于分类任务是正确的,并且在对象检测的情况下应该同样如此。
此外,ResNet使用残差连接和批量标准化可以轻松训练深度模型,这在VGG首次发布时尚未发明。
锚 (Anchor)
当我们正工作在已处理的图像上时,我们需要找到提议,即: 用于分类的感兴趣区域。我们之前提到锚点是解决变长问题的一种方法,但我们跳过大部分解释。
我们的目标是在图像中找到边界框。它们具有矩形形状,并且可以具有不同的尺寸和纵横比。想象一下,我们试图解决问题,事先知道图像上有两个对象。首先想到的是训练一个返回8个值的网络:两个 元组定义每个对象的边界框。这种方法存在一些基本问题。例如,图像可以具有不同的尺寸和纵横比,训练一个能预测原始坐标的模型可能变得非常复杂(如果可能的话)。另一个问题是无效预测:当预测
和
时,我们必须以某种方式强制
。
事实证明,通过学习预测相对参考盒的偏移,是进行边界框预测的一种更简单的方法。我们采用参考框 并学习预测
,通常是小值,调整参考框以更好地拟合我们想要的。
锚是固定的边界框,它们放置在整个图像中,具有不同的尺寸和比例,在首次预测对象位置时将用于参考。
由于我们正在处理大小为 的卷积特征图,因此我们为
的每个点创建了一组锚。重点是要理解: 即使我们是基于卷积特征图来定义锚,但最终锚也会参考原始图像。
由于我们只有卷积层和池化层,因此特征贴图的尺寸将与原始图像的尺寸成比例。数学上,如果图像为,则特征图将以
结束,其中
称为下采样率。如果我们在特征图的每个空间位置定义一个锚点,则最终图像将是一系列由
个像素分隔的锚。在VGG的情况下,
= 16。
原始图像的锚中心
为了选择一组锚,我们通常定义一组尺寸(例如64px,128px,256px)和一组宽高比(例如0.5,1,1.5)并使用所有可能的尺寸组合和比率。
左图: 一组锚 中图: 单个点的锚 右图:所有锚
区域提议网络
RPN使用卷积特征图并在图像上生成提议
正如我们之前提到的,RPN获取所有参考框(锚)并输出一组对象的好建议。它通过为每个锚提供两个不同的输出来实现这一点。
第一个是锚是对象的概率。如果你愿意的话,就是“对象得分”。请注意,RPN并不关心它是什么类的对象,只要它实际上看起来像一个对象(而不是背景)。我们将使用此对象得分来过滤掉第二阶段的错误预测。第二个输出是边界框回归,用于调整锚以更好地适应它预测的对象。
使用基础网络返回的卷积特征图作为输入,RPN以完全卷积的方式得以有效地实现。首先,我们使用具有512个通道和3x3核尺寸的卷积层,然后我们使用1x11x1核尺寸获得两个并行卷积层,其通道数取决于每个点的锚的数目。
RPN架构的卷积实现 (k是anchor的数目)
对于分类层,我们为每个锚输出两个预测:它是背景的分数(不是对象),它是前景的分数(实际对象)。
对于回归或边界框调整图层,我们输出4个预测:增量,我们将应用于锚以获得最终建议。
使用最终提议坐标及其“对象”得分,我们就可以获得一组很好的对象提议。
训练,目标和损失功能
RPN执行两种不同类型的预测:二分类和边界框回归调整。
对于训练,我们采用所有锚并将它们分为两个不同的类别。那些与标定框(ground-truth)对象重叠并且大于0.5 IoU的交叉点被认为是“前景”,那些不与任何标定框重叠或者与标定框重叠小于0.1 IoU的被认为是“背景” ”。
然后,我们随机抽样这些锚点,构成一个数量为256的小批次 - 尽量保证前景和背景锚点之间的平衡比例。
RPN使用这个小批量的所有锚以二元交叉熵来计算分类损失。然后,它仅使用标记为前景的那些锚点来计算回归损失。为了计算回归的目标,我们使用前景锚点和最接近的标定框对象,并计算将锚点转换为对象所需的正确。
本文建议使用平滑L1损失,而不是使用简单的L1或L2损失来表示回归误差。平滑L1基本上是L1,但是当L1误差足够小时,由某个定义,误差被认为几乎是正确的,并且损失以更快的速率减小。
出于多种原因,使用动态批次可能具有挑战性。尽管我们试图在被认为是背景的锚和被认为是前景的锚之间保持平衡的比例,但这并不总是可行的。根据图像中的标定对象以及锚点的大小和比例,可能最终得到零前景锚点。在这些情况下,我们转向使用与标定框有最大IoU的锚点。这远非理想,但实际上我们总是有前景样本和目标来学习。
后处理
非最大抑制 因为锚点通常重叠,所以提议最终也会在同一个对象上重叠。 为了解决重复提议的问题,我们使用一种称为非最大抑制(NMS)的简单算法方法。 NMS采用按分数排序的提议列表和已排序列表上的iterateqs,丢弃那些与某个更高分数提议的IoU大于预定阈值的提议。
虽然这看起来很简单,但谨慎对待IoU阈值非常重要。 太低,你可能最终错过了对象的提议; 太高了,你最终可能会为同一个对象获得太多提议。 常用值为0.6。
提议选择 应用NMS后,我们会按分数排序前N个提议。 在论文中使用了N = 2000N = 2000,但是可以将该数字降低到50,并且仍然可以获得非常好的结果。
独立应用
RPN可以单独使用而无需第二阶段模型。 在单一类别对象的问题中,对象概率可以用作最终类概率。 这是因为对于这种情况,“前景”=“单一类”和“背景”=“不是单一类”。
可以从RPN独立使用中受益的机器学习问题是流行的面部检测和文本检测(但仍然具有挑战性)。
仅使用RPN的一个优点是在训练和预测中都获得了速度的提高。 由于RPN是仅使用卷积层的非常简单的网络,因此预测时间可以比使用分类基础网络更快。
兴趣池化区域
在RPN步骤之后,我们有一堆对象提议,没有为它们分类。 我们要解决的下一个问题是如何采用这些边界框并将它们分类为我们想要的类别。
最简单的方法是采用每个提议,裁剪,然后通过预先训练的基础网络。 然后,我们可以使用提取的特征作为图像分类器的输入。 其主要问题是运行所有2000个提议的计算效率非常低且速度慢。
Faster R-CNN试图通过重用现有的卷积特征图来解决或至少缓解这个问题。 这是通过使用感兴趣区域池化为每个提议提取固定大小的特征图来完成的。 R-CNN需要固定大小的特征图,以便将它们分类为固定数量的类。
兴趣区域池化
在对象检测的实现中,广泛使用的一种更简单的方法,包括Luminoth的Faster R-CNN,是使用每个提议裁剪卷积特征图,然后通过插值(通常为双线性)将每个裁剪调整为固定大小的。 裁剪后,使用2x2内核的最大池化来获得每个提议的最终
特征图。
选择这些具体形状的原因与下一个步(R-CNN)使用它的方式有关。 重要的是要了解这些可根据第二阶段使用进行定制。
基于区域的卷积神经网络
基于区域的卷积神经网络(R-CNN)是Faster R-CNN管道中的最后一步。 在从图像中获取卷积特征图之后,使用它来获取RPN的对象提议并最终提取每个提议的特征(通过RoI池),我们最终需要使用这些特征进行分类。 R-CNN试图模仿分类CNN的最后阶段,其中使用完全连接的层来输出每个可能的对象类的分数。
R-CNN有两个不同的目标:
- 将提议分类为其中一个类,加上背景类(用于删除不良提议)。
- 根据预测的类更好地调整提议的边界框。
在最初的Faster R-CNN论文中,R-CNN获取每个提议的特征图,将其展平并使用两个带ReLU激活的尺寸为4096的完全连接层。
然后,它为每个不同的对象使用两个不同的完全连接的层:
- 具有
个单元的完全连接层,其中
是类的总数,而额外的一个用于背景类。
- 具有
单元的完全连接层。 我们想要一个回归预测,因此对于
个可能类别的每一个都需要
R-CNN 架构
训练和目标
R-CNN的目标以与RPN目标几乎相同的方式计算,但考虑到不同的可能类别。我们采用提议和标定框,并计算它们之间的IoU。
具有与任意标定框IoU大于0.5的的提议被赋予该标定框。那些介于0.1和0.5之间的被标记为背景。与我们在为RPN组装目标时所做的相反,我们忽略了没有任何交集的提议。这是因为在这个阶段我们假设我们有很好的建议,我们更有兴趣解决更难的案例。当然,所有这些值都是超参数,可以调整它们以更好地适应您要查找的对象类型。
边界框回归的计算目标是提议与其对应的标定框之间的偏移量,这仅针对已根据IoU阈值分配了类别的提议。
我们随机抽取一个数目为64的小批次,其中我们有多达25%的前景提案(具有类别)和75%的背景。
遵循与我们对RPN损失相同的路径,分类损失现在使用的是多类交叉熵损失,使用所有选定的提议, 以及使用平滑L1损失到与标定框匹配的25%提议。在获得损失时我们必须要小心,因为用于边界框回归的R-CNN完全连接网络的输出对每个类都有一个预测。在计算损失时,我们只需要考虑正确的类别。
后期处理
与RPN类似,我们最终会得到一堆分配了类的对象,这些对象在返回之前需要进一步处理。
为了应用边界框调整,我们必须考虑哪个是该提议的概率最高的类。 我们还必须忽略具有背景类的概率最高的那些提议。
在获得最终对象并忽略那些预测为背景的对象之后,我们应用基于类的NMS。 这是通过按类对对象进行分组,按概率对它们进行排序,然后在再次加入NMS之前将NMS应用于每个独立组来完成的。
对于我们的最终对象列表,我们还可以设置概率阈值和每个类的对象数量限制。
训练
在原始论文中,使用多步骤方法训练Faster R-CNN,独立训练部分并在最终完整训练方法之前合并训练的权重。从那时起,人们发现,进行端到端的联合训练可以带来更好的结果。
在将完整模型放在一起之后,我们最终得到了4种不同的损失,其中两种用于RPN,两种用于R-CNN。我们在RPN和R-CNN中有可训练的层,我们也有基本网络,对于基本网络我们可以训练(微调)或不训练。
训练基础网络的决定取决于我们想要学习的对象的性质和可用的计算能力。如果我们想要检测与基础网络所训练的原始数据集上的对象类似的对象,那么除了试图挤压我们可以获得的极致性能之外,没有任何实际需要。另一方面,训练基础网络在时间和必要的硬件上都是昂贵的,以便能够适应完整的梯度。
使用加权和来组合四种不同的损失。这是因为我们可能希望分类损失相对于回归损失更重,或者可能使R-CNN损失比RPN更多。
除了常规损失之外,我们还有正则化损失,为简洁起见我们跳过这些损失,但可以在RPN和R-CNN中定义。我们对某些层使用L2正则化,并且取决于所使用的基础网络以及是否经过训练,它也可能具有正则化。
我们使用带动量的随机梯度下降进行训练,将动量值设置为0.9。您可以轻松地使用任何其他优化器训练更快的R-CNN,而不会遇到任何大问题。
学习率从开始,然后在50K步骤后降至
。这是通常最重要的超参数之一。在使用Luminoth进行训练时,我们通常从默认值开始并在此刻进行调整。
评估
使用标准平均精度(mAP)在某个特定IoU阈值(例如mAP@0.5)进行评估。 mAP是来自信息检索的度量,通常用于计算排名问题和评估对象检测问题时的错误。
我们将不深入讨论细节,因为这些类型的度量标准应该有自己的博客文章,但重要的一点是当你错过了一个应该检测到的对象框时,以及当你检测到一些不存在的东西,或者多次检测同一个对象时,mAP会惩罚你。 。
结论
到目前为止,您应该清楚地知道R-CNN的工作速度有多快,为什么做出了一些决定,以及如何根据具体情况对它进行调整。 如果您想更深入地了解它的工作原理,你应该检查Luminoth的实现。
Faster R-CNN是其中的一个模型,它证明了用同样的原理解决复杂的计算机视觉问题是可能的,这些原理在这个新的深度学习革命开始时显示了如此惊人的结果。
目前正在建立新的模型,不仅用于对象检测,而且用于基于这个原始模型进行语义分割、3d对象检测等。一些借用RPN,一些借用R-CNN,其他的只是在两者之上构建。这就是为什么要充分了解其中的原因,以便我们更好地准备应对未来的问题。
(原文: https://tryolabs.com/blog/2018/01/18/faster-r-cnn-down-the-rabbit-hole-of-modern-object-detection)