Example #1
0
 def test_focal_loss_equals_ce_loss_multi_class(self) -> None:
     """
     Focal loss with predictions for multiple classes matches ce loss.
     """
     inputs = logit(
         torch.tensor(
             [[
                 [0.95, 0.55, 0.12, 0.05],
                 [0.09, 0.95, 0.36, 0.11],
                 [0.06, 0.12, 0.56, 0.07],
                 [0.09, 0.15, 0.25, 0.45],
             ]],
             dtype=torch.float32,
         ))
     targets = torch.tensor(
         [[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]],
         dtype=torch.float32,
     )
     focal_loss = sigmoid_focal_loss(inputs,
                                     targets,
                                     gamma=0,
                                     alpha=-1,
                                     reduction="mean")
     ce_loss = F.binary_cross_entropy_with_logits(inputs,
                                                  targets,
                                                  reduction="mean")
     self.assertEqual(ce_loss, focal_loss)
Example #2
0
def score_box_point_loss(target_scores, target_box_deltas, target_point_deltas,
                         pred_logits, pred_box_deltas, pred_point_deltas,
                         point_mask):
    # target_scores: [B, k]
    # target_box_deltas: [B, k, 4]
    # target_point_deltas: [B, k, p, 2]
    # point_mask: [B, k]

    score_loss = sigmoid_focal_loss(pred_logits,
                                    target_scores,
                                    reduction='sum')
    maxscore, _ = target_scores.max(-1)
    pos_mask = maxscore > 0.5

    target_box_deltas_pos = target_box_deltas[pos_mask].reshape(-1, 2, 2)
    pred_box_deltas_pos = pred_box_deltas[pos_mask].reshape(-1, 2, 2)
    box_loss = euclidean_loss(pred_box_deltas_pos, target_box_deltas_pos,
                              'sum')

    point_mask = pos_mask & point_mask

    target_point = target_point_deltas[point_mask]  # -1, p, 2
    pred_point = pred_point_deltas[point_mask]  # -1, p, 2

    point_loss = euclidean_loss(pred_point, target_point, 'sum')

    npos = target_box_deltas_pos.shape[0]
    npoint = target_point.shape[0]

    return score_loss / npos, box_loss / npos, point_loss / npoint
Example #3
0
    def test_focal_loss_equals_ce_loss(self) -> None:
        """
        No weighting of easy/hard (gamma = 0) or positive/negative (alpha = 0).
        """
        inputs = logit(
            torch.tensor([[[0.95], [0.90], [0.98], [0.99]]],
                         dtype=torch.float32))
        targets = torch.tensor([[[1], [1], [1], [1]]], dtype=torch.float32)
        inputs_fl = inputs.clone().requires_grad_()
        targets_fl = targets.clone()
        inputs_ce = inputs.clone().requires_grad_()
        targets_ce = targets.clone()

        focal_loss = sigmoid_focal_loss(inputs_fl,
                                        targets_fl,
                                        gamma=0,
                                        alpha=-1,
                                        reduction="mean")
        ce_loss = F.binary_cross_entropy_with_logits(inputs_ce,
                                                     targets_ce,
                                                     reduction="mean")

        self.assertEqual(ce_loss, focal_loss.data)
        focal_loss.backward()
        ce_loss.backward()
        self.assertTrue(
            # pyre-ignore
            torch.allclose(inputs_fl.grad.data, inputs_ce.grad.data))
Example #4
0
 def test_positives_ignored_focal_loss(self) -> None:
     """
     With alpha = 0 postive examples have focal loss of 0.
     """
     inputs = logit(
         torch.tensor(
             [[[0.05], [0.12], [0.89], [0.79]]], dtype=torch.float32
         )
     )
     targets = torch.tensor([[[1], [1], [0], [0]]], dtype=torch.float32)
     focal_loss = (
         sigmoid_focal_loss(inputs, targets, gamma=2, alpha=0)
         .squeeze()
         .numpy()
     )
     ce_loss = (
         F.binary_cross_entropy_with_logits(
             inputs, targets, reduction="none"
         )
         .squeeze()
         .numpy()
     )
     targets = targets.squeeze().numpy()
     self.assertTrue(np.all(ce_loss[targets == 1] > 0))
     self.assertTrue(np.all(focal_loss[targets == 1] == 0))
Example #5
0
 def run_focal_loss() -> None:
     fl = sigmoid_focal_loss(inputs,
                             targets,
                             gamma=0,
                             alpha=alpha,
                             reduction="mean")
     fl.backward()
     torch.cuda.synchronize()
Example #6
0
 def forward(self, input: Tensor, target: Tensor):
     """
     Shape:
     - Input: : $(N, *)$ where $*$ means, any number of additional dimensions.
     - Target: : $(N, *)$, same shape as the input.
     - Output: scalar. If `reduction` is 'none', then $(N, *)$ , same shape as input.
     """
     loss = sigmoid_focal_loss(input, target, self.gamma, self.alpha, self.reduction)
     return loss
Example #7
0
 def test_hard_ex_focal_loss_similar_to_ce_loss(self) -> None:
     """
     With gamma = 2 loss of hard examples is unchanged.
     """
     inputs = logit(
         torch.tensor([0.05, 0.12, 0.09, 0.17], dtype=torch.float32))
     targets = torch.tensor([1, 1, 1, 1], dtype=torch.float32)
     focal_loss = sigmoid_focal_loss(inputs, targets, gamma=2, alpha=-1)
     ce_loss = F.binary_cross_entropy_with_logits(inputs,
                                                  targets,
                                                  reduction="none")
     loss_ratio = (ce_loss / focal_loss).squeeze()
     correct_ratio = 1.0 / ((1.0 - inputs.sigmoid())**2)
     self.assertTrue(np.allclose(loss_ratio, correct_ratio))
Example #8
0
 def test_easy_ex_focal_loss_weighted_less_than_ce_loss(self) -> None:
     """
     With gamma = 2, alpha = 0.5 loss of easy examples is downweighted.
     """
     inputs = logit(
         torch.tensor([[[0.95], [0.90], [0.6], [0.3]]],
                      dtype=torch.float64))
     targets = torch.tensor([[[1], [1], [1], [1]]], dtype=torch.float64)
     focal_loss = sigmoid_focal_loss(inputs, targets, gamma=2, alpha=0.5)
     ce_loss = F.binary_cross_entropy_with_logits(inputs,
                                                  targets,
                                                  reduction="none")
     loss_ratio = (ce_loss / focal_loss).squeeze()
     correct_ratio = 2.0 / ((1.0 - inputs.squeeze().sigmoid())**2)
     self.assertTrue(np.allclose(loss_ratio, correct_ratio))
Example #9
0
 def test_easy_ex_focal_loss_less_than_ce_loss(self) -> None:
     """
     With gamma = 2 loss of easy examples is downweighted.
     """
     N = 5
     inputs = logit(torch.rand(N))
     targets = torch.randint(0, 2, (N, )).float()
     focal_loss = sigmoid_focal_loss(inputs, targets, gamma=2, alpha=-1)
     ce_loss = F.binary_cross_entropy_with_logits(inputs,
                                                  targets,
                                                  reduction="none")
     loss_ratio = (ce_loss / focal_loss).squeeze()
     prob = torch.sigmoid(inputs)
     p_t = prob * targets + (1 - prob) * (1 - targets)
     correct_ratio = 1.0 / ((1.0 - p_t)**2)
     self.assertTrue(np.allclose(loss_ratio, correct_ratio))
Example #10
0
 def test_sum_focal_loss_equals_ce_loss(self) -> None:
     """
     Sum of focal loss across all examples matches ce loss.
     """
     inputs = logit(
         torch.tensor([[[0.05], [0.12], [0.89], [0.79]]],
                      dtype=torch.float32))
     targets = torch.tensor([[[1], [1], [0], [0]]], dtype=torch.float32)
     focal_loss = sigmoid_focal_loss(inputs,
                                     targets,
                                     gamma=0,
                                     alpha=-1,
                                     reduction="sum")
     ce_loss = F.binary_cross_entropy_with_logits(inputs,
                                                  targets,
                                                  reduction="sum")
     self.assertEqual(ce_loss, focal_loss)
Example #11
0
def score_box_loss(target_scores, target_deltas, pred_logits, pred_deltas):
    # target_scores: [B, k]
    # target_deltas: [B, k, 4]
    # pred_scores: [B, k]
    # pred_deltas: [B, k, 4]
    score_loss = sigmoid_focal_loss(pred_logits,
                                    target_scores,
                                    reduction='sum')
    maxscore, _ = target_scores.max(-1)
    pos_mask = maxscore > 0.5

    target_box_deltas_pos = target_deltas[pos_mask].reshape(-1, 2, 2)
    pred_box_deltas_pos = pred_deltas[pos_mask].reshape(-1, 2, 2)
    box_loss = euclidean_loss(pred_box_deltas_pos, target_box_deltas_pos,
                              'sum')
    npos = target_box_deltas_pos.shape[0]

    return score_loss / npos, box_loss / npos
Example #12
0
 def test_mean_focal_loss_equals_ce_loss(self) -> None:
     """
     Mean value of focal loss across all examples matches ce loss.
     """
     inputs = logit(
         torch.tensor(
             [[0.05, 0.9], [0.52, 0.45], [0.89, 0.8], [0.39, 0.5]],
             dtype=torch.float32,
         ))
     targets = torch.tensor([[1, 0], [1, 0], [1, 1], [0, 1]],
                            dtype=torch.float32)
     focal_loss = sigmoid_focal_loss(inputs,
                                     targets,
                                     gamma=0,
                                     alpha=-1,
                                     reduction="mean")
     ce_loss = F.binary_cross_entropy_with_logits(inputs,
                                                  targets,
                                                  reduction="mean")
     self.assertEqual(ce_loss, focal_loss)
Example #13
0
    def focal_loss(self):
        from fvcore.nn import sigmoid_focal_loss

        self._log_accuracy()

        bg_class_ind = self.pred_class_logits.shape[1] - 1
        fg_inds = (self.gt_classes >= 0) & (self.gt_classes < bg_class_ind)
        num_foreground = fg_inds.nonzero().numel()

        gt_classes_target = torch.zeros_like(self.pred_class_logits)
        gt_classes_target[fg_inds, self.gt_classes[fg_inds]] = 1

        loss_cls = sigmoid_focal_loss(
            self.pred_class_logits[:, 0:bg_class_ind],
            gt_classes_target[:, 0:bg_class_ind],
            alpha=self.focal_loss_alpha,
            gamma=self.focal_loss_gamma,
            reduction="sum",
        ) / max(1, num_foreground)

        # logger.info("___________________________softmax cross entropy loss would have been: {}_________________________"
        #             "__".format(F.cross_entropy(self.pred_class_logits, self.gt_classes, reduction="mean")))
        # logger.info("classification loss divided by: {}".format(max(1, num_foreground)))
        return loss_cls
Example #14
0
    def losses(self, gt_clses, gt_belongs, gt_masks, pred_logits, pred_points,
               ins_feature):
        """
        Args:
            For `gt_clses`, `gt_belongs`, `gt_masks` parameters, see
                :meth:`TensorMask.get_ground_truth`.
            For `pred_logits` and `pred_points`, see
                :meth:`TensorMaskHead.forward`.

        Returns:
            losses (dict[str: Tensor]): mapping from a named loss to a scalar tensor
                storing the loss. Used during training only. The potential dict keys are:
                "loss_cls", and "loss_mask".
        """
        num_fg = gt_belongs.size(0)
        w, h = pred_points.size(2), pred_points.size(3)
        max_side = w * 0.5 if w > h else h * 0.5
        # print(num_fg,torch.sum(gt_clses))
        loss_normalizer = torch.tensor(max(1, num_fg),
                                       dtype=torch.float32,
                                       device=self.device)

        # classification
        loss_cls = (sigmoid_focal_loss(
            pred_logits,
            gt_clses,
            alpha=self.focal_loss_alpha,
            gamma=self.focal_loss_gamma,
            reduction="sum",
        ) / loss_normalizer)

        losses = {
            "loss_cls": loss_cls,
        }

        # mask prediction
        loss_mask = 0
        if num_fg < 1:
            losses = {
                "loss_cls": loss_cls,
                "loss_mask": torch.sum(pred_points * 0)
            }
            return losses

        pred_points_valids = pred_points[gt_belongs[:, 0], :, gt_belongs[:, 1],
                                         gt_belongs[:, 2]]

        N, P = pred_points_valids.size()

        pred_location = pred_points_valids.detach().view(N, P // 2, 2)

        location = (
            pred_location + gt_belongs[:, 1:].view(N, 1, 2)
        ) * self.classify_feature_strides[-1] / self.ins_feature_strides[0]
        location = location.float()

        pred_points_valids = pred_points_valids.view(N, P // 2, 2, 1)
        Q = gt_masks.size(1)
        gt_masks = gt_masks.view(N, 1, Q, 2)

        gt_masks = gt_masks.transpose(2, 3)

        pred_points_valids_contour = pred_points_valids

        batch_index = gt_belongs[:, 0]

        # print(pred_points_valids_contour.size(),gt_masks.size())
        #chamfer distance:
        # loss_mask=chamfer_loss(pred_points_valids_contour,gt_masks)*self.mask_loss_weight

        #normlized chamfer distance
        loss_mask1 = normlize_chamfer_loss(
            pred_points_valids_contour, gt_masks,
            max_side=max_side) * self.mask_loss_weight
        dist = emd_l1_loss2(pred_points_valids_contour, gt_masks)
        loss_mask2 = torch.mean(dist)

        points_delta = self.ins_head(ins_feature, location, batch_index)
        contour_weight = torch.zeros_like(points_delta) + 0.1
        contour_weight[:, :81 * 3, :] = 1
        loss_delta = torch.mean(
            torch.abs(points_delta - dist) * contour_weight)

        losses["loss_mask"] = loss_mask1 + loss_mask2
        losses["loss_delta"] = loss_delta
        return losses
Example #15
0
        for img_data, labels_data in tqdm(dataloader_train):

            labels_data[labels_data > 1] = 1
            img_label = labels_data.numpy().astype(np.float)

            optimizer.zero_grad()
            if opt.gpu_id >= 0:
                img_data = img_data.cuda()
                labels_data = labels_data.cuda().float()

            classes = model(img_data)

            loss_dis = sigmoid_focal_loss(classes,
                                          labels_data.view(-1, 1),
                                          alpha=0.25,
                                          gamma=2,
                                          reduction="mean")

            loss_dis_data = loss_dis.item()
            loss_dis.backward()
            optimizer.step()

            classes = classes.view(1, -1).squeeze(0)
            classes = torch.sigmoid(classes)
            output_dis = classes.data.cpu().numpy()

            tol_label = np.concatenate((tol_label, img_label))
            tol_pred = np.concatenate((tol_pred, output_dis))

            loss_train += loss_dis_data
Example #16
0
    def losses(
        self,
        gt_clses,
        gt_belongs,
        gt_masks,
        gt_ins,
        pred_logits,
        pred_points,
        ins_feature
    ):
        """
        Args:
            For `gt_clses`, `gt_belongs`, `gt_masks` parameters, see
                :meth:`TensorMask.get_ground_truth`.
            For `pred_logits` and `pred_points`, see
                :meth:`TensorMaskHead.forward`.

        Returns:
            losses (dict[str: Tensor]): mapping from a named loss to a scalar tensor
                storing the loss. Used during training only. The potential dict keys are:
                "loss_cls", and "loss_mask".
        """
        num_fg=gt_belongs.size(0)
        w,h=pred_points.size(2),pred_points.size(3)
        max_side=w*0.5 if w>h else h*0.5
        # print(num_fg,torch.sum(gt_clses))
        loss_normalizer = torch.tensor(max(1, num_fg), dtype=torch.float32, device=self.device)

        # classification
        loss_cls = (
            sigmoid_focal_loss(
                pred_logits,
                gt_clses,
                alpha=self.focal_loss_alpha,
                gamma=self.focal_loss_gamma,
                reduction="sum",
            )
            / loss_normalizer
        )


        losses = {"loss_cls": loss_cls, }

        # mask prediction
        loss_mask = 0
        if num_fg<1:
            losses= {"loss_cls": loss_cls, "loss_mask":torch.sum(pred_points*0)}
            return losses

        pred_points_valids=pred_points[gt_belongs[:,0],:,gt_belongs[:,1],gt_belongs[:,2]]

        N,P=pred_points_valids.size()

        # pred_location=(pred_points_valids.view(N,P//2,2)+gt_belongs[:,1:].view(N,1,2))*4
        pred_points_valids=pred_points_valids.view(N,P//2,2,1)

        Q=gt_masks.size(1)
        location=(gt_masks+gt_belongs[:,1:].view(N,1,2))*self.classify_feature_strides[-1]/self.ins_feature_strides[0]
        location=location.float()
        
        gt_masks=gt_masks.view(N,1,Q,2)

        gt_masks=gt_masks.transpose(2,3)

        pred_points_valids_contour=pred_points_valids

       
        batch_index=gt_belongs[:,0]


        pred_ins=self.ins_head(ins_feature,location,batch_index)
        # _,_,h,w=gt_ins.size()
        pred_ins=F.interpolate(pred_ins,scale_factor=self.ins_feature_strides[0],mode='bilinear').squeeze(1)

        loss_ins=F.binary_cross_entropy_with_logits(pred_ins,gt_ins)*self.ins_loss_weight
        losses['loss_ins'] = loss_ins

        # print(pred_points_valids_contour.size(),gt_masks.size())
        #chamfer distance:
        # loss_mask=chamfer_loss(pred_points_valids_contour,gt_masks)*self.mask_loss_weight

        #normlized chamfer distance
        # loss_mask=normlize_chamfer_loss(pred_points_valids_contour,gt_masks,max_side=max_side)*self.mask_loss_weight
        loss_mask=emd_l1_loss(pred_points_valids_contour,gt_masks)*self.mask_loss_weight
        
        losses["loss_mask"] = loss_mask
        return losses
Example #17
0
    def losses(
        self,
        gt_clses,
        gt_belongs,
        gt_masks,
        pred_logits,
        pred_points,
    ):
        """
        Args:
            For `gt_clses`, `gt_belongs`, `gt_masks` parameters, see
                :meth:`TensorMask.get_ground_truth`.
            For `pred_logits` and `pred_points`, see
                :meth:`TensorMaskHead.forward`.

        Returns:
            losses (dict[str: Tensor]): mapping from a named loss to a scalar tensor
                storing the loss. Used during training only. The potential dict keys are:
                "loss_cls", and "loss_mask".
        """
        num_fg = gt_belongs.size(0)
        w, h = pred_points.size(2), pred_points.size(3)
        max_side = w * 0.5 if w > h else h * 0.5
        # print(num_fg,torch.sum(gt_clses))
        loss_normalizer = torch.tensor(max(1, num_fg),
                                       dtype=torch.float32,
                                       device=self.device)

        # classification
        loss_cls = (sigmoid_focal_loss(
            pred_logits,
            gt_clses,
            alpha=self.focal_loss_alpha,
            gamma=self.focal_loss_gamma,
            reduction="sum",
        ) / loss_normalizer)

        losses = {
            "loss_cls": loss_cls,
        }

        # mask prediction
        loss_mask = 0
        if num_fg < 1:
            losses = {
                "loss_cls": loss_cls,
                "loss_mask": torch.sum(pred_points * 0)
            }
            return losses

        pred_points_valids = pred_points[gt_belongs[:, 0], :, gt_belongs[:, 1],
                                         gt_belongs[:, 2]]

        N, P = pred_points_valids.size()
        pred_points_valids = pred_points_valids.view(N, P // 2, 2, 1)

        Q = gt_masks.size(1)
        gt_masks = gt_masks.view(N, 1, Q, 2)
        gt_masks = gt_masks.transpose(2, 3)

        pred_points_valids_contour = pred_points_valids

        if self.circumscribed:
            num_points = P // 2
            edge = np.sqrt(num_points)
            # top=[0+i for i in range(edge)]
            # left=[i*edge+0 for i in range(1,edge-1)]
            # right=[i*edge+edge-1 for i in range(1,edge-1)]
            # bottom=[(edge-1)*edge+i for i in range(edge)]
            # Index=top+left+right+bottom
            All = [i * edge + j for i in range(edge) for j in range(edge)]
            Inner = [
                i * edge + j for i in range(1, edge - 1)
                for j in range(1, edge - 1)
            ]
            Out = list(set(All) - set(Inner))
            Out = torch.tensor(Out, dtype=torch.int64, device=self.device)
            pred_points_valids_contour = pred_points_valids[:, Out, :, :]

            # Inner=torch.tensor(Inner,dtype=torch.int64,device=self.device)
            # pred_points_valids_inner=pred_points_valids[:,Inner,:,:]

        # print(pred_points_valids_contour.size(),gt_masks.size())
        #chamfer distance:
        # loss_mask1=chamfer_loss(pred_points_valids_contour,gt_masks)*self.mask_loss_weight

        #normlized chamfer distance
        loss_mask1 = normlize_chamfer_loss(
            pred_points_valids_contour, gt_masks,
            max_side=max_side) * self.mask_loss_weight
        loss_mask2 = emd_l1_loss(pred_points_valids_contour,
                                 gt_masks) * self.mask_loss_weight

        losses["loss_mask"] = loss_mask1 + loss_mask2
        return losses