【目标检测算法】R-FCN学习笔记

R-FCN的idea出发点(关键思想)https://www.jianshu.com/p/409fd61db9db

  • 分类需要特征具有平移不变性,检测则要求对目标的平移做出准确响应。现在的大部分CNN在分类上可以做的很好,但用在检测上效果不佳。SPP,Faster R-CNN类的方法在ROI pooling前都是卷积,是具备平移不变性的,但一旦插入ROI pooling之后,后面的网络结构就不再具备平移不变性了。因此,本文想提出来的position sensitive score map这个概念是能把目标的位置信息融合进ROI pooling。

图像分类中的平移不变性:

在用基础的分类结构比如ResNet,Inception给一只猫分类时,无论猫怎么扭曲、平移,最终识别出来的都是猫,输入怎么变形,输出都不变,就是平移不变形。网络的层次越深这个特性会越明显。

目标检测中的平移变换性:

一只猫从图片左侧移到了图片右侧,检测出的猫的坐标会发生变化就称为平移可变性。

当卷积网络变深后最后一层卷积输出的feature map变小,物体在输入上的小偏移,经过N多层pooling后在最后的小feature map上会感知不到,即网络变深平移可变性变差。


链接:https://zhuanlan.zhihu.com/p/30867916
这篇论文是NIPS 2016的一篇论文,主要贡献在于解决了“分类网络的位置不敏感性(translation-invariance in image classification)”与“检测网络的位置敏感性(translation-variance in object detection)”之间的矛盾,在提升精度的同时利用“位置敏感得分图(position-sensitive score maps)”提升了检测速度。

基于ResNet-101的R-FCN在PASCAL VOC 2007的测试集上的mAP=83.6%,速度为170ms per image

动机

Faster R-CNN是首个利用CNN来完成proposals的预测的,之后的很多目标检测网络都是借助了Faster R-CNN的思想。而Faster R-CNN系列的网络都可以分成2个部分:

  1. Fully Convolutional subnetwork before RoI Layer
  2. RoI-wise subnetwork

第1部分就是直接用普通分类网络的卷积层,用其来提取共享特征,然后一个RoI Pooling Layer在第1部分的最后一张特征图上进行提取针对各个RoIs的特征向量(或者说是特征图,维度变换一下即可),然后将所有RoIs的特征向量都交由第2部分来处理(分类和回归),而第二部分一般都是一些全连接层,在最后有2个并行的loss函数:softmax和smoothL1,分别用来对每一个RoI进行分类和回归,这样就可以得到每个RoI的真实类别和较为精确的坐标和长宽了。

这里要注意的,第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 Layer不再放置在ResNet-101网络的最后一层卷积层之后而是放置在了“卷积层之间”,这样RoI Pooling Layer之前和之后都有卷积层,并且RoI Pooling Layer之后的卷积层不是共享计算的,它们是针对每个RoI进行特征提取的,所以这种网络设计,其RoI Pooling Layer之后就具有了“位置敏感性translation-variance”,但是这样做牺牲了测试速度,因为所有RoIs都要经过若干层卷积计算,测试速度会很慢。】

那么到底怎么办?要精度还是要速度?R-FCN的回答是:都要!!!

网络设计

  • position-sensitive score map

这张图就是R-FCN的网络结构图,其主要设计思想就是“位置敏感得分图position-sensitive score map”。现在就对着这张图来解释其设计思路。如果一个RoI含有一个类别c的物体,那么作者将该RoI划分为 k\times k 个区域,分别表示该物体的各个部位,比如假设该RoI中含有人这个物体,k=3,那么就将“人”划分为了9个子区域,top-center区域毫无疑问应该是人的头部,而bottom-center应该是人的脚部,而将RoI划分为 k\times k 个区域是希望这个RoI在其中的每一个区域都应该含有该类别c的物体的各个部位,即如果是人,那么RoI的top-center区域就必须含有人的头部。而当这所有子区域都含有各自对应的该物体的相应部位后,那么分类器才会将该RoI判断为该类别。物体的各个部位和RoI的这些子区域是“一一映射”的对应关系。(这就像《游戏王》中的对黑暗大法师的召唤一样,要集齐5张被封印的部位才能召唤出黑暗大法师)

好了,现在我们知道了一个RoI必须是 k\times k 个子区域都含有该物体的相应部位,才能判断该RoI属于该物体,如果该物体的很多部位都没有出现在相应的子区域中,那么就判断该RoI为背景类别。那么现在的问题就是“网络如何判断一个RoI的 k\times k 个子区域都含有相应部位呢?”前面我们是假设知道每个子区域是否含有物体的相应部位,那么我们就能判断该RoI是否属于该物体还是属于背景。那么现在的任务就是“判断RoI子区域是否含有物体的相应部位”。

这就是position-sensitive score map设计的核心思想了。R-FCN会在共享卷积层的最后再接上一层卷积层,而该卷积层就是“位置敏感得分图position-sensitive score map”,score map是什么意义呢?首先它就是一层卷积层,它的height和width和共享卷积层的一样,但是它的channels= k^{2}(C+1)如上图所示。那么C表示物体类别种数再加上1个背景类别,每个类别都有 k^{2}个score maps。现在我们先只针对其中的一个类别来讨论,假设是人这个类别,那么其有 k^{2} 个score maps,每一个score map表示“原图image中的哪些位置含有人的某个一个部位”,而该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\times k 个子区域都已经分别到“属于人的 k^{2} 个score maps”上找到其响应值了,那么如果这些响应值都很高,那么就证明该RoI是人呀~对吧。不过,当然这有点不严谨,因为我们只是在“属于人的 k^{2} 个score maps”上找响应值,我们还没有到属于其它类别的score maps上找响应值呢,万一该RoI的各个子区域在属于其它类别的上的score maps的响应值也很高,那么该RoI就也有可能属于其它类别呢?是吧,万一2个类别的物体本身就长的很像呢?所以呢,当然就是看那个类别的响应值更高了。

  • Position-sensitive RoI pooling

上一部分,我们只是简单的讲了下“RoI的 k\times k 个子区域在各个类别的score maps上找到其每个子区域的响应值”,我们并没有详细讲这个“找到”是如何“找”的呢?这就是这一部分的“位置敏感RoI池化操作了(Position-sensitive RoI pooling)”,字面意思理解就是“池化操作是位置敏感的”,现在就来解释“池化操作是怎么个位置敏感法”。

看这图,通过RPN提取出来的RoI区域,其是包含了“坐标、长宽”的4值属性的,也就是说不同的RoI区域能够对应到score map的不同位置上,而一个RoI会分成 k\times k 个bins(也就是子区域。每个子区域bin的长宽分别是 \frac{h}{k}\frac{w}{k} ),每个bin都对应到score map上的某一个区域(上图已经很明显的画出来了)。那么好既然该RoI的每个bin都对应到score map上的某一个子区域,那么池化操作就是在该bin对应的score map上的子区域执行,且执行的是平均池化。我们在上一部分已经讲了i 个bin应对在第 i 个score map上找响应值,那么也就是在第 i 个score map上的“该第 i 个bin对应的位置”上进行池化操作,且池化是取“bin这个范围内的所有值的平均值”并且由于有 C+1 个类别,所以每个类别都要进行相同方式的池化。(下图的公式就是池化操作的计算方式)

上图已经很明显的画出了池化的方式,对于每个类别,它都有 k^{2} 个score maps,那么按照上述的池化方式,RoI针对该类别可以得到 k^{2} 个值,那么一共有 C+1 个类别,那么一个RoI就得到 k^{2}(C+1) 个值就是上图的“channels= C+1 ,size= k\times k ”的特征图。(第二个)

那么对于每个类别,该类别的 k^{2} 个值都表示该RoI属于该类别的响应值,那么将这 k^{2} 个数相加就得到该类别的score,那么一共有 C+1 个scores,那么将这 C+1 个数使用简单的softmax函数就可以得到属于各个类别的概率了。

(注意,这里不需要使softmax分类器了,只需要使用简单的softmax函数,因为这里就是通过简单的比大小来判断最终的类别的,下图的2个公式已经写的很清楚了)。

  • position-sensitive regression

前面的“position-sensitive score map”+“Position-sensitive RoI pooling”得到的值是用来分类的,那么自然就有相应的操作得到的值用来回归。按照“position-sensitive score map”+“Position-sensitive RoI pooling”思路,其会让每一个RoI得到 C+1 个数作为每个类别的score,那么现在每个RoI还需要 4 个数作为“回归的偏移量”,也就是“坐标和长宽”的偏移量,所以仿照分类设计的思想,还需要一个类似于position-sensitive score map的用于回归的score map。那么现在就这样设计:

(1)在ResNet的共享卷积层的最后一层上,接上一个与position-sensitive score map并行的(sibling)score maps,该score maps用于regression,暂且命名为“regression score map”,而该regression score map的维度应当是 4k^{2} ,那么在经过Position-sensitive RoI pooling操作后,每一个RoI就会得到 4 个数作为“该RoI的坐标和长宽的偏移量”了。(不懂!!!

(2)对于坐标分支,可以理解成C不再是类别数而是坐标参数C=4。表示9个小区域的 [dx,dy,dw,dh] 4个偏移坐标。

(3)对于目标定位的输出和上面的分类输出过程类似,只是维度不再是k2 * (C+1),而是k2*4,表示9个小区域的[dx,dy,dw,dh]4个偏移坐标。

 

https://www.jianshu.com/p/409fd61db9db

理解难点1:平移不变性和平移可变性

理解难点2:R-FCN结构的由来

理解难点3:Position-sensitive score map的结构

理解难点4:Position-sensitive score map为什么会带来平移可变性

 

 

训练:

训练的样本选择策略:online hard example mining(OHEM)。主要思想就是对样本按loss进行排序,选择前面loss较小的,这个策略主要用来对负样本进行筛选,使得正负样本更加平衡。

 

测试:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值