class_docstr: This class computes an assignment between the targets and the predictions of the network
  For efficiency reasons, the targets don't include the no_object. Because of this, in general,
  there are more predictions than targets. In this case, we do a 1-to-1 matching of the best predictions,
  while the others are un-matched (and thus treated as non-objects).
class_docstr_tok: ["This","class","computes","an","assignment","between","the","targets","and","the","predictions","of","the","network","For","efficiency","reasons",",","the","targets","do","n't","include","the","no_object",".","Because","of","this",",","in","general",",","there","are","more","predictions","than","targets",".","In","this","case",",","we","do","a","1-to-1","matching","of","the","best","predictions",",","while","the","others","are","un-matched","(","and","thus","treated","as","non-objects",")","."]
docstr: 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)
docstr_tok: ["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",")"]
code: 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
      ]
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  from scipy.optimize import linear_sum_assignment
  import paddle
  import paddle.nn
  import paddle.nn.functional
  from paddle.metric import accuracy
  from ppdet.core.workspace import register
  from ppdet.modeling.losses.iou_loss import GIoULoss
label_desc: Use image node_id 2 for calling the HungarianMatcher obj's underlying member method code with example usage: obj.forward(outputs, targets) and returns: unknown, unknown