Faster R-CNN:关于RPN的loss及实现

Faster R-CNN是用于图像检测的一种算法,本文具体讨论了RPN部分的loss function数学计算以及Python3.0+TensorFlow1.9条件下的代码实现。
Faster R-CNN 在RPN上的损失函数由两部分构成分类损失函数和回归损失函数:
在这里插入图片描述
anchor的分类损失函数:
输入为预测的foreground的概率和anchor的标签,anchor为negative时标签值为0反之则为1。此损失函数采用了log loss即:
loss=y*log§+(1-y)*log(1-p),其中y是label,p是预测概率。

bbox坐标 smooth L1 loss的计算步骤:
1.求ground_truth 的边界框和RPN输出的边界框的差(每个边界框对应4个数值:中心点坐标(x,y),边界框的高度和宽度(w,h),此处的所有变量值都对应输入的原图)
2.对坐标差转化为t(t的计算由论文给出,并且由做差后的结果可以判断出计算过程中可以不用anchor的尺寸参与计算)并取绝对值
3.将t带入smooth l1 loss中进行计算,在计算中输入需要和1进行大小的比较,为保证loss函数的连续性比较的计算参数不参与反向传播,可利用tf.stop_gradient()阻断反向传播
4.将3中数据与权重以及标签参数相乘,可以过滤掉所有的negative的bbox坐标,并通过权重使坐标(reg)的损失函数值与分类(cls)的损失函数值接近。
5.总数N的除法运算并未直接执行而是采用了tf.reduce_mean()函数完成这一操作。

在上述计算过程中需要 用到tf.reduce_mean()和tf.reduce_sum()两个函数,分别用于求均值和求总和,二者均可以通过输入规定操作的维数。需要注意的是,在TensorFlow下的计算,尽可能的使用来自TensorFlow的函数,因为TensorFlow是符号式编程,一般情况,先定义各变量,然后建立计算图,指定变量之间的计算关系,把计算的输入放入后,模型中形成数据流。TensorFlow的运算都放在图中,运算发生在session启动后,对节点填充数据,进行运算,关闭session(会话),结束运算。每个创建的节点都被称为一个Op(operation)。与之不同的则是numpy,numpy下的函数均直接执行,无会话的启动。

关于以上功能,编写了一个类,代码如下:

# -*- coding: utf-8 -*-
# loss function for RPN

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import tensorflow as tf
import numpy as np


class rpn_loss(object):
    """
    The class rpn_loss is used to calc the loss of rpn
    The loss has two part:class loss and bbox loss
    The loss functions are log loss and robust loss
    """

    def __init__(self):
        # RPN output
        self._predictions = {}
        self._predictions_bbox = {}
        self._predictions_scores = {}
        self._anchor_label = {}
        self._truth_label = {}
        self._gound_truth_bbox = {}
        self._anchor_size = {}
        self._bbox2t = {}
        self._lmd = {}
        self._dim2mean = {}
        self.lmd = {}  # not sure

    def _predictions_process(self):
        pass

    def _smooth_l1_loss(self, bbox_predicted, bbox_ground_truth, w_h_1_1, lmd=10, sigma=1.0, gt_label, dim2mean=1):
        # if the 4 figures of bbox have been calculated
        bbox_diff = bbox_ground_truth-bbox_predicted
        t_diff = bbox_diff*w_h_1_1
        t_diff_abs = tf.abs(t_diff)
        compare_1 = tf.stop_gradient(tf.to_float(tf.less(t_diff_abs, 1.0)))
        sl_loss_box = 0.5*(compare_1*tf.pow(t_diff_abs, 2)) + \
            (1-compare_1)*(t_diff_abs-0.5)
        sum_loss_box = tf.reduce_sum(sl_loss_box, axis=dim2mean)
        loss_box = sum_loss_box*gt_label*lmd
        return loss_box

    def _class_loss(self, p_pred, label):
        # sparse_softmax_cross_entropy_with_logits whether to use
        l_loss = label*tf.log(p_pred)+(1-label)*tf.log(1-p_pred)
        l_loss_sum = tf.reduce_mean(tf.reduce_sum(l_loss))
        return l_loss_sum

    def _add_losses(self, l_loss_sum, loss_box):
        with tf.variable_scope("RPN_LOSS") as scope:
            rpn_bbox_pred = self._predictions_bbox['rpn_bbox_pred']
            rpn_ground_truth_bbox = self._gound_truth_bbox['rpn_ground_truth_bbox']
            lmd = self._lmd
            rpn_truth_label = self._truth_label['rpn_label_pred']
            w_h_1_1 = self._bbox2t
            rpn_bbox_loss = self._smooth_l1_loss(rpn_bbox_pred, rpn_ground_truth_bbox, w_h_1_1,\
                                                 lmd, gt_label=self._truth_label)
            rpn_pred_label = self._anchor_label
            rpn_cls_loss = self._class_loss(rpn_pred_label, rpn_truth_label)

            rpn_loss_sum = rpn_bbox_loss+rpn_cls_loss
            return rpn_loss_sum

你可能感兴趣的:(Faster R-CNN:关于RPN的loss及实现)