F-RCN论文阅读及难点解析

拥有回忆 提交于 2020-02-20 06:33:38

论文名称:《 R-FCN:object detection via region-based fully convolutional networks 》

论文下载:http://papers.nips.cc/paper/6465-r-fcn-object-detection-via-region-based-fully-convolutional-networks.pdf

论文代码:https://github.com/daijifeng001/r-fcn

一、概述:

1、R-FCN创新点:

R-FCN要解决的根本问题是Faster R-CNN检测速度慢的问题。Faster R-CNN速度慢是因为ROI层后的结构对不同的proposal是不共享的,试想下如果有300个proposal,ROI后的全连接网络就要计算300次,耗时惊人。所以本文作者把ROI后的结构往前挪来提升速度,但光是挪动下还不行,ROI在conv5后会引起上节提到的平移可变性问题,必须通过其他方法加强结构的平移可变性,Position-sensitive score map因此而生。

归纳如下:

(1)提出Position-sensitive score maps来解决目标检测的位置敏感性问题;

(2)充分利用全卷积网络来减少总体计算量,提升速度比Faster-RCNN快2.5-20倍;

2、R-FCN与传统二阶段网络的对比:

R-FCN中,所有能共享的层都在ROI Pooling之前做好了,因此在ROI Pooling后基本不会有太多的重复计算。为了要在ROI Pooling之前实现层共享,一方面将conv5_x的计算移到Pooling层之前,但这样依然还存在一些全连接层的重复计算,因此再引入position-sensitive score map和position-sensitive ROI Pooling,使得经过Pooling后简单地执行一些操作就能得到回归和分类结果,而不再像Faster RCNN一样用几个全连接层去得到结果。
在这里插入图片描述
相同点:

(1)均为two-stage的目标检测框架;

(2)最终输出的结果均为相应的类别和对应的BB;

不同点:

(1)和Faster R-CNN相比,Faster R-CNN的共享卷积子网络是91层,RoI-wise子网络是10层,而R-FCN只有共享卷积子网络,深度为101层;R-FCN具有更深的共享卷积网络层,这样可以获得更加抽象的特征;

(2)和Faster R-CNN相比,没有RoI-wise subnetwork,不像Faster R-CNN的feature map左右都有对应的网络层,它是真正的全卷积网络架构;

(3)和R-CNN相比,最大的不同就是直接获得整幅图像的feature map,再提取对应的ROI,而不是直接在不同的ROI上面获得相应的feature map。

3、要解决的问题(提出 Position-sensitive score maps):

分类网络的位置不敏感性和检测网络的位置敏感性的一个矛盾问题,而在目标检测中不仅要分类也要定位。
在这里插入图片描述
(1)类网络的位置不敏感性(translation-invariance),即平移不变性:

平移不变性则是针对分类任务的。对于分类任务,随着某个目标在图片中不断的移动,希望网络仍然可以准确的将目标区分为对应的类别。如上图左边所示,不管鸟在图片中如何移动,分类网络应将其准确分类为鸟。实验表明,深的全卷积网络能够具备这个特性,如ResNet-101等。举个例子,在用基础的分类结构比如ResNet、Inception给一只猫分类时,无论猫怎么扭曲、平移,最终识别出来的都是猫,输入怎么变形输出都不变这就是平移不变性,网络的层次越深这个特性会越明显。

(2)检测网络的位置敏感性(translation-variance),即平移可变性:

平移可变性则是针对目标检测的。对于检测任务,随着某个目标的移动,希望网络的预测框能够和它一起移动,即仍然能够准确的检测到它,即网络对目标位置的移动很敏感。更改预测框位置需要计算对应的偏差值,以及预测bbbox和GT的重合率等。深的全卷积网路不具备这样的特征。举个例子,一只猫从图片左侧移到了右侧,检测出的猫的坐标会发生变化就称为平移可变性。当卷积网络变深后最后一层卷积输出的feature map变小,物体在输入上的小偏移,经过N多层pooling后在最后的小feature map上会感知不到,这就是所谓“网络变深,平移可变性变差”。

举个例子,以ResNet-101为主干的Faster R-CNN 网络。如果在Faster R-CNN中没有ROI池化层把RPN生成的Proposal映射到原特征图中缩小预测范围,直接对整个feature map进行分类和位置的回归,由于ResNet的结构较深,平移可变性较差,检测出来的坐标会极度不准确。ROI就是Region proposal。

如果在ResNet卷积层中间加个ROI层结果就不一样了,ROI层提取出的proposal中,有的对应目标类别label,有的对应背景label,proposal位置的偏移就有可能造成其label分类(前景和背景分类)的不同。偏移后原来的前景label很有可能变成了背景label,原来的背景很有可能变成了前景,对携带label信息的proposal进行学习和分类,则分类loss对proposal的位置是敏感的,这种情况ROI层给深层网络带来了平移可变性。

如果把ROI加到ResNet的最后一层,前面输出的feature map太小,这时proposal的一个小偏移在conv5输出上很有可能都感知不到,即proposal对应的label没有改变,ROI把proposal对应到原特征图上的类别不准确,所以虽然有ROI也对平移可变性没有什么帮助,以此进行训练学习,识别出来的位置准确度会很差。

二、核心操作:

文中的ROI就是region proposal。另外Faster RCNN中的ROI Pooling和本文的ROI Pooling不是一个意思,前者只是简单将每个region feature变换到统一的尺寸的feature,变换过程中采用Max pooling;而后者则是一种position-sensitive的ROI Pooling。

1、Position-sensitive score map:

ResNet-101应用到R-FCN,把最后的average pool和1000-d fc全连接层都去掉,只保留前100层。后面新加一个1x1x1024的卷积层用来降维(从2048降到1024),再加一个特殊卷积来生成kk * (C+1)维的Position-sensitive score map_1。其中的C是要分类的类别数,加上1表示加上一个背景分类;kk是之后的ROI Pooling中对ROI(region proposal)区域要划分的小格数,比如论文中k=3就是对ROI在长宽方向各三等分形成9个小区域。

Position-sensitive score map的值对ROI相对于原图的位置移动很敏感。图中最后一个特殊卷积输出Position-sensitive score map_后,就要对其做ROI Pooling了,和Faster R-CNN中的ROI Pooling一样,要对score map_1上某个ROI对应部分9个小区域分别进行pooling,每个小区域只会在对应的(C+1)个维度上作pooling,得到11(C+1)的向量,即原来的ROI的一个面pool成了一个点,比如ROI左上角的区域就在前C+1个维度上pooling,左中位置的区域就在C+2到2C+2间的维度上作pooling,以此类推。pooling后输出的是C+1维度的kk个列向量,每个维度(对应一个类别)上的kk个数据(对应这kk部分是否都含有目标的一部分)再加到一起(图1的vote过程)形成C+1个单点数据,及对应类别的类别概率。对于目标定位的输出和上面的分类输出过程类似,只是维度不再是kk * (C+1),而是kk4,表示9个小区域的[dx,dy,dw,dh]4个偏移坐标。
在这里插入图片描述
除了主网络ResNet以外,还有RPN网络用于生成ROI(region proposal),因此在训练的时候,作者采用RPN网络和R-FCN交替训练的方式来共享特征。

这部分比较抽象,但是是本文精髓,下面再详细分析一下原理:

若一个RoI中含有一个类别C的物体,我们将该RoI划分为KK 个区域,其分别表示该物体的各个部位,比如假设该RoI中含有的目标是人,K=3,那么就将“人”划分成了9个子区域,top-center区域毫无疑问应该是人的头部,而bottom-center应该是人的脚部,我们将RoI划分为KK个子区域是希望这个RoI在其中的每一个子区域都应该含有该类别C的物体的各个部位,即如果是人,那么RoI的top-center区域就应该含有人的头部。当所有的子区域都含有各自对应的该物体的相应部位后,那么分类器才会将该RoI判断为该类别。也就是说物体的各个部位和RoI的这些子区域是“一一映射”的对应关系。一个RoI必须是KK个子区域都含有该物体的相应部位,我们才能判断该RoI属于该物体,如果该物体的很多部位都没有出现在相应的子区域中,那么就该RoI判断为背景类别。这就是为啥要在最后把一个类别的kk个概率加起来,就是要算k*k个位置的综合得分情况。

position-sensitive score map设计的核心思想就是如何让其能够反映一个RoI的 KK个子区域都含有相应部位。R-FCN会在共享卷积层的最后一层网络上接上一个卷积层,而该卷积层的输出位置敏感得分图position-sensitive score map,该score map的含义如下所述,首先它就是一层卷积层的输出,这个卷积层卷积核的height和width和前面共享卷积层的一样(即具有同样的感受野),但是它的通道个数(卷积核个数)为KK*(C+1) 。其中C表示物体类别种数,再加上1个背景类别,所以共有(C+1)类,而每个类别都有 KK个score map_2。卷积层使得ROI的通道数变为KK*(C+1)。 而后对ROI三维张量进行pool,变为11(kk(C+1))一列向量。对这列向量reshape即可得到 kk(C+1)的score map_2三维张量。每一和类别对应的KK个值,对应其在原图上的ROI的kk个位置包含该类目标的可能性。

只针对其中的一个类别来进行说明,假设我们的目标属于人这个类别,那么其有 KK 个score maps,每一个score map表示原始图像中的对应位置含有人的某个部位的概率,该score map会在真实含有对应的人体的某个部位的位置有高的响应值,也就是说每一个score map都是用来描述人体的其中一个部位出现在该score map的何处,而在出现的地方就有高响应值。既然是这样,那么我们只要将RoI的各个子区域对应到属于人的每一个score map(一个11*(C+1)的列向量的一个数)上然后获取它对不同类别(C+1)的响应值就可以判断这个位置含有每类物体的某个部位的相对置信程度。但是要注意的是,由于一个score map都是只属于一个类别的一个部位的,所以RoI的第 i个子区域一定要到kk中的第i张score map上去寻找对应区域的响应值,因为RoI的第i个子区域需要的部位和第i张score map关注的部位是对应的,这种对应关系就是我们要让网络去学习的东西。那么现在该RoI的KK个子区域都已经分别在属于人的KK个score maps上找到其响应值了,那么如果这些响应值都很高,那么就证明该RoI是人。我们只是在属于人的 KK个score maps上找响应值,还没有到属于其它类别的score maps(KK)上找响应值,万一该RoI的各个子区域在属于其它类别的上的score maps的响应值也很高,那么该RoI就也有可能属于其它类别。这就会涉及到一个比较的问题,哪个类别score maps(KK)的综合响应值高,我就将它判断为哪一类目标。

2、Position-sensitive ROI Pooling ——先横面划片,再纵向划片,把选中的三维张量平均池化为一个列向量:

R-FCN的网络结构图,score map_1 和score map_2, _2的每一个点称为score map
怎么使得ROl的K*K个子区域在各个类别的score maps上找到其每个子区域的响应值的?这就是位置敏感Rol池化操作(Position-sensitive RoI pooling),其字面意思是池化操作是位置敏感的。ROI的左上角区域和Score map_左上角的score map对应关系是怎么建立起来的?

通过RPN提取出来的RoI区域,其是包含坐标信息(x,y,w,h)。首先不同的RoI区域能够对应到score map_1的不同位置上,图中标出来的“ROI”(【KK(C+1)】nn)多个ROI中的一个ROI。每一个RoI会被划分成KK个bins(也就是子区域。每个子区域bin的长宽分别是 h/k 和 w/k ),此时ROI的维度是(kk个大小为【KK(C+1)n/kn/k】的三维张量),每个bin(共kk个)都对应到score map_2上的对应区域(KK个(C+1)列向量中的一个)。既然该RoI的每个bin都对应到score map_2上的某一个子区域,那么池化操作就是在该bin对应的score map_1上的子区域((C+1)n/kn/k的三维张量)执行,得到score map_2中的一个子区域((C+1)11)且执行的是平均池化。我们在前面已经讲了,第i个bin应该在第i个score map上寻找响应值,那么也就是在第i个score map上的第i个bin对应的位置上进行平均池化操作。由于我们有(C+1)个类别,所以每个类别都要进行相同方式的池化操作。即在原ROI三维张量中,俯视看,9个位置分9个三维张量,每一个位置(共9个)对应一个(kk(C+1))n/kn/k 的三维张量,只选择它被划分成的9=k*k段中的1段(C+1)n/kn/k大小的三维张量,进行池化得到score map_2中的一个列向量((C+1)11)。

上图已经很明显的画出了池化的方式,对于每个类别,它都有KK个score map,那么按照上述的池化方式,ROI可以针对该类别可以获得KK个值,那么一共有(C+1)个类别,那么一个RoI就可以得到KK(C+1)个值,就是上图的score map_2特征图。那么对于每个类别,该类别的KK个值都表示该RoI(不同位置)属于该类别的响应值,那么将这KK个数相加就得到该类别的score,那么一共有(C+1)个scores,那么在这(C+1)个数上面使用简单的softmax函数就可以得到各个类别的概率了(注意,这里不需要使softmax分类器了,只需要使用简答的softmax函数,因为这里就是通过简单的比大小来判断最终的类别的)。

3、R-FCN 算法具体步骤:

在这里插入图片描述
网络结构:首先输入图像经过一个全卷积网络(比如ResNet),然后一方面在最后一个卷积层后面添加特殊的卷积层(控制feature map的维度)生成position-sensitive score map的备用特征图,另一方面全卷积网络的某个卷积层(可能是最后一个卷积层)输出作为RPN网络的输入,RPN网络最后生成ROI。最后的ROI Pooling层将前面的socre map和ROI作为输入(在备用特征图中找到roil对应区域进行ROI Pooling,其本质是对特选部分平均池化),得到score map,取平均后输出类别信息。另外回归部分和分类部分是并列的。

(1)首先,选择一张需要处理的图片,并对这张图片进行相应的预处理操作;

(2)接着,我们将预处理后的图片送入一个预训练好的分类网络中(这里使用了ResNet-101网络的Conv4之前的网络),固定其对应的网络参数;

(3)接着,在预训练网络的最后一个卷积层获得的feature map后存在3个分支:

1)第1个分支就是在该feature map上面进行RPN操作,获得相应的ROI位置信息;

2)第2个分支是在该ROI对应的feature map上获得一个 KK(C+1)*原面积 维的position-sensitive score map;

3)第3个分支在该ROI对应的feature map上获得一个 4KK*原面积 维的位置敏感得分映射;

(4)最后,在深度为KK(C+1)维的分类score map_1和深度为4KK维的定位score map_1上面分别执行Position-Sensitive ROI pooling操作(这里使用的是平均池化操作),分别得到分类和定位的score map_2,再分别进行VOTE取均值化三维张量为列向量,最后通过softmax函数和计算offset分别获得对应的类别和位置信息。

position-sensitive score map中的每个 (kk(C+1))nn 大小的ROI进行ROI pooling后会得到kk(C+1)大小的输出,这个输出进行vote操作得到C+1维的输出,这个vote操作就是一个均值操作。最后再连接一个softmax层输出每一类的概率。回归支路和分类支路类似,只不过接的卷积层的卷积核数量不是k2(C+1)而是4*k2(代码中采用的是42k^2),因此在经过position-sensitive Roi Pooling后得到4kk维度的输出,再经过vote操作得到411的输出,表示预测的bbox坐标offset。

4、Loss计算及其分析:

这个Loss就是两阶段目标检测框架常用的形式。包括一个分类Loss和一个回归Loss。lamdy参数作为权重用来平衡两者的重要性。对于任意一个RoI,需要计算它的softmax损失,和当其不属于背景时的回归损失。这很简单,因为每个RoI都被指定属于某一个GT box或者属于背景,即先选择和GT box具有最大重叠率(IOU)的Rol,然后在剩余的Rol中选择与GT box的重叠率值大于0.5Rol进行匹配操作,最后将剩余的Rol都归为背景类。即每个Rol都有了对应的标签,我们就可以根据监督学习常用的方法来训练它,把网络对图片的ROI生成这一步训练的越来越精准。

5、online hard example mining:

这个方法是目标检测框架中经常会用到的一个tricks,其主要的思路如下所示:首先对RPN获得的候选ROI(正负样本分别进行排序)进行排序操作;然后在含有正样本(目标)的ROI中选择前N个ROI,将正负样本的比例维持在1:3的范围内,基本上保证每次抽取的样本中都会含有一定的正样本,都可以通过训练来提高网络的分类能力。如果不进行此操作的话,很可能会出现抽取的所有样本都是负样本(背景)的情况,这样让网络学习这些负样本,会影响网络的性能。

6、Rols预筛选:

为了过滤背景Rols使用的方法在测试的时候,为了减少RoIs的数量,作者在RPN提取阶段就对RPN提取的大约2W个proposals进行了过滤,方法如下所示,去除超过图像边界的proposals;使用基于类别概率且阈值IoU=0.7的NMS过滤;按照类别概率选择top-N个proposals;所以在测试的时候,最后一般只剩下300左右个RoIs,当然这个数量是一个超参数。并且在R-FCN的输出300个预测框之后,仍然要对其使用NMS去除冗余的预测框。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!