参考文章
- #Deep Learning回顾#之基于深度学习的目标检测
- 基于深度学习的目标检测技术演进:R-CNN、Fast R-CNN、Faster R-CNN
- faster-RCNN算法原理详解
- Object Detection--RCNN,SPPNet,Fast RCNN,FasterRCNN论文详解 【精】
- 目标检测之Faster RCNN 知识点总结
object detection技术的演进
[RCNN] - [SPP-Net] - [Fast-RCNN] - [Faster-RCNN]
序
object detection 主要分为两个任务:图像识别、定位
图像识别(classification)
输入:图片
输出:class
评估方法:准确率定位(localization)
输入:图片
输出:方框在图片中的位置(x,y,w,h)
评估方法:检测评价函数 intersection-over-union ( IOU )
思路:
-
classification 任务可以采用 卷积神经网络CNN 实现
-
localization 任务可以看做是 回归问题。首先预测出(x,y,w,h)框,然后与正确的标注框进行 回归操作
-
综上,object detection 成为classification + regression模式,我们可以基于 CNN 网络做一些 fine-tuning
-
regression太难做了,regression的训练参数收敛的时间要长得多,应想方设法转换为classification问题.
对一张图片,用各种大小的框(遍历整张图片)将图片截取出来,输入到CNN,然后CNN会输出这个框的得分(classification)以及这个框图片对应的x,y,h,w(regression)。取得分最高的那个框.
-
当多个物体时,任务就变成了:多物体识别+定位多个物体,需要找很多位置, 给很多个不同大小的框,还需要对框内的图像分类,数据量难度变很大。
优化思路:找出可能含有物体的框(也就是候选框,比如选1000个候选框),这些框之间是可以互相重叠互相包含的,这样我们就可以避免暴力枚举的所有框了。
常用选定候选框的方法:EdgeBoxes 和 Selective Search
各种选定候选框的方法的性能对比:
RCNN
前戏:
R-CNN相比传统方式:
- [x] 使用了CNN网络来提取特征
- [x] 采用大样本下有监督预训练+小样本微调的方式解决小样本难以训练甚至过拟合等问题(现实任务中,带标签的数据可能很少)
算法可以分为四步:
- 候选区域选择
SelectiveSearch算法,Region Proposal是一类传统的区域提取方法,可以看作不同宽高的滑动窗口,通过窗口滑动获得潜在的目标图像
根据Proposal提取的目标图像进行归一化,作为CNN的标准输入。 - CNN特征提取
标准CNN过程,根据输入进行卷积/池化等操作,得到固定维度的输出; -
分类与边界回归
实际包含两个子步骤:
一是对上一步的输出向量进行分类(需要根据特征训练分类器);
二是通过边界回归(bounding-box regression) 得到精确的目标区域,由于实际目标会产生多个子区域,旨在对完成分类的前景目标进行精确的定位与合并,避免多个检出。
存在的问题:
- 多个候选区域对应的图像需要预先提取,占用较大的磁盘空间;
- 针对传统CNN需要固定尺寸的输入图像,crop/warp(归一化)产生物体截断或拉伸,会导致输入CNN的信息丢失;
- 每一个ProposalRegion都需要进入CNN网络计算,上千个Region存在大量的范围重叠,重复的特征提取带来巨大的计算浪费。
R-CNN组成模块:
- 生成类无关的候选区域
- 大的卷积网络
- 特定的一组SVM分类器
- BBox Regression(精修bounding box的位置,有了这个好像是叫R-CNN BB)
训练过程:
- 有监督的预训练。采用大样本下有监督预训练+小样本微调的方式解决小样本难以训练甚至过拟合等问题。
- 特定领域的微调。
- 根据任务,将输出层改为N+1
- 样本,将IOU>0.5的region proposals打上对应类别的标签,否则打上背景标签,采用one-hot编码。
- 参数设置,学习率设置为了预训练时学习率的1/10,说是这样不会破坏初始。然后mini-batch size=128,其中32个正样本(涵盖所有类),96个负样本。
- 对象分类器(特定的一组SVM分类器):有多少个类别,就需要训练多少个SVM分类器,每个分类器判断输入是不是对应的类别。
- 正样本:CNN提取的ground truth的特征向量;负样本:CNN提取的IOU<0.3的region prosoals的特征向量。
- 因为负样本的个数远远多于正样本,一是会造成比例失衡,二是负样本太多了,会造成外存和内存的压力。所以采用了hard negative mining。
难分样本挖掘(hard negative mining)的思想:
假设给你一堆包含一个或多个人物的图片,并且每一个人都给你一个bounding box做标记,如果要训练一个分类器去做分类的话,你的分类器需要既包含正训练样本(人)和负训练样本(背景)。
好了,这样你的正负样本都有了,可以训练可以用的分类器了,你用滑动窗口在你的训练图片上进行运行,但是你会发现你的分类器并不是很好用,分类的效果并不是很好,因为它会抛出一堆的错误的正样本(当检测到人时实际上却并不是实际的人),这就问题来了,你训练了一个用于分类的分类器,然而这个分类器却并不能达到你想要的效果,那么应该怎么办呢?
这个时候就要用的hard negative了,hard negative就是当你得到错误的检测patch时,会明确的从这个patch中创建一个负样本,并把这个负样本添加到你的训练集中去。当你重新训练你的分类器后,分类器会表现的更好,并且不会像之前那样产生多的错误的正样本。
收尾:
- 减少region proposals的数量:NMS(非极大值抑制)
- 精修位置:BBox Regression
SPP-Net
RCNN 中CNN的特征提取过程非常耗时(大量的卷积计算),还要对每一个候选区域独立计算
SPP-Net在RCNN的基础上做了实质性的改进:
- 取消了crop/warp图像归一化过程,解决图像变形导致的信息丢失以及存储问题;
- 采用空间金字塔池化(SpatialPyramid Pooling )替换了 全连接层之前的最后一个池化层(上图top)
为了适应不同分辨率的特征图,定义一种可伸缩的池化层,不管输入分辨率是多大,都可以划分成mn个部分。这是SPP-net的第一个显著特征,它的输入是conv5特征图* 以及特征图候选框(原图候选框 通过stride映射得到),输出是固定尺寸(m*n)特征;
SPP 部分
它放在所有的卷积层之后,有效解决了卷积层的重复计算问题(测试速度提高了24~102倍)
特点:
- 只对原图提取一次卷积特征
- 在R-CNN中,每个候选框先resize到统一大小,然后分别作为CNN的输入,这样是很低效的。
- 优化后:对原图进行一次卷积得到整张图的feature map,然后找到每个候选框在 feature map上的映射patch,将此patch作为每个候选框的卷积特征输入到SPP layer和之后的层
- 结合空间金字塔方法实现CNNs的多尺度输入
- 一般CNN后接全连接层或者分类器,他们都需要固定的输入尺寸,因此不得不对输入数据进行crop或者warp,这些预处理会造成数据的丢失或几何的失真。
- 在卷积层和全连接层之间加入了SPP layer。此时网络的输入可以是任意尺度的,在SPP layer中每一个pooling的filter会根据输入调整大小,而SPP的输出尺度始终是固定的。
存在的问题:
- 和RCNN一样,训练过程仍然是隔离的,提取候选框 | 计算CNN特征| SVM分类 | Bounding Box回归独立训练,大量的中间结果需要转存,无法整体训练参数;
- SPP-Net在无法同时Tuning在SPP-Layer两边的卷积层和全连接层,很大程度上限制了深度CNN的效果;
- 在整个过程中,Proposal Region仍然很耗时
Region of Interest, ROI
Fast-RCNN
RCNN 存在的问题:
- 即使使用了selective search等预处理步骤来提取潜在的bounding box作为输入,但是计算机对所有region进行特征提取时会有重复计算,会造成严重的速度瓶颈
基于 SPP-Net 对 RCNN 进行改进加速:
- 借鉴SPP思路,提出简化版的ROI池化层(没用金字塔),同时加入了候选框映射功能,使得网络能够反向传播,解决了SPP的整体网络训练问题;
- 多任务Loss层
- SoftmaxLoss 代替了SVM,证明了softmax比SVM更好的效果;
- SmoothL1Loss 取代Bouding box 回归。
将分类和边框回归进行合并(又一个开创性的思路),通过多任务Loss层进一步整合深度网络,统一了训练过程,从而提高了算法准确度。
概述:
R-CNN : 一张图片 --> ~2000K 候选框 --> 归一化(crop/wrap) --> CNN --> 得到每个候选框的特征 --> 分类+回归
Fast-RCNN:一张图片 --> CNN --> feature map --> 各个尺寸候选框映射在 feature map 得到的特征 --> ROI Pooling(单层SPP-Net) --> 固定尺度的特征 --> softmax-classifier + bounding-box regressors
存在的问题:
SPP-Net 中的候选框提取过程依旧很耗时
Faster-RCNN
Fast R-CNN存在的问题
SelectiveSearch 选择性搜索,找出所有的候选框,非常耗时,存在性能问题
对 Fast R-CNN 进行改进加速
加入一个提取边缘的神经网络,也就说找到候选框的工作也交给神经网络来做了。做这样的任务的神经网络叫做Region Proposal Network(RPN)。
具体做法:
将RPN放在最后一个卷积层的后面(即替换 ROI Pooling 部分),RPN直接训练得到候选区域
Region Proposal Network(RPN)
• 在feature map上滑动窗口
• 建一个神经网络用于物体分类+框位置的回归
• 滑动窗口的位置提供了物体的大体位置信息
• 框的回归提供了框更精确的位置
Faster-RCNN 概要
Faster-RCNN:一张图片 --> CNN --> feature map --> RPN 得到候选区域 --> ROI Pooling(单层SPP-Net) --> 固定尺度的特征 --> classifier + bounding-box regressors
一种网络,四个损失函数
• RPN calssification(anchor good.bad)
• RPN regression(anchor->propoasal)
• Fast R-CNN classification(over classes)
• Fast R-CNN regression(proposal ->box)
详细结构解析
Faster RCNN 大致可以分为4个主要内容:
- Conv layers.作为一种CNN网络目标检测方法,Faster RCNN首先使用一组基础的 conv+relu+pooling 层提取image的feature maps。该feature maps被共享用于后续RPN层和全连接层。
- Region Proposal Networks.RPN网络用于生成region proposals。该层通过softmax判断anchors属于foreground或者background,再利用bounding box regression修正anchors获得精确的proposals。
- Roi Pooling。该层收集输入的feature maps和proposals,综合这些信息后提取proposal feature maps,送入后续全连接层判定目标类别。
- Classification。利用proposal feature maps计算proposal的类别,同时再次bounding box regression获得检测框最终的精确位置。
下图展示了使用 VGG16 作为基础网络的 Faster-RCNN 网络结构:
- Conv layers 部分提取图像特征,作为后续操作共享的 feature map
共有13个conv层,13个relu层,4个pooling层。
所有的conv层都是:kernel_size=3,pad=1
-
所有的pooling层都是:kernel_size=2,stride=2
综上所述,在整个Conv layers中,conv和relu层不改变输入输出大小,只有pooling层使输出长宽都变为输入的1/2。
- Region Proposal Networks(RPN) 部分生成检测框
经典的检测方法生成检测框都非常耗时,如OpenCV adaboost使用滑动窗口+图像金字塔生成检测框;或如RCNN使用SS(Selective Search)方法生成检测框。而Faster RCNN则抛弃了传统的滑动窗口和SS方法,直接使用RPN生成检测框,这也是Faster RCNN的巨大优势,能极大提升检测框的生成速度。
-
RPN网络实际分为2条线:
上面一条通过softmax分类anchors获得 foreground 和 background(检测目标是foreground)
下面一条用于计算对于 anchors 的 bounding box regression偏移量,以获得精确的 proposal
最后的Proposal层则负责综合foreground anchors和bounding box regression偏移量获取proposals,同时剔除太小和超出边界的proposals综上,整个网络到了Proposal Layer这里,就完成了相当于目标定位的功能
对于多通道图像+多卷积核做卷积,计算方式为先在输入图像4个通道分别作卷积,再将4个通道结果加起来得到一个卷积核的卷积输出,无论输入图像有多少个通道,输出图像通道数总是等于卷积核数量
对多通道图像做1x1卷积,其实就是将输入图像于每个通道乘以卷积系数后加在一起,即相当于把原图像中本来各个独立的通道“联通”在了一起。
- anchors
anchors 实际上就是一组矩形,9个矩形共有3种形状,三个面积尺寸(1282,2562,512^2),然后在每个面积尺寸下,取三种不同的长宽比例(1:1,1:2,2:1)
- 在原文中使用的是 ZF model 中,其Conv Layers中最后的conv5层num_output=256,对应生成256张特征图,所以相当于feature map每个点都是256-d。(VGG conv5 num_output=512,所以是512d,其他类似.....)
- 在conv5 feature map中每个点上有k个anchor(默认k=9),而每个anhcor要分foreground和background,所以每个点由256-d feature 转化为 cls=2k scores;而每个anchor都有[x, y, w, h]对应4个偏移量,所以reg=4k coordinates
softmax判定foreground与background
为何这样做?后面接softmax分类获得foreground anchors,也就相当于初步提取了检测目标候选区域box(一般认为目标在foreground anchors中)。bounding box regression原理
通过 bounding box regression 对上述 anchors 对应的检测框进行微调,使得foreground anchors和GT更加接近。
给定原始的Foreground Anchors A=(Ax, Ay, Aw, Ah),寻找一种映射f,使得f(Ax, Ay, Aw, Ah)=(G'x, G'y, G'w, G'h),其中(G'x, G'y, G'w, G'h)≈(Gx, Gy, Gw, Gh)。框G代表目标的 GroundTruth
- 先做平移
- 再做缩放
注意:只有当 Proposal 和 Ground Truth 比较接近时(线性问题) ,我们才能将其作
为训练样本训练我们的线性回归模型,否则会导致训练的回归模型不 work(当Proposal
跟 GT 离得较远,就是复杂的非线性问题了,此时用线性回归建模显然不合理) 。
- 平移量(, )与尺度因子(, ) 计算
那么目标函数可以表示为 ,
是要学习的参数(*表示x,y,w,h,也就是每一个变换对应一个目标函数)
是得到的预测值
线性回归就是给定输入的特征向量 X, 学习一组参数 W, 使得经过线性回归后的值
跟真实值Y(Ground Truth)非常接近. 即 。
- 要让预测值跟真实值 差距最小,得到损失函数为:
函数优化目标为:
- Proposal Layer
- 按照输入的foreground softmax scores由大到小排序anchors,提取前pre_nms_topN(e.g. 6000)个anchors。即提取修正位置后的foreground anchors
- 利用feat_stride和im_info将anchors映射回原图,判断fg anchors是否大范围超过边界,剔除严重超出边界fg anchors。
- 进行nms(nonmaximum suppression,非极大值抑制)
- 再次按照nms后的foreground softmax scores由大到小排序fg anchors,提取前post_nms_topN(e.g. 300)结果作为proposal输出。
由于在第三步中将anchors映射回原图判断是否超出边界,所以这里输出的proposal是对应MxN 原始输入图像尺度的,这点在后续网络中有用
RPN网络结构,总结起来就是:
生成anchors -> softmax分类器提取fg anchors -> bbox reg回归fg anchors -> Proposal Layer生成proposals
-
RoI pooling 部分生成固定长度的输出
为何需要RoI Pooling?
对于传统的CNN(如AlexNet,VGG),当网络训练好后输入的图像尺寸必须是固定值,同时网络输出也是固定大小的vector or matrix。如果输入图像大小不定,这个问题就变得比较麻烦。
Faster RCNN中提出了RoI Pooling解决这个问题(RoI Pooling确实是从SPP发展而来)
- RoI Pooling layer forward过程
proposal=[x1, y1, x2, y2]是对应MxN尺度的,首先使用spatial_scale参数将其映射回MxN大小的feature maps尺度,之后将每个proposal水平和竖直都分为7份,对每一份都进行max pooling处理。这样处理后,即使大小不同的proposal,输出结果都是7x7大小,实现了fixed-length output。
Classification
从PoI Pooling获取到7x7=49大小的proposal feature maps后,送入后续网络,可以看到做了如下2件事:通过全连接和softmax对proposals进行分类,这实际上已经是识别的范畴了
再次对proposals进行bounding box regression,获取更高精度的rect box
-
Faster RCNN训练
训练RPN网络:
上述公式中,i表示anchors index,表示foreground softmax predict概率,代表对应的GT predict概率(即当第i个anchor与GT间IoU>0.7,认为是该anchor是foreground,pi*=1;反之IoU<0.3时,认为是该anchor是background,=0;至于那些 0.3< IoU < 0.7 的anchor则不参与训练);t代表predict bounding box,代表对应foreground anchor对应的GT box。
整个Loss分为2部分:
- cls loss,即rpn_cls_loss层计算的softmax loss,用于分类anchors为forground与background的网络训练
- reg loss,即rpn_loss_bbox层计算的soomth L1 loss,用于bounding box regression网络训练。注意在该loss中乘了,相当于只关心foreground anchors的回归(其实在回归中也完全没必要去关心background)。
由于在实际过程中,Ncls和Nreg差距过大,用参数λ平衡二者(如Ncls=256,Nreg=2400时设置λ=10),使总的网络Loss计算过程中能够均匀考虑2种Loss。
使用的 soomth L1 loss,计算公式如下:
其中,smooth L1损失函数为:
smooth L1损失函数曲线如下图所示:
作者这样设置的目的是想让loss对于离群点更加鲁棒,相比于L2损失函数,其对离群点、异常值(outlier)不敏感,可控制梯度的量级使训练时不容易跑飞。