def forward(self, outputs, targets):
        """ Performs the matching
        Args:
            outputs: This is a dict that contains at least these entries:
                 "pred_logits": Tensor of dim [batch_size, num_queries, num_classes] with the classification logits
                 "pred_boxes": Tensor of dim [batch_size, num_queries, 4] with the predicted box coordinates
                 eg. outputs = {"pred_logits": pred_logits, "pred_boxes": pred_boxes}
            targets: This is a list of targets (len(targets) = batch_size), where each target is a dict containing:
                 "labels": Tensor of dim [num_target_boxes] (where num_target_boxes is the number of ground-truth
                           objects in the target) containing the class labels
                 "boxes": Tensor of dim [num_target_boxes, 4] containing the target box coordinates
                 eg. targets = [{"labels":labels, "boxes": boxes}, ...,{"labels":labels, "boxes": boxes}]
        Returns:
            A list of size batch_size, containing tuples of (index_i, index_j) where:
                - index_i is the indices of the selected predictions (in order)
                - index_j is the indices of the corresponding selected targets (in order)
            For each batch element, it holds:
                len(index_i) = len(index_j) = min(num_queries, num_target_boxes)
        """
        bs, num_queries = outputs["pred_logits"].shape[:2]

        if sum(len(v["labels"]) for v in targets) == 0:
            return [(paddle.to_tensor(
                [], dtype=paddle.int64), paddle.to_tensor(
                    [], dtype=paddle.int64)) for _ in range(bs)]

        # We flatten to compute the cost matrices in a batch
        out_prob = F.sigmoid(outputs["pred_logits"].flatten(
            start_axis=0, stop_axis=1))
        out_bbox = outputs["pred_boxes"].flatten(start_axis=0, stop_axis=1)

        # Also concat the target labels and boxes
        tgt_ids = paddle.concat([v["labels"] for v in targets])
        assert (tgt_ids > -1).all()
        tgt_bbox = paddle.concat([v["boxes"] for v in targets])

        # Compute the classification cost. Contrary to the loss, we don't use the NLL,
        # but approximate it in 1 - proba[target class].
        # The 1 is a constant that doesn't change the matching, it can be ommitted.

        # Compute the classification cost.
        alpha = self.focal_loss_alpha
        gamma = self.focal_loss_gamma

        neg_cost_class = (1 - alpha) * (out_prob**gamma) * (-(
            1 - out_prob + 1e-8).log())
        pos_cost_class = alpha * ((1 - out_prob)
                                  **gamma) * (-(out_prob + 1e-8).log())

        cost_class = paddle.gather(
            pos_cost_class, tgt_ids, axis=1) - paddle.gather(
                neg_cost_class, tgt_ids, axis=1)

        # Compute the L1 cost between boxes
        image_size_out = paddle.concat(
            [v["img_whwh"].unsqueeze(0) for v in targets])
        image_size_out = image_size_out.unsqueeze(1).tile(
            [1, num_queries, 1]).flatten(
                start_axis=0, stop_axis=1)
        image_size_tgt = paddle.concat([v["img_whwh_tgt"] for v in targets])

        out_bbox_ = out_bbox / image_size_out
        tgt_bbox_ = tgt_bbox / image_size_tgt
        cost_bbox = F.l1_loss(
            out_bbox_.unsqueeze(-2), tgt_bbox_,
            reduction='none').sum(-1)  # [batch_size * num_queries, num_tgts]

        # Compute the giou cost betwen boxes
        cost_giou = -get_bboxes_giou(out_bbox, tgt_bbox)

        # Final cost matrix
        C = self.cost_bbox * cost_bbox + self.cost_class * cost_class + self.cost_giou * cost_giou
        C = C.reshape([bs, num_queries, -1])

        sizes = [len(v["boxes"]) for v in targets]

        indices = [
            linear_sum_assignment(c[i].numpy())
            for i, c in enumerate(C.split(sizes, -1))
        ]
        return [(paddle.to_tensor(
            i, dtype="int32"), paddle.to_tensor(
                j, dtype="int32")) for i, j in indices]
 Performs the matching
        Args:
            outputs: This is a dict that contains at least these entries:
                 "pred_logits": Tensor of dim [batch_size, num_queries, num_classes] with the classification logits
                 "pred_boxes": Tensor of dim [batch_size, num_queries, 4] with the predicted box coordinates
                 eg. outputs = {"pred_logits": pred_logits, "pred_boxes": pred_boxes}
            targets: This is a list of targets (len(targets) = batch_size), where each target is a dict containing:
                 "labels": Tensor of dim [num_target_boxes] (where num_target_boxes is the number of ground-truth
                           objects in the target) containing the class labels
                 "boxes": Tensor of dim [num_target_boxes, 4] containing the target box coordinates
                 eg. targets = [{"labels":labels, "boxes": boxes}, ...,{"labels":labels, "boxes": boxes}]
        Returns:
            A list of size batch_size, containing tuples of (index_i, index_j) where:
                - index_i is the indices of the selected predictions (in order)
                - index_j is the indices of the corresponding selected targets (in order)
            For each batch element, it holds:
                len(index_i) = len(index_j) = min(num_queries, num_target_boxes)
        
ppdet/modeling/losses/sparsercnn_loss.py