> 文章列表 > Faster RCNN系列3——RPN的真值详解与损失值计算

Faster RCNN系列3——RPN的真值详解与损失值计算

Faster RCNN系列3——RPN的真值详解与损失值计算

Faster RCNN系列:

Faster RCNN系列1——Anchor生成过程
Faster RCNN系列2——RPN的真值与预测值概述
Faster RCNN系列3——RPN的真值详解与损失值计算
Faster RCNN系列4——生成Proposal与RoI
Faster RCNN系列5——RoI Pooling与全连接层

目录

  • 一、RPN真值详解
  • 二、RPN预测值
  • 三、损失值计算
  • 参考文章

一、RPN真值详解

  RPN的真值分为类别真值偏移量真值,即每一个Anchor是否对应着真实物体,以及每一个Anchor对应物体的真实偏移值,这两种真值的具体求解过程如下图所示:

在这里插入图片描述

  1. Anchor生成

  Anchor生成的具体过程可参考Faster RCNN系列——Anchor生成过程,可生成 37 × 50 × 9 = 16650 37×50×9=16650 37×50×9=16650个Anchors,这种方法对于靠近图像边缘的点来说,可能生成超出图像范围的Anchor,需要把这部分超过图像范围的Anchor过滤掉。

def forward(self, input):# 利用NumPy首先得到原图上的中心点坐标,并利用contiguous保证内存连续shifts = torch. from_numpy(np.vstack((shift_x.ravel(), shift__y.ravel(),shift_x.rave1(), shift_y.rave1())).transpose())shifts = shifts.contiguous().type_as(rpn_cls_score) .float ()# 调用基础Anchor生成所有Anchorsself.anchors = self.anchors.type_as(gt_boxes)all_ anchors = self. anchors.view(1, A, 4) + shifts.view(K, 1, 4)# 保留边框内的Anchorsinds_inside = torch.nonzero(keep).view(-1)anchors = all_ anchors[inds_inside, :]
  1. 类别真值求解

  类别真值求解的详细过程可参考Faster RCNN系列——RPN的真值与预测值概述中类别真值的部分,需要注意的是,求解过程中的三个步骤的顺序不能变动,原因:

  • 保证一个Anchor既符合正样本,也符合负样本时,才会被赋予正样本。

  • 为了保证召回率,允许一个标签对应多个Anchor,不允许一个Anchor对应多个标签。

def forward(self, input):# 生成标签向量,对应每一个Anchor的状态,1为正,0为负,初始化为-1labels = gt_boxes.new(batch_size, inds_inside.size(0)).fill_(-1)# 生成IoU矩阵,每一行代表一个Anchor, 每一列代表一个标签overlaps = bbox_overlaps_batch(anchors, gt_boxes)# 对每一行求最大值,返回的第一个为最大值,第二个为最大值的位置max_overlaps, argmax_overlaps = torch.max(overlaps, 2)# 对每一列取最大值,返回的是每一个标签对应的IoU最大值gt_max_overlaps, _ = torch.max(overlaps, 1)# 如果一个Anchor最大的IoU小于0.3, 视为负样本labels[max_overlaps < 0.3] = 0#与所有Anchors的最大IoU为0的标签要过滤掉gt_ max_overlaps[gt_max_overlaps==0] = 1e-5# 将与标签有最大IoU的Anchor赋予正样本keep = torch.sum(overlaps.eq(gt_max_overlaps.view(batch_size, 1, -1).expand_as(overlaps)), 2)if torch.sum(keep)>0:labels[keep>0] = 1#  如果一个 Anchor最大的IoU大于0.7,视为正样本labels[max_overlaps >= 0.7] = 1
  1. Anchor的筛选

  由于Anchor的总数量接近于2万,并且大部分Anchor的标签都是背景,如果都计算损失的话则正、负样本失去了均衡,不利于网络的收敛。因此,RPN默认选择256个Anchors进行损失的计算,其中最多不超过128个的正样本。如果数量超过了限定值,则进行随机选取。当然,这里的256与128都可以根据实际情况进行调整,而不是固定死的。

def forward(self, input):......for i in range(batch_size):#如果正样本数量太多,则进行下采样随机选取if sum_fg[i] > 128 :fg_inds = torch.nonzero(labels[i] == 1).view(-1)rand_num = torch.from_numpy(np.random.permutation(fg_ inds.size(0))).type_as(gt_boxes).long()disable_inds = fg_inds[rand_num[:fg_inds.size(0)-num_fg]]labels[i][disable_inds] = -1# 负样本同上......
  1. 偏移量真值求解

  偏移量真值的求解过程可参考Faster RCNN系列——RPN的真值与预测值概述中偏移量真值的部分。

  得到偏移量的真值后,将其保存在bbox_ targets 中。与此同时,还需要求解两个权值矩阵bbox_inside_weights 和bbox_outside_weights,前者是用来设置正样本回归的权重,正样本设置为1,负样本设置为0,因为负样本对应的是背景,不需要进行回归;后者的作用则是平衡RPN分类损失与回归损失的权重,在此设置为1/256。

def forward(self, input):......# 选择每一个Anchor对应最大Iou的标签进行偏移计算bbox_targets = _compute_targets_batch(anchors, gt_ boxes.view(-1, 5)[argmax_overlaps.view(-1), :].view(batch_size, -1, 5))#设置两个权重向量bbox_inside_weights[labels==1] = 1num_examples = torch.sum(labels[i] >=0)bbox_outside_weights[labels == 1] = 1.0 / examples.item()bbox_outside_weights[labels == 0]=1.0 / examples.item()

二、RPN预测值

  RPN的预测值分为类别预测值偏移量预测值,计算过程可参考Faster RCNN系列——RPN的真值与预测值概述,通过卷积神经网络的分类分支求得类别预测值、通过回归分支求得偏移量预测值。

三、损失值计算

  有了类别真值偏移量真值类别预测值偏移量预测值,就可以计算RPN网络的损失函数了。RPN网络的损失函数包含类别损失和回归损失,公式如下:

L ( P i , t i ) = 1 N c l s ∑ L c l s ( p i , p i ∗ ) + λ 1 N r e g ∑ p i ∗ L r e g ( t i , t i ∗ ) L(P_{i},t_{i})=\\frac{1}{N_{cls}}\\sum L_{cls}(p_{i},p_{i}^{*})+\\lambda \\frac{1}{N_{reg}}\\sum p_{i}^{*}L_{reg}(t_{i},t_{i}^{*}) L(Pi,ti)=Ncls1Lcls(pi,pi)+λNreg1piLreg(ti,ti)

   ∑ L c l s ( p i , p i ∗ ) \\sum L_{cls}(p_{i},p_{i}^{*}) Lcls(pi,pi)表示筛选出的256个Anchor的类别损失, p i p_{i} pi为每一个Anchor的类别真值, p i ∗ p_{i}^{*} pi为每一个Anchor的类别预测值。这里的类别只有前景和背景之分,为二分类,因此类别损失函数 L c l s L_{cls} Lcls使用交叉熵损失函数,公式如下:

L c l s ( p i , p i ∗ ) = − ∑ p i l o g p i ∗ L_{cls}(p_{i},p_{i}^{*})=-\\sum p_{i}logp_{i}^{*} Lcls(pi,pi)=pilogpi

   ∑ p i ∗ L r e g ( t i , t i ∗ ) \\sum p_{i}^{*}L_{reg}(t_{i},t_{i}^{*}) piLreg(ti,ti)表示回归损失, t i t_{i} ti为每一个Anchor的偏移量真值, t i ∗ t_{i}^{*} ti为每一个Anchor的偏移量预测值。这里的 p i ∗ p_{i}^{*} pi对应上文中的bbox_inside_weights,用来筛选正负样本,这里的 λ 1 N r e g \\lambda \\frac{1}{N_{reg}} λNreg1对应上文中的bbox_outside_weights,用来平衡类别损失和回归损失。回归损失函数 L r e g L_{reg} Lreg使用 s m o o t h L 1 smooth_{L1} smoothL1函数,公式如下:

L r e g ( t i , t i ∗ ) = ∑ i ∈ x , y , w , h s m o o t h L 1 ( t i , t i ∗ ) L_{reg}(t_{i},t_{i}^{*})=\\sum_{i\\in x,y,w,h} smooth_{L1}(t_{i},t_{i}^{*}) Lreg(ti,ti)=ix,y,w,hsmoothL1(ti,ti)

s m o o t h L 1 ( x ) = { 0.5 x 2 i f ∣ x ∣ < 1 ∣ x ∣ − 0.5 o t h e r w i s e smooth_{L1}(x) = \\left\\{\\begin{matrix} 0.5x^{2} & if|x|<1 & \\\\ |x|-0.5 & otherwise & \\end{matrix}\\right. smoothL1(x)={0.5x2x0.5ifx<1otherwise

参考文章

《深度学习之Pytorch物体检测实战》