检测过程:
检测过程:
前景:需要检测的目标均为前景,不需要检测的均为背景
网络类型 | 代表网络 | 工作原理 | 优点 |
---|---|---|---|
One-stage | SSD、YOLO | 基于anchors直接进行分类以及调整边界框 | 检测速度快 |
Two-stage | Faster R-CNN | 1. 通过专门模块生成候选框(Region Proposal Network,RPN)去寻找前景和调整边界框(基于anchors);2. 基于之前生成的候选框进行进一步分类以及调整边界框(基于proposals) | 检测准确率高 |
具体使用哪种类型的网络需看实际任务需求。
PS:Faster R-CNN是一个经典的网络,虽然是Two-stage网络,但对One-stage网络的学习有帮助。
题目名称:Rich feature hierarchies for accurate object detection and semantic segmentation
论文地址:https://arxiv.org/pdf/1311.2524.pdf
提出时间:2014年
R-CNN可以说是利用深度学习进行目标检测的开山之作,作者Ross Girshick多次在PASCAL VOC的目标检测竞赛中夺冠,曾在2010年带领团队获得终身成就奖。
原理:利用SS(Selective Search)算法和图像分割的方法得到一些原始区域,然后使用一些合并策略将这些区域合并,得到一个层次化的区域结构,而这些结构就包含着可能需要的物体。
将2000个候选框缩放到227×227像素,接着将候选框区域输入事先训练好的AlexNet网络,获取4096维的特征,即得到2000×4096维矩阵。
CNN将负责分类的FC去掉了,所以可以得到右边4096维的特征向量。
将第二步获得的特征向量 ∈ R [ 2000 , 4096 ] \in \mathbb{R}^{[2000, 4096]} ∈R[2000,4096]与20(分类个数)个SVM组成权值矩阵 ∈ R [ 4096 , 20 ] \in \mathbb{R}^{[4096, 20]} ∈R[4096,20]相乘,得到每个候选框是某个目标类别的得分矩阵 ∈ R [ 2000 , 20 ] \in \mathbb{R}^{[2000, 20]} ∈R[2000,20]。分别对得分矩阵中每一列(即每一类)进行非极大值抑制(Non Maximum Suppression,NMS),剔除重叠的候选框,得到该列(该类别)中得分最高的一些候选框。
SVM是一个二分类的分类器,所以多类别需要训练相同个数的分类器。
这里分类数为20是因为使用的数据集是PASCAL VOC
- 2000:2000个候选框
- 20:PASCAL VOC的类别数
最右边的矩阵每一行代表一个候选框,列(20列)为该候选框对每一个类别的分数(共有20个)
IoU:两个目标框的交并比。
最后得到的是,一个类别只有一个最完美的候选框
其实边界框、候选框、建议框都是一个东西,所以这里统一称为候选框
对NMS处理后剩余的候选框进一步筛选和剔除后,分别用20个回归器对上述20个类别中剩余的候选框进行回归操作,最终得到每个类别修正后得分最高的Bounding Box。
如图,黄色框P表示候选框Region Proposal,绿色G表示GT,红色框 G ^ \hat{G} G^ 表示Region Proposal进行回归后的预测窗口,这是一个可以用最小二乘法解决的线性回归问题。
Note: 在回归过程中, 依然使用CNN的输出特征向量 ∈ R [ 2000 , 4096 ] \in \mathbb{R}^{[2000, 4096]} ∈R[2000,4096]进行预测。
题目名称:Fast R-CNN
论文地址:https://arxiv.org/pdf/1504.08083.pdf
代码链接:https://github.com/rbgirshick/fast-rcnn
提出时间:2015年
Fast R-CNN是R-CNN的升级版,同样使用VGG-16作为网络的backbone。与R-CNN相比,Faster R-CNN训练时间快9倍,推理时间快213倍,准确率从62%提升至66%(PASCAL VOC数据集)。
ROI(Region of Interest,感兴趣区域)
在R-CNN中,通过SS算法得到2000个候选框,则需要进行2000次正向传播得到2000个特征 —— 很冗余 ——很多重叠部分计算计算一次就可以。
在Fast R-CNN中,直接将整张图片送入CNN得到这张图片的特征图,再根据候选框与原图的关系映射到特征图上,就不需要重复运算了。——大幅度提升Fast R-CNN的运算速度
在Fast R-CNN网络训练过程中,并不会使用SS算法提供的所有候选框(SS算法生成大约2000个候选框),只需使用一小部分的数据即可。对于采样数据,它分为“正样本”和“负样本”。
为什么要将样本分为正样本和负样本呢?
假如我们要训练一个猫狗分类器,如果猫的样本数量远大于狗的样本数量(数据不平衡),网络在预测时会更偏向于“猫”,很明显这样是不对的。如果数据中全是“猫”的样本, 没有“狗”的样本,那么网络预测几乎一定会出现问题。
同理,在训练Fast R-CNN时,如果数据中全部都是正样本,那么网络就会很大概率认为候选区域是所需要检测的目标(可能这个框明明框住的是背景,但网络仍会认为这个被框住的背景是有用的,是一个前景),这时网络肯定会出问题。所以数据要分为正样本和负样本。
在原论文中,对于每一张图片,从2000个候选框中采集64个候选框。这64个候选框,一部分框的是正样本,一部分框的是负样本。那么正样本是如何定义的呢?
只要候选框与真实框(GT)的IoU大于0.5,则认定为正样本,反之认定为负样本。
原理:
左边图其实是一个经过特征提取的特征图,本身可视化出来也是很抽象的,这里只是为了方便理解,使用了RGB图像。
具体实现为:将特征图划分为 7×7 个小块,对其每一小块执行MaxPooling
这样处理对输入特征图的尺寸没有要求了,无论怎样都可以缩放到7×7 -> 在R-CNN中,输入图像被限定为227×227,而在Fast R-CNN中,输入图像尺寸不再被限制。
这里忽略了Channel维度,和最大池化一样,有几个通道就做几次,最后concat就可以了。
其中 L c l s L_{cls} Lcls为分类损失,是Softmax交叉熵损失。
nn.CrossEntropyLoss
nn.BCELoss
BCELoss: Binary Cross Entropy Loss
其中 p u p_u pu代表分类器预测当前候选区域为类别 u u u的概率。
Note:对于softmax的交叉熵损失来说,如果采用one-hot编码(标签),那么结果只计算真实类别概率的损失。
即: H = − l o g ( o i ) H = -log(o_i) H=−log(oi)。和Fast R-CNN的分类损失是一样的。
其中 L l o c L_{loc} Lloc为定位损失。如果我们将 ∑ i ∈ x , y , w , h s m o o t h L 1 \sum_{i \in x, y, w, h}smooth_{L_1} ∑i∈x,y,w,hsmoothL1看成是一个函数 F \mathcal{F} F,那么该回归损失可以写为:
L l o c ( t u , v ) = ∑ i ∈ x , y , w , h s m o o t h L 1 ( t i u − v i ) = F ( t x u − v x ) + F ( t y u − v y ) + F ( t w u − v w ) + F ( t h u − v h ) L_{loc}(t^u, v) = \sum_{i \in x, y, w, h}smooth_{L_1}(t_i^u - v_i) \\ = \mathcal{F}(t_x^u - v_x) + \mathcal{F}(t_y^u - v_y) + \mathcal{F}(t_w^u - v_w) + \mathcal{F}(t_h^u - v_h) Lloc(tu,v)=i∈x,y,w,h∑smoothL1(tiu−vi)=F(txu−vx)+F(tyu−vy)+F(twu−vw)+F(thu−vh)
即回归损失由四部分组成,分别针对 x , y , w , h x, y, w, h x,y,w,h的 s m o o t h L 1 smooth_{L_1} smoothL1损失。
λ \lambda λ是一个平衡系数,用于平衡分类损失和回归损失(此消彼长,很好理解)。
艾佛森括号:“在数学中,以Kenneth E. Iverson命名的“艾佛森括号”,是一种用方括号记号,如果方括号内的条件满足则为1,不满足则为0。”
即对于 [ u ≥ 1 ] [u\ge 1] [u≥1],当 u ≥ 1 u\ge 1 u≥1时里面的数为1,当 u < 1 u< 1 u<1里面的数为0。
那么如何理解这个艾佛森括号呢? u u u 是对应目标真实类别标签,即
详细的损失函数解释可以看:https://www.cnblogs.com/wangguchangqing/p/12021638.html
均方误差是模型预测值 f ( x ) f(x) f(x) 与真实样本值 y y y 之间差值平方的均值,其公式如下:
M S E = ∑ i = 1 n ( f x i − y i ) 2 n \mathrm{MSE} = \frac{\sum_{i=1}^{n} (f_{x_i} - y_i)^2}{n} MSE=n∑i=1n(fxi−yi)2
其中, y i y_i yi和 f ( x i ) f(x_i) f(xi)分别表示第 i i i个样本的真实值及其对应的预测值, n n n为样本的个数。
忽略下标 i i i ,设 n = 1 n=1 n=1,以 f ( x ) − y f(x)−y f(x)−y为横轴,MSE的值为纵轴,得到函数的图形如下:
MSE的函数曲线光滑、连续,处处可导,便于使用梯度下降算法,是一种常用的损失函数。而且,随着误差的减小,梯度也在减小,这有利于收敛,即使使用固定的学习速率,也能较快的收敛到最小值。
当 y y y和 f ( x ) f(x) f(x)也就是真实值和预测值的差值大于 1 1 1时,会放大误差;而当差值小于 1 1 1时,则会缩小误差,这是平方运算决定的。
可见,使用 MSE 损失函数,受离群点的影响较大,虽然样本中只有 5 个离群点,但是拟合的直线还是比较偏向于离群点。
均绝对误差是指模型预测值 f ( x ) f(x) f(x)和真实值 y y y之间距离的均值,其公式如下:
M A E = ∑ n = 1 n ∣ f ( x i ) − y i ∣ n \mathrm{MAE} = \frac{\sum_{n=1}^n |f(x_i)-y_i|}{n} MAE=n∑n=1n∣f(xi)−yi∣
忽略下标 i i i ,设 n = 1 n=1 n=1,以 f ( x ) − y f(x)−y f(x)−y为横轴,MAE的值为纵轴,得到函数图形如下:
MAE曲线连续,但在 y − f ( x ) = 0 y−f(x)=0 y−f(x)=0处不可导。而且 MAE 大部分情况下梯度都是相等的,这意味着即使对于小的损失值,其梯度也是大的。这不利于函数的收敛和模型的学习。但是,无论对于什么样的输入值,都有着稳定的梯度,不会导致梯度爆炸问题,具有较为稳健性的解。
相比于MSE,MAE有个优点就是,对于离群点不那么敏感。因为MAE计算的是误差 y − f ( x ) y−f(x) y−f(x)的绝对值,对于任意大小的差值,其惩罚都是固定的。
针对上面带有离群点的数据,MAE的效果要好于MSE。
如果离群点(异常值)需要被检测出来,则可以选择MSE作为损失函数;如果离群点只是当做受损的数据处理,则可以选择MAE作为损失函数。
总之,MAE作为损失函数更稳定,并且对离群值不敏感,但是其导数不连续,求解效率低。另外,在深度学习中,收敛较慢。MSE导数求解速度高,但是其对离群值敏感,不过可以将离群值的导数设为0(导数值大于某个阈值)来避免这种情况。
在某些情况下,上述两种损失函数都不能满足需求。例如,若数据中90%的样本对应的目标值为150,剩下10%在0到30之间。那么使用MAE作为损失函数的模型可能会忽视10%的异常点,而对所有样本的预测值都为150。这是因为模型会按中位数来预测。而使用MSE的模型则会给出很多介于0到30的预测值,因为模型会向异常点偏移。
这种情况下,MSE和MAE都是不可取的,简单的办法是对目标变量进行变换,或者使用别的损失函数,例如:Huber,Log-Cosh以及分位数损失等。
在Faster R-CNN以及SSD中对边框的回归使用的损失函数都是Smooth L1 作为损失函数,
S m o o t h L 1 ( x ) = { 0.5 x 2 , ∣ x ∣ < 1 ∣ x ∣ − 0.5 , o t h e r w i s e \mathrm{Smooth \ L_1} (x) = \begin{cases} 0.5x^2,& |x|<1 \\ |x|-0.5,& \mathrm{otherwise} \end{cases} Smooth L1(x)={0.5x2,∣x∣−0.5,∣x∣<1otherwise
其中, x = f ( x i ) − y i x=f(x_i)−y_i x=f(xi)−yi 为真实值和预测值的差值。
Smooth L1 能从两个方面限制梯度:
其中 x x x为预测框与groud truth之间的差异:
L 2 ( x ) = x 2 L 1 ( x ) = x S m o o t h L 1 ( x ) = { 0.5 x 2 , ∣ x ∣ < 1 ∣ x ∣ − 0.5 , o t h e r w i s e L_2(x) = x^2 \\ L_1(x) = x \\ \mathrm{Smooth \ L_1} (x) = \begin{cases} 0.5x^2,& |x|<1 \\ |x|-0.5,& \mathrm{otherwise} \end{cases} L2(x)=x2L1(x)=xSmooth L1(x)={0.5x2,∣x∣−0.5,∣x∣<1otherwise
上面损失函数对 x x x的导数为:
∂ L 2 ( x ) ∂ x = 2 x ∂ L 1 ( x ) ∂ x = { 1 , x ≤ 0 − 1 , o t h e r w i s e ∂ S m o o t h L 1 ( x ) ∂ x = { x , ∣ x ∣ < 1 ± x , o t h e r w i s e \frac{\partial L_2(x)}{\partial x} = 2x \\ \frac{\partial L_1(x)}{\partial x} = \begin{cases} 1, & x\le 0 \\ -1, & \mathrm{otherwise} \end{cases} \\ \frac{\partial \mathrm{Smooth \ L_1} (x)}{\partial x} = \begin{cases} x,& |x|<1 \\ \pm x,& \mathrm{otherwise} \end{cases} ∂x∂L2(x)=2x∂x∂L1(x)={1,−1,x≤0otherwise∂x∂Smooth L1(x)={x,±x,∣x∣<1otherwise
上面导数可以看出:
三者放在一起的函数曲线对比:
从上面可以看出,该函数实际上就是一个分段函数,在 [ − 1 , 1 ] [-1,1] [−1,1]之间实际上就是L2损失,这样解决了L1的不光滑问题,在 [ − 1 , 1 [-1,1 [−1,1]区间外,实际上就是L1损失,这样就解决了离群点梯度爆炸的问题
对于大多数CNN网络,我们一般是使用L2-loss而不是L1-loss,因为L2-loss的收敛速度要比L1-loss要快得多。
对于边框预测回归问题,通常也可以选择L2损失,但L2范数的缺点是当存在离群点(outliers)的时候,这些点会占loss的主要组成部分。比如说真实值为1,预测10次,有一次预测值为1000,其余次的预测值为1左右,显然loss值主要由1000决定。所以FastRCNN采用稍微缓和一点绝对损失函数(smooth L1损失),它是随着误差线性增长,而不是平方增长。
Smooth L1 和 L1 Loss 函数的区别在于,L1 Loss 在0点处导数不唯一,可能影响收敛。Smooth L1的解决办法是在 0 点附近使用平方函数使得它更加平滑。
Smooth L1的优点:
虽然Fast R-CNN比R-CNN快乐213倍,但仍然不快。通过对特征提取的改进,虽然变快了,但是SS算法获取候选框是没有改进的,仍然需要2s的时间(后面CNN实现部分只需要几毫秒),所以SS算法获取候选框成为了Fast R-CNN的速度瓶颈。
论文题目:Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks
论文链接:https://arxiv.org/abs/1506.01497
提出时间:2015年
Faster R-CNN是Fast R-CNN的升级版,同样使用VGG-16作为网络的backbone。推理速度在GPU上达到5fps(包括候选框的生成),准确率也有进一步的提升。在2015年的ILSVRC以及COCO竞赛中获得多个项目的第一名。
这么快是因为Faster R-CNN使用RPN(Region Proposal Network)解决了候选框生成慢的问题。
本质上是:RPN + Fast R-CNN
首先对输入图片进入特征提取得到的特征图上使用一个滑动窗口,每滑动到一个位置,生成一个一维向量。再对这个一维向量送入两个FC,输出两个值:①目标概率 2 k 2k 2k scores和②边界框回归参数 4 k 4k 4k coordinates。其中 2 k 2k 2k是针对 k k k个anchor box而言,即针对每一个anchor生成两个概率,一个是背景(负样本)的概率,一个是前景(正样本)的概率 —— k k k个anchor就会生成 2 k 2k 2k个scores。同样的,针对每一个anchor也会生成4个候选框回归参数,所以是 4 k 4k 4k coordinates。
k k k个anchor的形状是固定的(长宽比例是固定的)
思考一个问题:ZF和VGG的感受野分别为171和228,那为什么可以识别256×256和512×512像素的目标呢?
作者认为通过一个小的感受野去预测一个比它感受野大的目标候选框是有可能的 —— 看到物体的一部分也是有可能猜出目标完整的位置区域(这是作者给出的看法)。在实际使用中,用小感受野去预测大的候选框也是有效的。
这里的滑动窗口实现使用3×3卷积实现的(stride-1, padding=1),卷积过后得到与输入shape相同的特征图,之后再并联两个1×1卷积获得 2 k 2k 2k scores 和 4 k 4k 4k coordinates。
其中, λ \lambda λ为平衡参数,默认为10,所以 λ 1 N r e g \lambda \frac{1}{N_{reg}} λNreg1和 1 N c l s \frac{1}{N_{cls}} Ncls1是差不多大的。所以这个式子还可以进一步化简(在代码部分, λ 1 N r e g \lambda \frac{1}{N_{reg}} λNreg1使用 1 N c l s \frac{1}{N_{cls}} Ncls1代替)。
log \log log是以e为底的。
在PyTorch官方实现的代码中,分类损失使用的二分类交叉熵损失。
现在普遍的方法:直接采用RPN Loss + Fast R-CNN Loss的联合训练方法
原论文中采用分别训练RPN以及Fast R-CNN的方法(分布训练的方法):
以下四个部分全部由CNN完成,所以是单阶段端到端网络而非双阶段网络
R-CNN和Fast R-CNN之所以是双阶段网络,是因为使用了SS算法生成候选框,而Faster R-CNN使用RPN网络代替了这个部分,所以是单阶段网络