Ejemplo n.º 1
0
        # pdb.set_trace()
        # landmark_delta, loc_delta, conf, feat_dim = net(img)  # forward pass
        landmark_delta, loc_delta, conf = net(img)  # forward pass
        _t['forward_pass'].toc()

        _t['misc'].tic()
        priorbox = PriorBox(cfg['anchor_cfg'],
                            image_size=(img_h, img_w),
                            phase='test')
        # priorbox = PriorBox(cfg['anchor_cfg'], feat_dim, (img_h, img_w), phase='test')
        priors = priorbox.forward()
        if args.cuda:
            priors = priors.cuda()
        # landmarks = decode_landmark(landmark_delta.squeeze(0), priors.data)
        landmarks = decode_ldmk(landmark_delta.squeeze(0), priors.data)
        boxes = decode(loc_delta.data.squeeze(0), priors.data,
                       cfg['anchor_cfg']['variance'])
        boxes = boxes * origin_scale

        landmarks = landmarks * landmark_origin_scale
        landmarks = landmarks.data.cpu().numpy()

        boxes = boxes.data.cpu().numpy()
        scores = conf.data.cpu().numpy()[:, 1]

        if scores.max() < 0.1:
            continue
        num_valid_img = num_valid_img + 1
        # ignore low scores
        inds = np.where(scores > args.confidence_threshold)[0]

        boxes = boxes[inds]
    def forward(self, predictions, predictions_tch, priors, targets):
        """Multibox Loss
        Args:
            predictions (tuple): A tuple containing loc preds, conf preds,
            and prior boxes from SSD net.
                conf shape: torch.size(batch_size,num_priors,num_classes)
                loc shape: torch.size(batch_size,num_priors,4)
                priors shape: torch.size(num_priors,4)

            ground_truth (tensor): Ground truth boxes and labels for a batch,
                shape: [batch_size,num_objs,5] (last idx is the label).
        """

        loc_data, conf_data, _ = predictions
        loc_data_tch, conf_data_tch, _ = predictions_tch

        priors = priors
        num = loc_data.size(0)
        num_priors = (priors.size(0))

        #         pred_boxes = torch.Tensor(num, num_priors, 4)
        #         for i in range(0, num):
        #             pred_boxes[i] = decode(loc_data_tch.data[i], priors.data, self.variance)

        # teacher model's pred boxes
        pred_boxes = list()
        for i in range(0, num):
            # print(loc_data_tch.data[i].size())
            pred_boxes.append(
                decode(loc_data_tch.data[i], priors.data, self.variance))
        #         print(pred_boxes)
        #         print(targets)

        # match priors (default boxes) and ground truth boxes
        loc_t = torch.Tensor(num, num_priors, 4)
        conf_t = torch.LongTensor(num, num_priors)
        for idx in range(num):
            truths = targets[idx][:, :-1].data
            labels = targets[idx][:, -1].data
            tch_pred = pred_boxes[idx].data
            defaults = priors.data
            match(self.threshold, truths, defaults, self.variance, labels,
                  loc_t, conf_t, idx)
            # match_distillation(self.threshold, truths, tch_pred, defaults, self.variance, labels, loc_t, conf_t, idx)
        if GPU:
            loc_t = loc_t.cuda()
            conf_t = conf_t.cuda()
        # wrap targets
        loc_t = Variable(loc_t, requires_grad=False)
        conf_t = Variable(conf_t, requires_grad=False)

        pos = conf_t > 0

        # Localization Loss (Smooth L1)
        # Shape: [batch,num_priors,4]
        pos_idx = pos.unsqueeze(pos.dim()).expand_as(loc_data)
        loc_p = loc_data[pos_idx].view(-1, 4)
        loc_t = loc_t[pos_idx].view(-1, 4)
        loss_l = F.smooth_l1_loss(loc_p, loc_t, size_average=False)

        # Compute max conf across batch for hard negative mining
        batch_conf = conf_data.view(-1, self.num_classes)
        batch_conf_tch = conf_data_tch.view(-1, self.num_classes)
        loss_c = log_sum_exp(batch_conf) - batch_conf.gather(
            1, conf_t.view(-1, 1))

        # Hard Negative Mining
        loss_c[pos.view(-1, 1)] = 0  # filter out pos boxes for now
        loss_c = loss_c.view(num, -1)
        _, loss_idx = loss_c.sort(1, descending=True)
        _, idx_rank = loss_idx.sort(1)
        num_pos = pos.long().sum(1, keepdim=True)
        num_neg = torch.clamp(self.negpos_ratio * num_pos, max=pos.size(1) - 1)
        neg = idx_rank < num_neg.expand_as(idx_rank)

        # Confidence Loss Including Positive and Negative Examples
        pos_idx = pos.unsqueeze(2).expand_as(conf_data)
        neg_idx = neg.unsqueeze(2).expand_as(conf_data)
        conf_p = conf_data[(pos_idx + neg_idx).gt(0)].view(
            -1, self.num_classes)
        targets_weighted = conf_t[(pos + neg).gt(0)]
        loss_c = F.cross_entropy(conf_p, targets_weighted, size_average=False)

        conf_p_tch = conf_data_tch[(pos_idx + neg_idx).gt(0)].view(
            -1, self.num_classes).detach()

        # print('conf_data_tch.requires_grad', conf_p_tch.requires_grad)
        if conf_p.size(0) != 0:
            log_conf_p = F.log_softmax(conf_p, -1)
            log_conf_p_tch = F.log_softmax(conf_p_tch, -1)
            conf_p_tch = F.softmax(conf_p_tch, -1)
            Tq = -conf_p_tch * log_conf_p_tch
            KL = (conf_p_tch * log_conf_p_tch - conf_p_tch * log_conf_p)
            KL_sum_expand = KL.sum(1).unsqueeze(1).expand_as(KL)
            Tq_sum_expand = Tq.sum(1).unsqueeze(1).expand_as(Tq)
            gamma = 2
            beta = 2
            pt = (1 - (-KL_sum_expand - beta * Tq_sum_expand).exp())
            weight = pt.pow(gamma)
            weight = Variable(weight, requires_grad=False)
            loss_c_distillation = (KL * weight).sum()

            # loss_c_distillation = (conf_p_tch * log_conf_p_tch).sum() - (conf_p_tch * log_conf_p).sum()
        else:
            raise NotImplementedError("distillation loss has no sample!")
            loss_c_distillation = loss_c

            # Sum of losses: L(x,c,l,g) = (Lconf(x, c) + αLloc(x,l,g)) / N
        N = max(num_pos.data.sum().float(), 1)
        loss_l /= N
        loss_c /= N
        loss_c_distillation /= N
        return loss_l, loss_c, loss_c_distillation