FCOS论文及源码详解(六)

FCOS论文及源码详解(六)


FCOS论文及源码详解(二)中提到,FCOS的training部分关键在于调用train_net.py,故解析FCOS源码从该文件开始。
train_net.py→train()开头
→build_detection_model()→GeneralizedRCNN→build_backbone(), build_rpn(), build_roi_heads().
build_backbone()→build_resnet_backbone()→ResNet
FCOS论文及源码详解(二)FCOS论文及源码详解(三)已将ResNet分析完毕。
FCOS论文及源码详解(四)得到build_rpn()→build_fcos()→FCOSModule,并分析其head部分, FCOS论文及源码详解(五)分析其box_selector_test部分,本篇分析其loss_evaluator部分。

FCOS代码

build_rpn()

fcos.fcos.FCOSModule

loss_evaluator
loss_evaluator→make_fcos_loss_evaluator()调用自fcos_core.modeling.rpn.fcos.loss

def make_fcos_loss_evaluator(cfg):
    loss_evaluator = FCOSLossComputation(cfg)
    return loss_evaluator

即loss_evaluator→make_fcos_loss_evaluator()→FCOSLossComputation
在其上方索至

class FCOSLossComputation(object):
    """
    This class computes the FCOS losses.
    """

    def __init__(self, cfg):
        self.cls_loss_func = SigmoidFocalLoss(
            cfg.MODEL.FCOS.LOSS_GAMMA, # 2.0
            cfg.MODEL.FCOS.LOSS_ALPHA # 0.25
        )

SigmoidFocalLoss调用自fcos_core.layers

class SigmoidFocalLoss(nn.Module):
    def __init__(self, gamma, alpha):
        super(SigmoidFocalLoss, self).__init__()
        self.gamma = gamma
        self.alpha = alpha

    def forward(self, logits, targets):
        device = logits.device
        if logits.is_cuda:
            loss_func = sigmoid_focal_loss_cuda
        else:
            loss_func = sigmoid_focal_loss_cpu

        loss = loss_func(logits, targets, self.gamma, self.alpha)
        return loss.sum()

以sigmoid_focal_loss_cpu()为例说明,在其上方索至

def sigmoid_focal_loss_cpu(logits, targets, gamma, alpha):
    num_classes = logits.shape[1]
    gamma = gamma[0]
    alpha = alpha[0]
    dtype = targets.dtype
    device = targets.device
    # arange(): [start, end)
    # unsqueeze(): Returns a new tensor with a dimension of size one inserted at the specified position.
    # dim (int) – the index at which to insert the singleton dimension
    class_range = torch.arange(1, num_classes+1, dtype=dtype, device=device).unsqueeze(0)

    t = targets.unsqueeze(1)
    p = torch.sigmoid(logits)
    term1 = (1 - p) ** gamma * torch.log(p)
    term2 = p ** gamma * torch.log(1 - p)
    return -(t == class_range).float() * term1 * alpha - ((t != class_range) * (t >= 0)).float() * term2 * (1 - alpha)

该算式即
F o c a l L o s s ( p t ) = − α t ( 1 − p t ) γ l o g ( p t ) Focal Loss(p_t)=−α_t(1 − p_t)^γ log(p_t) FocalLoss(pt)=αt(1pt)γlog(pt)
p t = { p , y = 1 1 − p , o t h e r w i s e p_t= \left\{ \begin{array}{lr} p, y=1 & \\ 1-p, otherwise & \\ \end{array} \right. pt={p,y=11p,otherwise
参见FCOS论文及源码详解(一)

继续看类FCOSLossComputation的方法__init__()

        self.fpn_strides = cfg.MODEL.FCOS.FPN_STRIDES # [8, 16, 32, 64, 128]
        self.center_sampling_radius = cfg.MODEL.FCOS.CENTER_SAMPLING_RADIUS # 0.0 if CENTER_SAMPLING_RADIUS <= 0, it will disable center sampling
        self.iou_loss_type = cfg.MODEL.FCOS.IOU_LOSS_TYPE # "iou"
        self.norm_reg_targets = cfg.MODEL.FCOS.NORM_REG_TARGETS # False

        # we make use of IOU Loss for bounding boxes regression,
        # but we found that L1 in log scale can yield a similar performance
        self.box_reg_loss_func = IOULoss(self.iou_loss_type)
        self.centerness_loss_func = nn.BCEWithLogitsLoss(reduction="sum")

nn.BCEWithLogitsLoss(reduction=“sum”)→sigmiod+BCELoss(Binary Cross Entropy Loss)
L = l 1 , . . . , l N T , l n = − w n [ y n ⋅ l o g σ ( x n ) + ( 1 − y n ) ⋅ l o g ( 1 − σ ( x n ) ) ] L={l_1,...,l_N}^T,l_n=-w_n[y_n·logσ(x_n)+(1-y_n)·log(1-σ(x_n))] L=l1,...,lNT,ln=wn[ynlogσ(xn)+(1yn)log(1σ(xn))]
"sum"→ l ( x , y ) = s u m ( L ) l(x,y)=sum(L) l(x,y)=sum(L)

IOULoss调用自fcos_core.layers

class IOULoss(nn.Module):
    def __init__(self, loss_type="iou"):
        super(IOULoss, self).__init__()
        self.loss_type = loss_type

    def forward(self, pred, target, weight=None):
        pred_left = pred[:, 0]
        # omit pred_top, pred_right, pred_bottom
        # omit target_left, ...

        target_area = (target_left + target_right) * \
                      (target_top + target_bottom)
        # omit pred_area

        w_intersect = torch.min(pred_left, target_left) + torch.min(pred_right, target_right)
        # omit g_w_intersect, h_intersect, g_h_intersect
        ac_uion = g_w_intersect * g_h_intersect + 1e-7
        area_intersect = w_intersect * h_intersect
        area_union = target_area + pred_area - area_intersect
        # 推断:+1防止除数为0
        ious = (area_intersect + 1.0) / (area_union + 1.0)
        gious = ious - (ac_uion - area_union) / ac_uion
        if self.loss_type == 'iou':
            losses = -torch.log(ious)
        # omit elif 

        if weight is not None and weight.sum() > 0:
            return (losses * weight).sum()
        else:
            assert losses.numel() != 0
            return losses.sum()

IOULoss可参考下图
在这里插入图片描述
参见FCOS论文及源码详解(一)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值