RCNN Fast R-CNN Faster R-CNN总结(学习笔记)

最近开始系统性地学习目标检测算法,阅读地第一篇就是领域内大名鼎鼎的RCNN系列,整个学习过程颇为不易,也遇到很多难以理解的地方,特别是对于Faster RCNN中的anchor box部分,这部分说实话我想了很久哈哈哈,也没日没夜地查找了很多网上的资源,很感激这些博主能够将自己的深刻见解写成博文供大家学习,因此这里也将我本人学习过程中的一些感想、阅读过的资源分享出来给大家,希望能够帮到各位。

注:本文需要结合RCNN系列原论文进行理解,适合读过一遍论文但是仍然不能完全理解RCNN、FastRCNN以及FasterRCNN思想或概念的同学们:D

RCNN

b站原理简单讲解

这个R-CNN论文讲解视频讲得还可以,大部分地方都没啥问题。

RCNN系列原理详解博客

步骤:

  • 一张图像生成1k~2k个候选区域(Selective Search方法)
  • 对每个候选区域,使用深度网络提取特征
  • 特征送入每一类的SVM分类器,判断是否属于该类
  • NMS(非极大值抑制)
  • 使用回归器精细修正候选框位置

image-20231111193724683

selective search

大概了解即可,这篇讲得可以。

作者在原文中提到,对于进行所有实验,其采用的都是SS法的快速模式。

Feature extraction

AlexNet的前七层

affine image warping

将建议的区域大小转换为匹配CNN的输入(227 × 227)。作者评估了三种方案,包括各向同性缩放(先扩充后裁剪&先裁剪后扩充)以及各向异性缩放。参照这篇博客

各向异性缩放:
这种方法很简单,就是不管图片的长宽比例,管它是否扭曲,进行缩放就是了,全部缩放到CNN输入的大小227×227,如下图D所示。

各项同性缩放:
因为图片扭曲后,估计会对后续CNN的训练精度有影响,于是作者也测试了“各向同性缩放”方案。有两种办法:

先扩充后裁剪
直接在原始图片中,把bounding box的边界进行扩展延伸成正方形,然后再进行裁剪;如果已经延伸到了原始图片的外边界,那么就用bounding box中的颜色均值填充;如下图B所示;

先裁剪后扩充
先把bounding box图片裁剪出来,然后用固定的背景颜色填充成正方形图片(背景颜色也是采用bounding box的像素颜色均值),如下图C所示。

对于上面的异性、同性缩放,文献还有个padding处理,示意图中第1、3行就是结合了padding=0,第2、4行结果图则是采用padding=16的结果。经过最后的试验,作者发现采用各向异性缩放、padding=16的精度最高

image-20231112145504713

CNN

在ILSVRC2012上完成预训练的Alexnet网络模型。为了让模型适应新任务(目标检测)以及warp后的图像输入,仅使用warped region proposals对预训练后的CNN进行SGD训练。使用N+1分类层(N类目标+背景图像块)替代了Alexnet之前的1000个最终分类层。以0.001的学习率(预训练时学习率的1/10)来启动SGD。

样本选取

将所有与ground truth的IOU≥0.5的region proposals视为正样本,并将其余的视为负样本。由于正负样本的不平衡性(负样本太多了),所以在SGD的每批次迭代中,都采用将32个正样本(所有类别)和96个背景样本作为一个批次来输入至神经网络中。

SVM

样本选取

将所有与ground truth的IOU≤0.3(这个阈值通过网格搜索得到)的region proposals视为负样本,并将ground truth的BB视为正样本。

由于训练数据太大,所以采用难例挖掘方法训练SVM。

也可以参考这篇RCNN详解

Let’s say I give you a bunch of images that contain one or more people, and I give you bounding boxes for each one. Your classifier will need both positive training examples (person) and negative training examples (not person).
For each person, you create a positive training example by looking inside that bounding box. But how do you create useful negative examples?
A good way to start is to generate a bunch of random bounding boxes, and for each that doesn’t overlap with any of your positives, keep that new box as a negative.
Ok, so you have positives and negatives, so you train a classifier, and to test it out, you run it on your training images again with a sliding window. But it turns out that your classifier isn’t very good, because it throws a bunch of false positives (people detected where there aren’t actually people).
A hard negative is when you take that falsely detected patch, and explicitly create a negative example out of that patch, and add that negative to your training set. When you retrain your classifier, it should perform better with this extra knowledge, and not make as many false positives.

a) Positive samples: apply the existing detection a t all positions and scales with a 50% overlap wit h the given bounding box and then select the hi ghest scoring placement.
b) Negative samples:

hard negative, selected by finding high scoring detections in images not co ntaining the target object.

问题一:微调阶段和SVM阶段阈值不同的原因?

微调阶段是由于CNN对小样本容易过拟合,需要大量训练数据,故对IoU限制宽松:Ground Truth+与Ground Truth相交IoU>0.5的建议框为正样本,否则为负样本;SVM这种机制是由于其适用于小样本训练,故对样本IoU限制严格(负样本和正样本的限制都更加严格了):Ground Truth为正样本,与Ground Truth相交IoU<0.3的建议框为负样本。

问题二:为什么微调之后,训练SVM呢?简单地将最后一层微调网络(21路Softmax回归分类器)作为对象检测器不是更加简洁么?

因为微调时和训练SVM时所采用的正负样本阈值不同,微调阶段正样本定义并不强调精准的位置,而SVM正样本只有Ground Truth;并且微调阶段的负样本是随机抽样的,而SVM的负样本是经过hard negative mining方法筛选的,是更加严格的负样本;导致在采用SoftMax会使PSACAL VOC 2007测试集上mAP从54.2%降低到50.9%。(IoU大于0.5就作为正样本会导致网络定位准确度的下降,故使用了SVM来做检测,全部使用ground-truth样本作为正样本,且使用非正样本的,且IoU大于0.3的“hard negatives”,提高了定位的准确度。)

NMS

rejects a region if it has an intersection-overunion (IoU) overlap with a higher scoring selected region larger than a learned threshold.

边界框回归

边界框回归要设计4个不同的Ridge回归模型分别求解 w x w_x wx, w y w_y wy, w h w_h wh, w w w_w ww

RCNN训练和测试过程详解

可以看这篇博客,写得很详细

可视化

基于第5个池化层的输出来可视化。

具体步骤:

    直接可视化第一层filters非常容易理解,它们主要捕获方向性边缘和对比色。难以理解的是后面的层。Zeiler and Fergus提出了一种可视化的很棒的反卷积办法。我们则使用了一种简单的非参数化方法,直接展示网络学到的东西。这个想法是单一输出网络中一个特定单元(特征),然后把它当做一个正确类别的物体检测器来使用。
    方法是这样的,先计算所有抽取出来的推荐区域(大约1000万),计算每个区域所导致的对应单元的激活值,然后按激活值对这些区域进行排序,然后进行最大值抑制,最后展示分值最高的若干个区域。这个方法让被选中的单元在遇到他想激活的输入时“自己说话”。我们避免平均化是为了看到不同的视觉模式和深入观察单元计算出来的不变性。
    我们可视化了第五层的池化层pool5,是卷积网络的最后一层,feature_map(卷积核和特征数的总称)的大小是6 x 6 x 256 = 9216维。忽略边界效应,每个pool5单元拥有195×195的感受野,输入是227×227。pool5中间的单元,几乎是一个全局视角,而边缘的单元有较小的带裁切的支持。(理解1:也就是pool5的输出一共有256个特征,针对每一个特征,有6*6个单元,每个单元对应与输入的227*227的感受野是195*195,所以6*6个单元的中间单元几乎是原图227*227的全局视角,边缘单元有带剪裁的部分,此处可以忽略,在附录D中选取的就是pool5输出特征图每个通道上的(3,3)位置的单元)
    论文图4的每一行显示了对于一个pool5单元的最高16个激活区域情况,这个实例来自于VOC 2007上我们调优的CNN,这里只展示了256个单元中的6个(附录D包含更多)。我们看看这些单元都学到了什么。第二行,有一个单元看到狗和斑点的时候就会激活,第三行对应红斑点,还有人脸,当然还有一些抽象的模式,比如文字和带窗户的三角结构。这个网络似乎学到了一些类别调优相关的特征,这些特征都是形状、纹理、颜色和材质特性的分布式表示。而后续的fc6层则对这些丰富的特征建立大量的组合来表达各种不同的事物。

    (理解2:此步就是针对所有抽取出来的每张图2000个预选框区域,所有图像共1000万个预选框区域,计算每个区域所导致的选定pool5层单元的激活值,按照激活值对这些区域进行排序,使用非极大值抑制算法,展示激活值最高的16个区域,图3展示了256个特征中6个特征的每个特征16个激活值最高的区域)

    (理解3:此处的非极大值抑制的具体使用是,比如此处排序的是1000万个预选框区域的激活值,先选择激活值最大的预选框a,然后在剩下的预选框中,将与预选框a的IOU交并比大于一定阈值的预选框剔除,并将预选框a保存下来,然后在剩下的所有预选框中继续选择激活值最大的预选框b,并在剩下的预选框中,将与预选框b的IOU交并比大于一定阈值的预选框剔除,并将预选框b保存下来,以此往复,找到所有被保留下来的预选框。此处是展示前16个被保留下来的预选框区域)

    (理解4:说实在的非极大值抑制就是在同一图像同一物体周边的多个重复的预选框,选出最优的那一个,剔除,但可视化这里,最优的选取是根据想可视化单元的激活值大小)

Fast RCNN

论文讲解视频

Fast-RCNN简介

R-CNN缺点

  1. 多阶段的训练过程(CNN、SVM分类器、SVM回归器)
  2. 训练过程需要耗费大量的空间和时间(SVM基于神经网络提取到的特征进行训练,因此需要将特征存储在磁盘上)
  3. 检测速度太慢(对每一个候选区域都提取特征)

因此,Fast R-CNN为了解决R-CNN和SPPnet的缺点,拥有以下特点:

  1. 更高的检测精度(mAP衡量)
  2. 单阶段训练
  3. 训练可以更新所有的网络权重(SPPnet难以更新卷积层的权重)
  4. 不需要磁盘存储特征

SPPnet

SPP-net:R-CNN候选区域缩放后的畸变问题和提取特征时的重复计算导致了模型性能和速度的瓶颈。为了解决这些问题,2015年,何凯明等人提出了SPP-net,在保证性能的同时,检测速度也有了较大的提升,论文名字为” Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition”, 可从这里直接下载。

R-CNN需要对候选区域进行缩放的原因是全连接层的输入维度必须固定。整个网络包含底部的卷积层和顶部的全连接层,卷积层能够适应任意尺寸的输入图像,产生相应维度的特征图,但是全连接层不同,全连接层的参数是神经元对于所有输入的连接权重,即如果输入维度不固定,全连接层的参数数量也无法确定,网络将无法训练。为了既能固定全连接层的输入维度又不让候选区域产生畸变,很自然的想法就是在卷积层和全连接层的衔接处加入一个新的网络层,使得通过该层后特征的维度可以固定,在SPP-net中引入的 空间金字塔池化层(Spatial Pyramid Pooling Layer, SPP Layer) 就是这样一种网络层,SPP-net也因此得名。

这篇SPP Layer原理写得很好,其实SPP Layer之所以能够将不同大小(一般指长宽,因为通道数量是可以确定的)特征变成一样大小的特征,主要就是基于特征图的大小自适应计算得到最大池化层的参数,即池化核的大小(size)、步长(stride)以及填充(padding)。参照这个博客,计算公式如下:

在这里插入图片描述

在这里插入图片描述

此外,SPP-net也解决了R-CNN重复计算的问题。SPP-net的思路是由于原图与经过卷积层后得到的特征图在空间位置上存在一定的对应关系,所以只需对整张图像进行一次卷积层特征提取,然后将候选区域在原图的位置映射到卷积层的特征图上得到该候选区域的特征,最后将得到每个候选区域的卷积层特征输入到全连接层进行后续操作。

Fast R-CNN架构

Fig. 1 illustrates the Fast R-CNN architecture. A Fast R-CNN network takes as input an entire image and a set of object proposals. The network first processes the whole image with several convolutional (conv) and max pooling layers to produce a conv feature map. Then, for each object proposal a region of interest (RoI) pooling layer extracts a fixed-length feature vector from the feature map. Each feature vector is fed into a sequence of fully connected (fc) layers that finally branch into two sibling output layers: one that produces softmax probability estimates over K object classes plus a catch-all “background” class and another layer that outputs four real-valued numbers for each of the K object classes. Each set of 4 values encodes refined bounding-box positions for one of the K classes.

ROI Pooling Layer

SPP Layer的简化版,SPP Layer对每个候选区域使用了不同大小的金字塔映射,即SPP Layer采用多个尺度的池化层进行池化操作;而RoI Pooling Layer只需将不同尺度的特征图下采样到一个固定的尺度(例如7*7)。例如对于VGG16网络conv5_3有512个特征图,虽然输入图像的尺寸是任意的,但是通过RoI Pooling Layer后,均会产生一个7×7×512维度的特征向量作为全连接层的输入,即RoI Pooling Layer只采用单一尺度进行池化。

模型微调

原文中说到Fast RCNN能够使用反向传播来更新训练所有的网络权重,而SPPnet不能更新所有的权重,即卷积层的参数。(注意:这里其实不是说不能更新,而是由于在finetune的过程中反向传播非常低效所导致的更新速度非常非常非常慢。)

原论文对SPP net难以更新的解释:

The root cause is that back-propagation through the SPP layer is highly inefficient when each training sample (i.e. RoI) comes from a different image, which is exactly how R-CNN and SPPnet networks are trained. The inefficiency stems from the fact that each RoI may have a very large receptive field, often spanning the entire input image. Since the forward pass must process the entire receptive field, the training inputs are large (often the entire image).

来自知乎某个大佬的解释:RoI-centric sampling和image-centric sampling的区别:SPP-net是先把所有图像用SS计算的RoIs存起来,再从中每次随机选128个RoIs作为一个batch进行训练,这128个RoIs最坏的情况来自128张不同的图像,那么,要对128张图像都送入网络计算其特征,同时内存就要把128张图像的各层feature maps都记录下来(反向求导时要用),所以时间和空间上开销都比较大;而Fast R-CNN虽然也是SS计算RoIs,但每次只选2张图像的RoIs(一张图像上约2000个RoIs),再从中选128个作为一个batch,那么训练时只要计算和存储2张图像的Feature maps,所以时间和内存开销更小。

这里也提到了Fast R-CNN的采样方式:即,利用训练期间的特征共享。在Fast RCNN网络训练中,随机梯度下降(SGD)的小批量是被分层采样的,首先采样 N N N个图像,然后从每个图像中采样 R / N R/N R/N个 RoI。最关键的是,来自同一图像的RoI在向前和向后传播中共享计算和内存。减小 N N N就意味着减少了小批量的计算。例如,当 N = 2 N = 2 N=2 R = 128 R = 128 R=128时,得到的训练方案比从128幅不同的图采样一个RoI(即R-CNN和SPPnet的策略)快64倍。

多任务损失函数

Fast R-CNN统一了类别输出任务和边界框回归任务,其有两个损失函数:分类损失和回归损失。分类采用softmax代替SVM进行分类,共输出N(类别)+1(背景)类。softmax由于引入了类间竞争,所以分类效果优于SVM。而第二个输出为bbox回归,回归损失输出的是4*N(类别),4表示的是(x,y,w,h)。每个训练用的ROI都标记有真实类别u与groundtruth BB框v,采用多任务损失函数同时训练分类与边界框回归能力:

背景图像的u被设置为0,因此只有当BB中包含的目标不为背景时,才会计算回归损失 L l o c L_{loc} Lloc

小批样采样策略

每个SGD小批量由 N = 2 N=2 N=2个图像构成,每个图片中采样64个ROI,从与ground truth BB IOU值≥0.5的proposals中提取25%作为正样本,再选取和ground truth BB IOU值在[0.1,0.5)区间内的proposals作为负样本(难例挖掘)。此外,图像以0.5的概率水平翻转,不适用其它数据增强。

截断SVD

由于一张图像约产生2000个RoI,将近一半多的时间用在全连接层计算,为了提高运算速度,可以用SVD(奇异值分解)对全连接层进行变换来提高运算速度。一个大的矩阵可以近似分解为三个小矩阵的乘积,分解后的矩阵的元素数目远小于原始矩阵的元素数目,从而达到减少计算量的目的。通过对全连接层的权值矩阵进行SVD分解,使得处理一张图像的速度明显提升(Truncated SVD can reduce detection time by more than 30% with only a small (0.3 percentage point) drop in mAP and without needing to perform additional fine-tuning after model compression.)。

原理可以看这篇

综上所述,Fast R-CNN目标检测主要流程如下:

(1). 输入一张待检测图像;

(2). 提取候选区域:利用Selective Search算法在输入图像中提取出候选区域,并把这些候选区域按照空间位置关系映射到最后的卷积特征层;

(3). 区域归一化:对于卷积特征层上的每个候选区域进行RoI Pooling操作,得到固定维度的特征;

(4). 分类与回归:将提取到的特征输入全连接层,然后用Softmax进行分类,对候选区域的位置进行回归。

Faster RCNN

Fast RCNN的成功,使得检测的时间大大减少,但是其仍旧需要依靠Selective Search方法来搜索全局图像中可能包含目标的ROI,因此,对于整个目标检测流程来说,proposals的建议成了最耗时的地方(对于在cpu上实现的SS算法,其搜索一张图片大概需要2秒),这篇论文考虑的就是将proposals建议流程加速,从而使得完整的检测流程也能满足实时性的要求。

作者考虑的是能不能用一个在GPU上实现的深度神经网络来快速地提取ROI呢?然后再将提取到的ROI给Fast RCNN来进行识别和位移微调,从而加速整个目标检测流程。

在这个想法的基础上,作者又想到,既然要用深度神经网络来生成ROI,那么这个深度网络生成ROI的过程是不是需要计算全局图像的特征图?而Fast RCNN也需要用到全局图像的特征图,因此,很自然地引出来一个想法,这个特征图能否共用于ROI生成过程与目标检测过程呢?

更进一步,特征图是共享的,这是不是代表提取得到全局图像特征图的网络架构是共享的?也就是说,使用一个深度学习模型,提取得到特征图,然后在特征图的基础上,分两个分支,一个分支基于特征图生成建议的ROI(proposals),另一个分支基于生成的ROI和特征图,来对图中出现的目标进行检测。这就是Faster RCNN的一个重要思想,即卷积层共享。

基于卷积层共享的思想,Fast RCNN对目标进行检测时,本来也需要特征提取网络来对全局图像生成特征图,因此生成proposals的消耗几乎是free的,在原论文中,这个时间消耗是10ms一张图,大大加快了检测的流程。

Faster RCNN架构

Faster RCNN的架构如下图所示,可以分为四个模块:

(1)conv layers。即特征提取网络,用于提取特征。通过一组conv+relu+pooling层来提取图像的feature maps,用于后续的RPN层和取proposal。
(2)RPN(Region Proposal Network)。即区域候选网络,该网络替代了之前RCNN版本的Selective Search,用于生成候选框。这里任务有两部分,一个是分类:判断所有预设anchor(后面会解释)是属于positive还是negative(即anchor内是否有目标,二分类);还有一个bounding box regression:修正anchors得到较为准确的proposals。因此,RPN网络相当于提前做了一部分检测,即判断是否有目标(具体什么类别这里不判),以及修正anchor使框的更准一些。
(3)RoI Pooling,上面讲过。
(4)Classification and Regression。利用proposals feature maps计算出具体类别,同时再做一次bounding box regression获得检测框最终的精确位置。
其实Faster RCNN就是在Fast RCNN的基础上,应用RPN网络替代了SS算法。因此后面的检测部分就是Fast RCNN。

特征提取模块(conv layers)

作者使用了两种深度模型来进行实验,分别为ZF模型(5层)和VGG模型(13层)。

RPN网络

输入图片经过卷积、池化操作之后得到的抽象特征被RPN网络和检测网络共享,对于RPN网络,其首先将检测得到的特征图进行如下图所示的处理:

1)在原文中使用的是ZF model中,其Conv Layers中最后的conv5层num_output=256,对应生成256张特征图(feature maps),所以相当于feature map每个点都是256-dimensions

2)在conv5之后,做了rpn_conv卷积(3×3卷积)且num_output=256,相当于每个点又融合了周围3x3的空间信息),同时256-d不变

3)之后,对3×3卷积之后得到的特征,应用1×1卷积,即将输入图像中的每个通道乘以卷积系数加在一起,相当于把原图像中本来各个独立通道"联通"在一起

4)假设特征图的大小为hh×ww×256,经过3×3卷积之后变成了hh×ww×256(融合了特征图中每个点周遭的空间信息),之后再经过1×1卷积变成hh×ww×18和hh×ww×36(分别对应分类分支和回归分支),其中18=2×9,36=4×9,9代表9个不同的anchor(下面会讲为什么是9)

5)对于分类分支,hh×ww×18的特征图经过reshape后变成(2,hh×ww×9),2表示二分类,对于回归分支,则变成(4,hh×ww×9),4代表每个anchor的坐标

6)对于分类分支,之所以进行reshape,是为了softmax层计算是否包含目标的概率,而进行softmax的matrix的一边需要等于num of class

7)对于分类分支,执行softmax,得出对这hh×ww×9(每个特征图有hh×ww个点,每个点有9个anchor)的两个score,一个是有目标的概率,一个是没有目标的概率

8)补充一点,全部anchors拿去训练太多了,训练程序会在合适的anchors中随机选取128个postive anchors+128个negative anchors进行训练

注意,在tf版本的代码中使用的VGG conv5 num_output=512g,所以是512d,其他类似。

Anchor

这是本论文首次提出的东西,假设原图的大小为H×W,其经过特征提取网络之后,被下采样为多通道的、大小为hh×ww(通常hh=H/16,ww=W/16)的特征图。这些特征图包含了深度模型提取到的关于全局图像的各种信息。对于特征图中的每个点(总共hh×ww个),都能映射回原图的一块区域,称其为anchor,anchor box就是anchor的基础上,通过不同的尺寸缩放、比例缩放得到的对应于原图一块区域的矩形框。

这篇提到:Anchor的生成过程和深度学习没有任何的关系,他的本质只是你设定好一些规则,并依据这些规则,在图像中生成不同尺寸,不同长宽比的框,并希望这些框能够最终覆盖你的物体。

假设原图大小为1000×600(论文中的示例),下采样缩小16倍得到特征图的面积=1000/16×600/16≈2400,RPN会在这2400个点上,每个点生成9个anchor box(尺寸分别为 12 8 2 128^2 1282 25 6 2 256^2 2562 51 2 2 512^2 5122,比例系数分别为1:1、1:2、2:1,3种尺寸×3种比例=9种不同大小不同比例的anchor box),差不多能生成20000个anchor box。

anchor box其实就是一种先验框,基于这些先验框结合特征提取模型提取到的深度特征RPN网络的分类分支能够判断每个anchor box负责区域是否包含目标,并输出一个概率,而其回归分支则能够计算出每个anchor box和其最近(IOU最大)的ground truth bounding box的距离偏移(RPN回归分支计算出的偏移不是完全准确的,所以需要通过后面Fast RCNN来对偏移进一步修正)。

应用anchor有一个很显著的好处,即大大减少了网络的参数数量,参照原文的解释:

The translation-invariant property also reduces the model size. MultiBox has a (4 + 1) × 800-dimensional fully-connected output layer, whereas our method has a (4 + 2) × 9-dimensional convolutional output layer in the case of k = 9 anchors. As a result, our output layer has 2.8 × 104 parameters (512 × (4 + 2) × 9 for VGG-16), two orders of magnitude fewer than MultiBox’s output layer that has 6.1 × 106 parameters (1536 × (4 + 1) × 800 for GoogleNet [34] in MultiBox [27]).

anchor box采样

在训练RPN时,通过以下方式确定每个anchor box的标签(分正负标签,正标签代表有目标,不具体指某一个特定的目标,负标签代表样本):

  1. 与某个ground truth box的IOU值是所有与该ground truth boxIOU值中最大的anchor box被设置正标签
  2. 与任意ground truth box的IOU值大于0.7的anchor box被设置正标签
  3. 与所有ground truth box的IOU值均小于0.3的anchor box被设置为负标签
  4. 既没有正标签也没有负标签的anchor box不会对训练作出贡献(即不将这类anchor box考虑至损失函数当中)

损失函数被定义为:

注意损失函数中的 P i ∗ L r e g ( t i , t i ∗ ) P^*_i L_{reg}(t_i,t^*_i) PiLreg(ti,ti),这代表对于第 i i i个anchor box,只有当其具有正标签(包含目标)时才考虑计算回归损失(位置偏移的损失)。

除此之外,原文还提到:

To account for varying sizes, a set of k bounding-box regressors are learned. Each regressor is responsible for one scale and one aspect ratio, and the k regressors do not share weights. As such, it is still possible to predict boxes of various sizes even though the features are of a fixed size/scale, thanks to the design of anchors.

即,对于k种不同的anchor box(原文中k=3×3),训练k个不同的回归器,我理解的是这k个回归器对应的就是reg layer层的36个通道,其中每四个通道算一个回归器

RPN训练

RPN网络的训练可以参照下图的前半部分。

采用"image-centric"的采样策略,即类似于Fast RCNN中提到的训练采样策略:每个mini batch由一张图片和该图片中包含正反标签的anchor box组成(选256个),其中,设置正负样本的数量为1:1,由于负样本的数量通常远远高于正样本数量,因此当正样本数量小于256/2=128个时,使用负样本来填充多余的位置。

Anchor box难点

Q1:Anchor box是怎么作用到RPN中的?

参照Faster RCNN之RPN理解一文读懂Faster RCNN以及论文原文,对于得到的通道数为256的特征图,先生成所有的anchor box,对每一个像素点,都要生成9个box,一共有hh×ww×9。然后再进行3×3卷积和18个filter的1×1卷积,再reshape成(2,hh×ww×9)。如下图所示:

还是不太理解,看看能不能根据Faster RCNN的代码来推测其运行原理。

Anchor生成过程代码详解

这一篇中提到,其实就是在特征层对每个cell映射到原图中的anchor box,并根据这些anchor box和GT的IOU值确定其标签和偏移量,进而进行训练。

也就是说,其实在RPN的训练过程中,提供给RPN的只是每个anchor box的标签和偏移量,进而能够让网络学习到如何进行分类和回归。

这一篇中也作了相同的解释:

We learn offsets for x,y,w,h values, where (x,y) is the center of the box, w and h are width and height. We learn these offsets are regression. For learning these scores and offsets, we need to have targets. These targets are generated by comparing the anchor boxes with ground truth boxes. This process is anchor target generation. In anchor target generation, we calculate the IOU of GT boxes with anchor boxes to check if it is fg/bg and then the difference in the coordinates are calculated as targets to be learned by the regressor. Then these targets are used as input for cross-entropy loss and smooth l1 loss.

看了陈云大神写的pytorch源码RPN训练代码解析1RPN训练代码解析2,发现其在RPN的训练过程中,只提供了256个label(正负样本)值和20000个偏移量(严格讲是20000个anchor box中所有完整出现在原图中的anchor box的偏移量,特征图的高和宽×9≈20000),就能让网络学习到如何分类和回归。

Q2:网络是如何学习到分类和回归的呢?

参照faster-rcnn中,对RPN的理解这篇文章和我看了两天博客得到的理解,基于ZF模型提取到的特征图是256维的,即hh×ww×256,也就是说对于每一个anchor(特征图上的特征点),网络都学习到了这个anchor所对应原图区域的256种特征。而在经过3×3卷积之后,进一步增加了256种特征的空间语义性。之后,对于分类分支,其用具有18个通道的1×1卷积操作,对这256维特征进行降维,18代表着2×9,即每个anchor对应的9个anchor box属于目标or背景的概率(其实在二分类中,通道数可以等于9,即只需要得到anchor box属于目标的概率,因此会有一些人在实现faster rcnn时在这里只使用9个通道的1×1卷积)。这9个anchor box共享其对应anchor的256维特征,并且每个通道都对应其中一个anchor box属于目标的概率。对于回归分支也是类似的理解。

这篇目标检测——理解Anchor box的作用讲得很好,截图存下来,可以去原博客看看这一部分:

image-20231122201329910

这一段真的写得好,点赞!!

预测阶段并不存在真实框了,等图片处理完一堆卷积之后会产生50x38个富含信息的格子,如果其中有一个格子的信息很像我们训练时遇到的蓝色信息,那就请格子再脑补一个红色那样尺寸的先验框,然后再猜一组偏移量(训练的时候红框和偏移量是联合记忆的,预测的时候也要联合两者来猜)。

Q3:在RPN训练时,传给它的不是全部的特征图吗?是如何实现从全部特征图中将特定选择好的256个anchor box放入其中进行训练的呢?

还是参照这篇RPN训练代码解析2,其针对陈云大神实现的faster rcnn pytorch版代码进行了详细解析。

在陈云实现的代码里面,用到了一个函数AnchorTargetCreator,其目的:利用每张图中bbox的真实标签来为所有任务分配ground truth,输入为:最初生成的20000个anchor box坐标、此一张图中所有的groundtruth truth bbox的坐标。

输出则是:size为(20000,1)的正负label(其中只有128个为1,128个为0,其余都为-1)、 size为(20000,4)的回归目标(所有完整出现在原图中的anchor box的偏移量)

那问题来了,我们在RPN网络里要做三个操作:分类、回归、提供rois 。分类和回归的ground truth 怎么获取?如何给20000个anchor在分类时赋予正负标签gt_rpn_label?如何给回归操作赋予回归目标gt_rpn_loc??? 这就是此creator的目的,利用每张图bbox的真实标签来为所有任务分配ground truth!注意虽然是给所有20000个anchor赋予了ground truth,但是我们只从中任挑128个正类和128个负类共256个样本来训练。不利用所有样本训练的原因是显然图中负类远多于正类样本数目。同样回归也只挑256个anchor来完成。此函数首先将一张图中所有20000个anchor中所有完整包含在图像中的anchor筛选出来,假如挑出15000个anchor,要记录下来这部分的索引。然后利用函数bbox_iou计算15000个anchor与真实bbox的IOU。然后利用函数_create_label根据行列索引分别求出每个anchor与哪个bbox的iou最大,以及最大值,然后返回最大iou的索引argmax_ious(即每个anchor与真实bbox最大iou的索引)与label(label中背景为-1,负样本为0, 正样本为1)。注意虽然是要挑选256个,但是这里返回的label仍然是全部,只不过label里面有128为0,128个为1,其余都为-1而已。然后函数bbox2loc利用返回的索引argmax_ious来计算出回归的目标参数组loc。然后根据之前记录的索引,将15000个再映射回20000长度的label(其余的label一律置为-1)和loc(其余的loc一律置为(0,0,0,0))。

为什么我们挑出来256个label还要映射回20000呢?就是因为这里网络的预测结果(1*1卷积)就是20000个,而我们将要忽略的label都设为了-1,这就允许我们得以筛选,而loc也是一样的道理。

也就是说,其传给RPN用于训练的标签和真实偏移值都是长度为hh×ww×9的(hh、ww为特征图的高宽),只是对不需要的元素设置了特别的标签值,如label设为-1表示计算交叉熵损失时不用这个label,而loc设置为(0,0,0,0)也代表计算回归损失时,不用这个loc。

那么具体是怎么实现根据标签值和loc值就能筛选数据进行训练的呢?

在陈云大神实现的代码里,对RPN进行训练代码如下:

	gt_rpn_loc, gt_rpn_label = self.anchor_target_creator(
            at.tonumpy(bbox),
            anchor,
            img_size) 
        gt_rpn_label = at.totensor(gt_rpn_label).long()
        gt_rpn_loc = at.totensor(gt_rpn_loc)
        rpn_loc_loss = _fast_rcnn_loc_loss(
            rpn_loc,
            gt_rpn_loc,
            gt_rpn_label.data,
            self.rpn_sigma) 

        # NOTE: default value of ignore_index is -100 ...
        rpn_cls_loss = F.cross_entropy(rpn_score, gt_rpn_label.cuda(), ignore_index=-1) 
        _gt_rpn_label = gt_rpn_label[gt_rpn_label > -1] #不计算背景类
        _rpn_score = at.tonumpy(rpn_score)[at.tonumpy(gt_rpn_label) > -1]
        self.rpn_cm.add(at.totensor(_rpn_score, False), _gt_rpn_label.data.long())

可以看到里面这一行rpn_cls_loss = F.cross_entropy(rpn_score, gt_rpn_label.cuda(), ignore_index=-1),直接将ignore_index参数设置成-1,从而忽略了为-1的样本。

RPN与Fast RCNN的权重共享

对于在训练过程中实现对RPN以及Fast RCNN的权重共享,作者讨论了三种方法,分别为:

  1. 交替训练:首先训练 RPN,并使用RPN生成的proposals来训练Fast R-CNN。再使用训练Fast R-CNN后生成的特征网络参数来初始化 RPN,并迭代此过程。本文的所有实验都使用了该解决方案。

  2. 近似联合训练:将RPN和Fast RCNN作为一个整体来训练。注意Fast RCNN使用的proposals是由RPN网络得到的,并不是外界直接给的。为什么要叫近似联合训练呢?作者在原文中提到

    The RoI pooling layer [2] in Fast R-CNN accepts the convolutional features and also the predicted bounding boxes as input(这里说明了Fast RCNN接收RPN生成的预测作为输入。), so a theoretically valid backpropagation solver should also involve gradients w.r.t. the box coordinates. These gradients are ignored in the above approximate joint training.(由于接受了RPN的预测作为输入,因此其在反向传播中按理应该是要从Fast RCNN的输入反向传播至RPN的回归分支的,但是这里写的是忽略了这一分支涉及的梯度,因此叫近似联合训练。)

    为什么要这样呢?因为加上这一分支的梯度之后会使得问题更难解决(难以计算)。

    文中提到:采用近似联合训练,能够在得到相似精度的基础上,减少25%-50%的训练时间,因此作者在后续的python代码中使用的是这种训练方式。

  3. 非近似联合训练:理论上如果不舍弃是不是能更好的提升RPN部分网络的性能呢?作者把这种训练方式称为“ Non-approximate joint training”,即非近似联合训练。此方法在paper中只是一笔带过,表示“This is a nontrivial problem and a solution can be given by an “RoI warping” layer as developed in [15], which is beyond the scope of this paper”。

本文的实际实验过程中,使用的是交替训练法,并且其只迭代了两个循环,也就是4-step训练,如下所示:

  1. 第一步:用ImageNet模型初始化,独立训练一个RPN网络;
  2. 第二步:仍然用ImageNet模型初始化,但是使用上一步RPN网络产生的proposal作为输入,训练一个Fast-RCNN网络,至此,两个网络每一层的参数完全不共享;
  3. 第三步:使用第二步的Fast-RCNN网络参数初始化一个新的RPN网络,但是把RPN、Fast-RCNN共享的那些卷积层的learning rate设置为0,也就是不更新,仅仅更新RPN特有的那些网络层,重新训练,此时,两个网络已经共享了所有公共的卷积层;
  4. 第四步:仍然固定共享的那些网络层,把Fast-RCNN特有的网络层也加入进来,形成一个unified network,继续训练,fine tune Fast-RCNN特有的网络层,此时,该网络已经实现我们设想的目标,即网络内部预测proposal并实现检测的功能。

还不太理解的可以参考这篇

总结

image-20231120141518462

  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值