class_docstr: FreeAnchor RetinaHead used in https://arxiv.org/abs/1909.02466.
  
  Args:
      num_classes (int): Number of categories excluding the background
          category.
      in_channels (int): Number of channels in the input feature map.
      stacked_convs (int): Number of conv layers in cls and reg tower.
          Defaults to 4.
      conv_cfg (:obj:`ConfigDict` or dict, optional): dictionary to
          construct and config conv layer. Defaults to None.
      norm_cfg (:obj:`ConfigDict` or dict, optional): dictionary to
          construct and config norm layer. Defaults to
          norm_cfg=dict(type='GN', num_groups=32, requires_grad=True).
      pre_anchor_topk (int): Number of boxes that be token in each bag.
          Defaults to 50
      bbox_thr (float): The threshold of the saturated linear function.
          It is usually the same with the IoU threshold used in NMS.
          Defaults to 0.6.
      gamma (float): Gamma parameter in focal loss. Defaults to 2.0.
      alpha (float): Alpha parameter in focal loss. Defaults to 0.5.
class_docstr_tok: ["FreeAnchor","RetinaHead","used","in","https",":","\/\/arxiv.org\/abs\/1909.02466",".","Args",":","num_classes","(","int",")",":","Number","of","categories","excluding","the","background","category",".","in_channels","(","int",")",":","Number","of","channels","in","the","input","feature","map",".","stacked_convs","(","int",")",":","Number","of","conv","layers","in","cls","and","reg","tower",".","Defaults","to","4.","conv_cfg","(",":","obj",":","`","ConfigDict","`","or","dict",",","optional",")",":","dictionary","to","construct","and","config","conv","layer",".","Defaults","to","None",".","norm_cfg","(",":","obj",":","`","ConfigDict","`","or","dict",",","optional",")",":","dictionary","to","construct","and","config","norm","layer",".","Defaults","to","norm_cfg=dict","(","type='GN","'",",","num_groups=32",",","requires_grad=True",")",".","pre_anchor_topk","(","int",")",":","Number","of","boxes","that","be","token","in","each","bag",".","Defaults","to","50","bbox_thr","(","float",")",":","The","threshold","of","the","saturated","linear","function",".","It","is","usually","the","same","with","the","IoU","threshold","used","in","NMS",".","Defaults","to","0.6.","gamma","(","float",")",":","Gamma","parameter","in","focal","loss",".","Defaults","to","2.0.","alpha","(","float",")",":","Alpha","parameter","in","focal","loss",".","Defaults","to","0.5","."]
docstr: Compute positive loss.
  
  Args:
      cls_prob (Tensor): Classification probability of shape
          (num_anchors, num_classes).
      bbox_pred (Tensor): Box probability of shape (num_anchors, 4).
      flat_anchors (Tensor): Multi-level anchors of the image, which are
          concatenated into a single tensor of shape (num_anchors, 4)
      gt_instances (:obj:`InstanceData`): Ground truth of instance
          annotations. It should includes ``bboxes`` and ``labels``
          attributes.
  
  Returns:
      tuple:
  
          - box_prob (Tensor): Box probability of shape (num_anchors, 4).
          - positive_loss (Tensor): Positive loss of shape (num_pos, ).
          - num_pos (int): positive samples indexes.
docstr_tok: ["Compute","positive","loss",".","Args",":","cls_prob","(","Tensor",")",":","Classification","probability","of","shape","(","num_anchors",",","num_classes",")",".","bbox_pred","(","Tensor",")",":","Box","probability","of","shape","(","num_anchors",",","4",")",".","flat_anchors","(","Tensor",")",":","Multi-level","anchors","of","the","image",",","which","are","concatenated","into","a","single","tensor","of","shape","(","num_anchors",",","4",")","gt_instances","(",":","obj",":","`","InstanceData","`",")",":","Ground","truth","of","instance","annotations",".","It","should","includes","``","bboxes","``","and","``","labels","``","attributes",".","Returns",":","tuple",":","-","box_prob","(","Tensor",")",":","Box","probability","of","shape","(","num_anchors",",","4",")",".","-","positive_loss","(","Tensor",")",":","Positive","loss","of","shape","(","num_pos",",",")",".","-","num_pos","(","int",")",":","positive","samples","indexes","."]
code: def positive_loss_single(
      self,
      cls_prob: Tensor,
      bbox_pred: Tensor,
      flat_anchors: Tensor,
      gt_instances: InstanceData,
  ) -> tuple:
      """Compute positive loss.
  
      Args:
          cls_prob (Tensor): Classification probability of shape
              (num_anchors, num_classes).
          bbox_pred (Tensor): Box probability of shape (num_anchors, 4).
          flat_anchors (Tensor): Multi-level anchors of the image, which are
              concatenated into a single tensor of shape (num_anchors, 4)
          gt_instances (:obj:`InstanceData`): Ground truth of instance
              annotations. It should includes ``bboxes`` and ``labels``
              attributes.
  
      Returns:
          tuple:
  
              - box_prob (Tensor): Box probability of shape (num_anchors, 4).
              - positive_loss (Tensor): Positive loss of shape (num_pos, ).
              - num_pos (int): positive samples indexes.
      """
  
      gt_bboxes = gt_instances.bboxes
      gt_labels = gt_instances.labels
      with torch.no_grad():
          if len(gt_bboxes) == 0:
              image_box_prob = torch.zeros(
                  flat_anchors.size(0), self.cls_out_channels
              ).type_as(bbox_pred)
          else:
              # box_localization: a_{j}^{loc}, shape: [j, 4]
              pred_boxes = self.bbox_coder.decode(
                  flat_anchors, bbox_pred
              )
  
              # object_box_iou: IoU_{ij}^{loc}, shape: [i, j]
              object_box_iou = bbox_overlaps(gt_bboxes, pred_boxes)
  
              # object_box_prob: P{a_{j} -> b_{i}}, shape: [i, j]
              t1 = self.bbox_thr
              t2 = object_box_iou.max(dim=1, keepdim=True).values.clamp(
                  min=t1 + 1e-12
              )
              object_box_prob = (
                  (object_box_iou - t1) / (t2 - t1)
              ).clamp(min=0, max=1)
  
              # object_cls_box_prob: P{a_{j} -> b_{i}}, shape: [i, c, j]
              num_obj = gt_labels.size(0)
              indices = torch.stack(
                  [torch.arange(num_obj).type_as(gt_labels), gt_labels],
                  dim=0,
              )
              object_cls_box_prob = torch.sparse_coo_tensor(
                  indices, object_box_prob
              )
  
              # image_box_iou: P{a_{j} \in A_{+}}, shape: [c, j]
              """
                  from "start" to "end" implement:
                  image_box_iou = torch.sparse.max(object_cls_box_prob,
                                                   dim=0).t()
  
                  """
              # start
              box_cls_prob = torch.sparse.sum(
                  object_cls_box_prob, dim=0
              ).to_dense()
  
              indices = torch.nonzero(box_cls_prob, as_tuple=False).t_()
              if indices.numel() == 0:
                  image_box_prob = torch.zeros(
                      flat_anchors.size(0), self.cls_out_channels
                  ).type_as(object_box_prob)
              else:
                  nonzero_box_prob = (
                      torch.where(
                          (gt_labels.unsqueeze(dim=-1) == indices[0]),
                          object_box_prob[:, indices[1]],
                          torch.tensor([0]).type_as(object_box_prob),
                      )
                      .max(dim=0)
                      .values
                  )
  
                  # upmap to shape [j, c]
                  image_box_prob = torch.sparse_coo_tensor(
                      indices.flip([0]),
                      nonzero_box_prob,
                      size=(
                          flat_anchors.size(0),
                          self.cls_out_channels,
                      ),
                  ).to_dense()
              # end
          box_prob = image_box_prob
  
      # construct bags for objects
      match_quality_matrix = bbox_overlaps(gt_bboxes, flat_anchors)
      _, matched = torch.topk(
          match_quality_matrix,
          self.pre_anchor_topk,
          dim=1,
          sorted=False,
      )
      del match_quality_matrix
  
      # matched_cls_prob: P_{ij}^{cls}
      matched_cls_prob = torch.gather(
          cls_prob[matched],
          2,
          gt_labels.view(-1, 1, 1).repeat(1, self.pre_anchor_topk, 1),
      ).squeeze(2)
  
      # matched_box_prob: P_{ij}^{loc}
      matched_anchors = flat_anchors[matched]
      matched_object_targets = self.bbox_coder.encode(
          matched_anchors,
          gt_bboxes.unsqueeze(dim=1).expand_as(matched_anchors),
      )
      loss_bbox = self.loss_bbox(
          bbox_pred[matched],
          matched_object_targets,
          reduction_override="none",
      ).sum(-1)
      matched_box_prob = torch.exp(-loss_bbox)
  
      # positive_losses: {-log( Mean-max(P_{ij}^{cls} * P_{ij}^{loc}) )}
      num_pos = len(gt_bboxes)
      positive_loss = self.positive_bag_loss(
          matched_cls_prob, matched_box_prob
      )
  
      return box_prob, positive_loss, num_pos
  
file_path: mmdetection/mmdet/models/dense_heads/free_anchor_retina_head.py
imports: from typing import List
  import torch
  import torch.nn.functional
  from mmengine.structures import InstanceData
  from torch import Tensor
  from mmdet.registry import MODELS
  from mmdet.structures.bbox import bbox_overlaps
  from mmdet.utils import InstanceList, OptConfigType, OptInstanceList
  from ..utils import multi_apply
  from .retina_head import RetinaHead
label_desc: Use image node_id 3 for calling the FreeAnchorRetinaHead obj's underlying member method code with example usage: obj.positive_loss_single(cls_prob, bbox_pred, flat_anchors, gt_instances) and returns: box_prob,  positive_loss,  num_pos