yhenon / pytorch-retinanet

Pytorch implementation of RetinaNet object detection.
Apache License 2.0
2.14k stars 664 forks source link

the loss file has some wrong #196

Open liuzonglei0713 opened 3 years ago

liuzonglei0713 commented 3 years ago

the following code has some wrong. 'if bbox_annotation.shape[0] == 0:' if the bbox_annotation.shape[0] is zero.that is no label. so we do not computer. we need continue. """ if bbox_annotation.shape[0] == 0: if torch.cuda.is_available(): alpha_factor = torch.ones(classification.shape).cuda() * alpha

                alpha_factor = 1. - alpha_factor
                focal_weight = classification
                focal_weight = alpha_factor * torch.pow(focal_weight, gamma)

                bce = -(torch.log(1.0 - classification))

                # cls_loss = focal_weight * torch.pow(bce, gamma)
                cls_loss = focal_weight * bce
                classification_losses.append(cls_loss.sum())
                regression_losses.append(torch.tensor(0).float())

            else:
                alpha_factor = torch.ones(classification.shape) * alpha

                alpha_factor = 1. - alpha_factor
                focal_weight = classification
                focal_weight = alpha_factor * torch.pow(focal_weight, gamma)

                bce = -(torch.log(1.0 - classification))

                # cls_loss = focal_weight * torch.pow(bce, gamma)
                cls_loss = focal_weight * bce
                classification_losses.append(cls_loss.sum())
                regression_losses.append(torch.tensor(0).float())

            continue

""" I think wo shoude write like the following: """ class FocalLoss(nn.Module): def forward(self, classifications, regressions, anchors, annotations): alpha = 0.25 gamma = 2.0 batch_size = classifications.shape[0] classification_losses = [] regression_losses = []

    anchor = anchors[0, :, :]

    anchor_widths  = anchor[:, 2] - anchor[:, 0]
    anchor_heights = anchor[:, 3] - anchor[:, 1]
    anchor_ctr_x   = anchor[:, 0] + 0.5 * anchor_widths
    anchor_ctr_y   = anchor[:, 1] + 0.5 * anchor_heights

    for j in range(batch_size):

        classification = classifications[j, :, :]
        regression = regressions[j, :, :]

        bbox_annotation = annotations[j, :, :]
        bbox_annotation = bbox_annotation[bbox_annotation[:, 4] != -1]

        if bbox_annotation.shape[0] == 0:
            regression_losses.append(torch.tensor(0).float().cuda())
            classification_losses.append(torch.tensor(0).float().cuda())

            continue

        classification = torch.clamp(classification, 1e-4, 1.0 - 1e-4)

        IoU = calc_iou(anchors[0, :, :], bbox_annotation[:, :4]) # num_anchors x num_annotations

        IoU_max, IoU_argmax = torch.max(IoU, dim=1) # num_anchors x 1

        #import pdb
        #pdb.set_trace()

        # compute the loss for classification
        targets = torch.ones(classification.shape) * -1
        targets = targets.cuda()

        targets[torch.lt(IoU_max, 0.4), :] = 0 #低于0.4全部标0

        positive_indices = torch.ge(IoU_max, 0.5) #高于0.5标1

        num_positive_anchors = positive_indices.sum()

        assigned_annotations = bbox_annotation[IoU_argmax, :]

        targets[positive_indices, :] = 0
        targets[positive_indices, assigned_annotations[positive_indices, 4].long()] = 1

        alpha_factor = torch.ones(targets.shape).cuda() * alpha

        alpha_factor = torch.where(torch.eq(targets, 1.), alpha_factor, 1. - alpha_factor)
        focal_weight = torch.where(torch.eq(targets, 1.), 1. - classification, classification)
        focal_weight = alpha_factor * torch.pow(focal_weight, gamma)

        bce = -(targets * torch.log(classification) + (1.0 - targets) * torch.log(1.0 - classification))

        # cls_loss = focal_weight * torch.pow(bce, gamma)
        cls_loss = focal_weight * bce

        cls_loss = torch.where(torch.ne(targets, -1.0), cls_loss, torch.zeros(cls_loss.shape).cuda())

        classification_losses.append(cls_loss.sum()/torch.clamp(num_positive_anchors.float(), min=1.0))

        # compute the loss for regression

        if positive_indices.sum() > 0:
            assigned_annotations = assigned_annotations[positive_indices, :]

            anchor_widths_pi = anchor_widths[positive_indices]
            anchor_heights_pi = anchor_heights[positive_indices]
            anchor_ctr_x_pi = anchor_ctr_x[positive_indices]
            anchor_ctr_y_pi = anchor_ctr_y[positive_indices]

            gt_widths  = assigned_annotations[:, 2] - assigned_annotations[:, 0]
            gt_heights = assigned_annotations[:, 3] - assigned_annotations[:, 1]
            gt_ctr_x   = assigned_annotations[:, 0] + 0.5 * gt_widths
            gt_ctr_y   = assigned_annotations[:, 1] + 0.5 * gt_heights

            # clip widths to 1
            gt_widths  = torch.clamp(gt_widths, min=1)
            gt_heights = torch.clamp(gt_heights, min=1)

            targets_dx = (gt_ctr_x - anchor_ctr_x_pi) / anchor_widths_pi
            targets_dy = (gt_ctr_y - anchor_ctr_y_pi) / anchor_heights_pi
            targets_dw = torch.log(gt_widths / anchor_widths_pi)
            targets_dh = torch.log(gt_heights / anchor_heights_pi)

            targets = torch.stack((targets_dx, targets_dy, targets_dw, targets_dh))
            targets = targets.t()

            targets = targets/torch.Tensor([[0.1, 0.1, 0.2, 0.2]]).cuda()

            negative_indices = 1 - positive_indices

            regression_diff = torch.abs(targets - regression[positive_indices, :])

            regression_loss = torch.where(
                torch.le(regression_diff, 1.0 / 9.0),
                0.5 * 9.0 * torch.pow(regression_diff, 2),
                regression_diff - 0.5 / 9.0
            )
            regression_losses.append(regression_loss.mean())
        else:
            regression_losses.append(torch.tensor(0).float().cuda())

    return torch.stack(classification_losses).mean(dim=0, keepdim=True), torch.stack(regression_losses).mean(dim=0, keepdim=True

"""

wvalcke commented 3 years ago

This is not correct. If there is no annotation, we need to calculate the classification loss, the regression loss will be zero in this case, but NOT the classification loss. You're training then network on a hard negative sample, meaning you want it NOT to detect any object. So all outputs for the classification should be 0 for each object type.

liuzonglei0713 commented 3 years ago

I see, i am worng.

------------------ 原始邮件 ------------------ 发件人: "yhenon/pytorch-retinanet" <notifications@github.com>; 发送时间: 2020年11月7日(星期六) 凌晨3:30 收件人: "yhenon/pytorch-retinanet"<pytorch-retinanet@noreply.github.com>; 抄送: "梅 兰 竹 菊"<1148953314@qq.com>;"Author"<author@noreply.github.com>; 主题: Re: [yhenon/pytorch-retinanet] the loss file has some wrong (#196)

This is not correct. If there is no annotation, we need to calculate the classification loss, the regression loss will be zero in this case, but NOT the classification loss. You're training then network on a hard negative sample, meaning you want it NOT to detect any object. So all outputs for the classification should be 0 for each object type.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.