【转】R-FCN解析
转自:https://blog.csdn.net/WZZ18191171661/article/details/79481135
论文题目:R-FCN: Object Detection via Region-based Fully Convolutional Networks
论文链接:论文链接
论文代码:Caffe版本链接地址;Python版本链接地址;Deformable R-FCN版本链接地址
一、R-FCN初探
1. R-FCN贡献
- 提出Position-sensitive score maps来解决目标检测的位置敏感性问题;
- 区域为基础的,全卷积网络的二阶段目标检测框架;
-
比Faster-RCNN快2.5-20倍(在K40GPU上面使用ResNet-101网络可以达到 0.17 sec/image);
我在很多相关的检测论文中都看到这两个概念,但是一直都没有理解其真正的含义,相信很多朋友们也有同样的困惑,所以我在这里解释一下。
Faster R-CNN是首个利用CNN来完成proposals预测的,从此之后很多的目标检测网络都开始使用Faster R-CNN的思想。而Faster R-CNN系列的网络都可以分成2个部分:ROI Pooling之前的共享全卷积网络和ROI Pooling之后的ROI-wise子网络(用来对每个ROI进行特征提出,并进行回归和分类)。第1部分就是直接用普通分类网络的卷积层,用来提取共享特征,然后利用ROI Pooling在最后一层网络形成的feature map上面提取针对各个RoIs的特征向量,然后将所有RoIs的特征向量都交给第2部分来处理(即所谓的分类和回归),而第二部分一般都是一些全连接层,在最后有2个并行的loss函数:softmax和smoothL1,分别用来对每一个RoI进行分类和回归,这样就可以得到每个RoI的真实类别和较为精确的坐标信息啦(x, y, w, h)。
需要注意的是第1部分通常使用的都是像VGG、GoogleNet、ResNet之类的基础分类网络,这些网络的计算都是所有RoIs共享的,在一张图片上面进行测试的时候只需要进行一次前向计算即可。而对于第2部分的RoI-wise subnetwork,它却不是所有RoIs共享的,主要的原因是因为这一部分的作用是“对每个RoI进行分类和回归”,所以不能进行共享计算。那么问题就处在这里,首先第1部分的网络具有“位置不敏感性”,而如果我们将一个分类网络比如ResNet的所有卷积层都放置在第1部分用来提取特征,而第2部分则只剩下全连接层,这样的目标检测网络是位置不敏感的translation-invariance,所以其检测精度会较低,而且这样做也会浪费掉分类网络强大的分类能力(does not match the network's superior classification accuracy)。而ResNet论文中为了解决这个问题,做出了一点让步,即将RoI Pooling层不再放置在ResNet-101网络的最后一层卷积层之后而是放置在了“卷积层之间”,这样RoI Pooling Layer之前和之后都有卷积层,并且RoI Pooling Layer之后的卷积层不是共享计算的,它们是针对每个RoI进行特征提取的,所以这种网络设计,其RoI Pooling层之后就具有了位置敏感性translation-variance,但是这样做会牺牲测试速度,因为所有的RoIs都需要经过若干层卷积计算,这样会导致测试速度很慢。R-FCN就是针对这个问题提出了自己的解决方案,在速度和精度之间进行折中。
二、R-FCN架构分析
1. R-FCN算法步骤
图3 R-FCN算法步骤
如图所示,我们先来分析一下R-FCN算法的整个运行步骤,使得我们对整个算法有一个宏观的理解,接下来再对不同的细节进行详细的分析。
- 首先,我们选择一张需要处理的图片,并对这张图片进行相应的预处理操作;
- 接着,我们将预处理后的图片送入一个预训练好的分类网络中(这里使用了ResNet-101网络的Conv4之前的网络),固定其对应的网络参数;
- 接着,在预训练网络的最后一个卷积层获得的feature map上存在3个分支,第1个分支就是在该feature map上面进行RPN操作,获得相应的ROI;第2个分支就是在该feature map上获得一个K*K*(C+1)维的位置敏感得分映射(position-sensitive score map),用来进行分类;第3个分支就是在该feature map上获得一个4*K*K维的位置敏感得分映射,用来进行回归;
- 最后,在K*K*(C+1)维的位置敏感得分映射和4*K*K维的位置敏感得分映射上面分别执行位置敏感的ROI池化操作(Position-Sensitive Rol Pooling,这里使用的是平均池化操作),获得对应的类别和位置信息。
这样,我们就可以在测试图片中获得我们想要的类别信息和位置信息啦。
2. Position-Sensitive Score Map解析
图3是R-FCN的网络结构图,其主要设计思想就是“位置敏感得分图position-sensitive score map”。现在我们来解释一下其设计思路。如果一个RoI中含有一个类别C的物体,我们将该RoI划分为K*K 个区域,其分别表示该物体的各个部位,比如假设该RoI中含有的目标是人,K=3,那么就将“人”划分成了9个子区域,top-center区域毫无疑问应该是人的头部,而bottom-center应该是人的脚部,我们将RoI划分为K*K个子区域是希望这个RoI在其中的每一个子区域都应该含有该类别C的物体的各个部位,即如果是人,那么RoI的top-center区域就应该含有人的头部。当所有的子区域都含有各自对应的该物体的相应部位后,那么分类器才会将该RoI判断为该类别。也就是说物体的各个部位和RoI的这些子区域是“一一映射”的对应关系。
OK,现在我们知道了一个RoI必须是K*K个子区域都含有该物体的相应部位,我们才能判断该RoI属于该物体,如果该物体的很多部位都没有出现在相应的子区域中,那么就该RoI判断为背景类别。那么现在的问题就是网络如何判断一个RoI的 K*K个子区域都含有相应部位呢?前面我们是假设知道每个子区域是否含有物体的相应部位,那么我们就能判断该RoI是否属于该物体还是属于背景。那么现在我们的任务就是判断RoI子区域是否含有物体的相应部位。
这其实就是position-sensitive score map设计的核心思想了。R-FCN会在共享卷积层的最后一层网络上接上一个卷积层,而该卷积层就是位置敏感得分图position-sensitive score map,该score map的含义如下所述,首先它就是一层卷积层,它的height和width和共享卷积层的一样(即具有同样的感受野),但是它的通道个数为K*K*(C+1) 。其中C表示物体类别种数,再加上1个背景类别,所以共有(C+1)类,而每个类别都有 K*K个score maps。现在我们只针对其中的一个类别来进行说明,假设我们的目标属于人这个类别,那么其有 K*K 个score maps,每一个score map表示原始图像中的哪些位置含有人的某个部位,该score map会在含有对应的人体的某个部位的位置有高的响应值,也就是说每一个score map都是用来描述人体的其中一个部位出现在该score map的何处,而在出现的地方就有高响应值”。既然是这样,那么我们只要将RoI的各个子区域对应到属于人的每一个score map上然后获取它的响应值就好了。但是要注意的是,由于一个score map都是只属于一个类别的一个部位的,所以RoI的第 i个子区域一定要到第i张score map上去寻找对应区域的响应值,因为RoI的第i个子区域需要的部位和第i张score map关注的部位是对应的。那么现在该RoI的K*K个子区域都已经分别在属于人的K*K个score maps上找到其响应值了,那么如果这些响应值都很高,那么就证明该RoI是人呀。当然这有点不严谨,因为我们只是在属于人的 K*K个score maps上找响应值,我们还没有到属于其它类别的score maps上找响应值呢,万一该RoI的各个子区域在属于其它类别的上的score maps的响应值也很高,那么该RoI就也有可能属于其它类别呢?是吧,如果2个类别的物体本身就长的很像呢?这就会涉及到一个比较的问题,那个类别的响应值高,我就将它判断为哪一类目标。它们的响应值同样高这个情况发生的几率很小,我们不做讨论。
OK,这就是position-sensitive score map的全部思想了,应该很容易理解了吧。
3. Position-Sensitive Rol Pooling解析
上面我们只是简单的讲解了一下ROl的K*K个子区域在各个类别的score maps上找到其每个子区域的响应值,我们并没有详细的解释这个“找到”是如何找的?这就是位置敏感Rol池化操作(Position-sensitive RoI pooling),其字面意思是池化操作是位置敏感的,下来我们对它进行解释说明。
5. 为什么position-sensitive score map能够在含有某个类别的物体的某个部位的区域上具有高响应值?
这种有高响应值现在只是作者自己设想的啊,如果网络不满足这一点的话,那么我们前面的所有分析都不成立啦。现在我们就大致解释一下为什么训练该网络能够让网络最终满足这一点。首先根据网络的loss计算公式,如果一个RoI含有人这个物体,那么该RoI通过position-sensitive score map和Position-sensitive RoI pooling得到的(C+1)个值中属于人的那个值必然会在softmax损失函数的驱动下变得尽量的大,那么如何才能使得属于人的这个值尽量的大呢?那么我们需要想想属于人的这个预测值是怎么来的?经过前面的分析,我们已经知道它是通过Position-sensitive RoI pooling这种池化操作获得的,那么也就是说使得(C+1)个值中属于人的那个值尽量大,必然会使得position-sensitive score map中属于人的那个score map上的RoI对应的位置区域的平均值尽量大,从而会使得该score map上在该区域上的响应值尽量大,因为只有该区域的响应值大了,才能使得预测为人的概率大,才会降低softmax的loss,整个训练过程才能进行下去。
图5 位置敏感得分映射表现1
图6 位置敏感得分映射表现2
6. Loss计算及其分析
这个Loss就是两阶段目标检测框架常用的形式。包括一个分类Loss和一个回归Loss。lamdy用来平衡两者的重要性。对于任意一个RoI,我们需要计算它的softmax损失,和当其不属于背景时的回归损失。这很简单,因为每个RoI都被指定属于某一个GT box或者属于背景,即先选择和GT box具有最大重叠率(IOU)的Rol,然后在剩余的Rol中选择与GT box的重叠率值大于0.5Rol进行匹配操作,最后将剩余的Rol都归为背景类。即每个Rol都有了对应的标签,我们就可以根据监督学习常用的方法来训练它啦。
7. online hard example mining
这个方法是目标检测框架中经常会用到的一个tricks,其主要的思路如下所示:首先对RPN获得的候选ROI(正负样本分别进行排序)进行排序操作;然后在含有正样本(目标)的ROI中选择前N个ROI,将正负样本的比例维持在1:3的范围内,基本上保证每次抽取的样本中都会含有一定的正样本,都可以通过训练来提高网络的分类能力。如果不进行此操作的话,很可能会出现抽取的所有样本都是负样本(背景)的情况,这样让网络学习这些负样本,会影响网络的性能。(这完全是我个人的理解,哈哈哈)
8. Atrous algorithm(Dilated Convolutions或者膨胀卷积)
图7 膨胀卷积
这个方法同样也是目标检测中常用的一个tricks,其最主要的目的是可以在减小卷积步长的同时扩大feature map的大小,即同等情况下,通过这个操作,我们可以获得一个更大的feature map,而实验表明,大的feature map会提升检测的性能。具体的解释可以去看这个链接。上图是一个膨胀卷积的操作,通过几次操作,我们可以看到我们的接收场在不断的扩大,具体的解释请看英文吧。
9. 为了过滤背景Rols使用的方法
在测试的时候,为了减少RoIs的数量,作者在RPN提取阶段就对RPN提取的大约2W个proposals进行了过滤,方法如下所示,
- 去除超过图像边界的proposals;
- 使用基于类别概率且阈值IoU=0.7的NMS过滤;
- 按照类别概率选择top-N个proposals;
所以在测试的时候,最后一般只剩下300左右个RoIs,当然这个数量是一个超参数。并且在R-FCN的输出300个预测框之后,仍然要对其使用NMS去除冗余的预测框。
10. 训练细节
R-FCN和Faster R-CNN采取了同样的训练策略,具体的训练策略可以参考这篇博客。
11. 图片中的ROI和特征上的ROI之间的映射关系
如果你不清楚它们是如何映射的,请查看这个链接。
三、R-FCN性能分析
1. 定量结果分析
表1 使用ResNet-101全卷积策略
如上表所示,作者测试了不同大小的ROI对性能的影响(我们使用了预训练的ResNet-101网络,在VOC 07数据集上面进行测试),我们可以看到如果使用1x1的ROI,显示输出失败,具体原因不得而知。当使用7x7的ROI时,能够获得最好的结果,这也是论文中最终使用7x7大小的ROI的原因吧,作者应该是做了很多的验证工作。
表2 Faster R-CNN与R-FCN性能比较
如上表所示,我们比较了Faster R-CNN和R-FCN的性能,从表中我们可以看出与Faster R-CNN相比,R-FCN有更快的运行速度,大概是2.5倍以上。另外,我们可以发现性能稍微有一点点提升,当调整ROI的个数时,我们发现300个ROI时能够获得最好的性能。
表3 预训练网络的深度对性能的影响
如上表所示,随着预训练网络层数的加深,我们的检测性能在不断的得到提高,使用VGG和ResNet网络还是有很大的性能差异,但是过深的网络并没有提高其性能,可能的原因是我们的网络发生了过拟合情况。
表4 COCO数据集的训练结果
如上表所示,我们采用了COCO数据集进行性能验证,与Faster R-CNN相比,R-FCN可以实现3倍的加速,准确率可以提升2个百分点。
2. 定性结果分析
图9 COCO检测结果
以上是R-FCN算法在VOC2007和COCO数据集上面的性能表现,总体上看效果还是挺不错的,具体的效果需要你自己去尝试,根据自己的需求去选择合适的算法。
四、总结
总的来讲,和Faster R-CNN相比,R-FCN具有更快的运行速度(2.5倍以上),稍微提高了一点检测精度,在速度和准确率之间进行了折中,提出position-sensitive score map来解决检测的位置敏感性问题。算法中的很多细节值得我们进行深入的研究和分析,希望你从中学到了很多有用的东西。
参考文献:
[1] R-FCN对应的poster,相关链接;
[2] VGG Reading Group - Sam Albanie ,参考链接,密码:hby1;
[3] 详解R-FCN,博客链接;