class_docstr: Head of PAAAssignment: Probabilistic Anchor Assignment with IoU
  Prediction for Object Detection.
  
  Code is modified from the `official github repo
  <https://github.com/kkhoot/PAA/blob/master/paa_core
  /modeling/rpn/paa/loss.py>`_.
  
  More details can be found in the `paper
  <https://arxiv.org/abs/2007.08103>`_ .
  
  Args:
      topk (int): Select topk samples with smallest loss in
          each level.
      score_voting (bool): Whether to use score voting in post-process.
      covariance_type : String describing the type of covariance parameters
          to be used in :class:`sklearn.mixture.GaussianMixture`.
          It must be one of:
  
          - 'full': each component has its own general covariance matrix
          - 'tied': all components share the same general covariance matrix
          - 'diag': each component has its own diagonal covariance matrix
          - 'spherical': each component has its own single variance
          Default: 'diag'. From 'full' to 'spherical', the gmm fitting
          process is faster yet the performance could be influenced. For most
          cases, 'diag' should be a good choice.
docstr: Fit loss to GMM distribution and separate positive, ignore, negative
  samples again with GMM model.
  
  Args:
      pos_losses (Tensor): Losses of all positive samples in
          single image.
      label (Tensor): classification target of each anchor with
          shape (num_anchors,)
      label_weight (Tensor): Classification loss weight of each
          anchor with shape (num_anchors).
      bbox_weight (Tensor): Bbox weight of each anchor with shape
          (num_anchors, 4).
      pos_inds (Tensor): Index of all positive samples got from
          first assign process.
      pos_gt_inds (Tensor): Gt_index of all positive samples got
          from first assign process.
      anchors (list[Tensor]): Anchors of each scale.
  
  Returns:
      tuple: Usually returns a tuple containing learning targets.
  
          - label (Tensor): classification target of each anchor after
            paa assign, with shape (num_anchors,)
          - label_weight (Tensor): Classification loss weight of each
            anchor after paa assign, with shape (num_anchors).
          - bbox_weight (Tensor): Bbox weight of each anchor with shape
            (num_anchors, 4).
          - num_pos (int): The number of positive samples after paa
            assign.
docstr_tok: ["Fit","loss","to","GMM","distribution","and","separate","positive",",","ignore",",","negative","samples","again","with","GMM","model",".","Args",":","pos_losses","(","Tensor",")",":","Losses","of","all","positive","samples","in","single","image",".","label","(","Tensor",")",":","classification","target","of","each","anchor","with","shape","(","num_anchors",",",")","label_weight","(","Tensor",")",":","Classification","loss","weight","of","each","anchor","with","shape","(","num_anchors",")",".","bbox_weight","(","Tensor",")",":","Bbox","weight","of","each","anchor","with","shape","(","num_anchors",",","4",")",".","pos_inds","(","Tensor",")",":","Index","of","all","positive","samples","got","from","first","assign","process",".","pos_gt_inds","(","Tensor",")",":","Gt_index","of","all","positive","samples","got","from","first","assign","process",".","anchors","(","list","[","Tensor","]",")",":","Anchors","of","each","scale",".","Returns",":","tuple",":","Usually","returns","a","tuple","containing","learning","targets",".","-","label","(","Tensor",")",":","classification","target","of","each","anchor","after","paa","assign",",","with","shape","(","num_anchors",",",")","-","label_weight","(","Tensor",")",":","Classification","loss","weight","of","each","anchor","after","paa","assign",",","with","shape","(","num_anchors",")",".","-","bbox_weight","(","Tensor",")",":","Bbox","weight","of","each","anchor","with","shape","(","num_anchors",",","4",")",".","-","num_pos","(","int",")",":","The","number","of","positive","samples","after","paa","assign","."]
code: def paa_reassign(
      self,
      pos_losses: Tensor,
      label: Tensor,
      label_weight: Tensor,
      bbox_weight: Tensor,
      pos_inds: Tensor,
      pos_gt_inds: Tensor,
      anchors: List[Tensor],
  ) -> tuple:
      """Fit loss to GMM distribution and separate positive, ignore, negative
      samples again with GMM model.
  
      Args:
          pos_losses (Tensor): Losses of all positive samples in
              single image.
          label (Tensor): classification target of each anchor with
              shape (num_anchors,)
          label_weight (Tensor): Classification loss weight of each
              anchor with shape (num_anchors).
          bbox_weight (Tensor): Bbox weight of each anchor with shape
              (num_anchors, 4).
          pos_inds (Tensor): Index of all positive samples got from
              first assign process.
          pos_gt_inds (Tensor): Gt_index of all positive samples got
              from first assign process.
          anchors (list[Tensor]): Anchors of each scale.
  
      Returns:
          tuple: Usually returns a tuple containing learning targets.
  
              - label (Tensor): classification target of each anchor after
                paa assign, with shape (num_anchors,)
              - label_weight (Tensor): Classification loss weight of each
                anchor after paa assign, with shape (num_anchors).
              - bbox_weight (Tensor): Bbox weight of each anchor with shape
                (num_anchors, 4).
              - num_pos (int): The number of positive samples after paa
                assign.
      """
      if not len(pos_inds):
          return label, label_weight, bbox_weight, 0
      label = label.clone()
      label_weight = label_weight.clone()
      bbox_weight = bbox_weight.clone()
      num_gt = pos_gt_inds.max() + 1
      num_level = len(anchors)
      num_anchors_each_level = [item.size(0) for item in anchors]
      num_anchors_each_level.insert(0, 0)
      inds_level_interval = np.cumsum(num_anchors_each_level)
      pos_level_mask = []
      for i in range(num_level):
          mask = (pos_inds >= inds_level_interval[i]) & (
              pos_inds < inds_level_interval[i + 1]
          )
          pos_level_mask.append(mask)
      pos_inds_after_paa = [label.new_tensor([])]
      ignore_inds_after_paa = [label.new_tensor([])]
      for gt_ind in range(num_gt):
          pos_inds_gmm = []
          pos_loss_gmm = []
          gt_mask = pos_gt_inds == gt_ind
          for level in range(num_level):
              level_mask = pos_level_mask[level]
              level_gt_mask = level_mask & gt_mask
              value, topk_inds = pos_losses[level_gt_mask].topk(
                  min(level_gt_mask.sum(), self.topk), largest=False
              )
              pos_inds_gmm.append(pos_inds[level_gt_mask][topk_inds])
              pos_loss_gmm.append(value)
          pos_inds_gmm = torch.cat(pos_inds_gmm)
          pos_loss_gmm = torch.cat(pos_loss_gmm)
          # fix gmm need at least two sample
          if len(pos_inds_gmm) < 2:
              continue
          device = pos_inds_gmm.device
          pos_loss_gmm, sort_inds = pos_loss_gmm.sort()
          pos_inds_gmm = pos_inds_gmm[sort_inds]
          pos_loss_gmm = pos_loss_gmm.view(-1, 1).cpu().numpy()
          min_loss, max_loss = pos_loss_gmm.min(), pos_loss_gmm.max()
          means_init = np.array([min_loss, max_loss]).reshape(2, 1)
          weights_init = np.array([0.5, 0.5])
          precisions_init = np.array([1.0, 1.0]).reshape(
              2, 1, 1
          )  # full
          if self.covariance_type == "spherical":
              precisions_init = precisions_init.reshape(2)
          elif self.covariance_type == "diag":
              precisions_init = precisions_init.reshape(2, 1)
          elif self.covariance_type == "tied":
              precisions_init = np.array([[1.0]])
          if skm is None:
              raise ImportError(
                  'Please run "pip install sklearn" '
                  "to install sklearn first."
              )
          gmm = skm.GaussianMixture(
              2,
              weights_init=weights_init,
              means_init=means_init,
              precisions_init=precisions_init,
              covariance_type=self.covariance_type,
          )
          gmm.fit(pos_loss_gmm)
          gmm_assignment = gmm.predict(pos_loss_gmm)
          scores = gmm.score_samples(pos_loss_gmm)
          gmm_assignment = torch.from_numpy(gmm_assignment).to(device)
          scores = torch.from_numpy(scores).to(device)
  
          pos_inds_temp, ignore_inds_temp = self.gmm_separation_scheme(
              gmm_assignment, scores, pos_inds_gmm
          )
          pos_inds_after_paa.append(pos_inds_temp)
          ignore_inds_after_paa.append(ignore_inds_temp)
  
      pos_inds_after_paa = torch.cat(pos_inds_after_paa)
      ignore_inds_after_paa = torch.cat(ignore_inds_after_paa)
      reassign_mask = (pos_inds.unsqueeze(1) != pos_inds_after_paa).all(
          1
      )
      reassign_ids = pos_inds[reassign_mask]
      label[reassign_ids] = self.num_classes
      label_weight[ignore_inds_after_paa] = 0
      bbox_weight[reassign_ids] = 0
      num_pos = len(pos_inds_after_paa)
      return label, label_weight, bbox_weight, num_pos
  
imports: from typing import List, Optional, Tuple
  import numpy
  import torch
  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 ConfigType, InstanceList, OptConfigType, OptInstanceList
  from ..layers import multiclass_nms
  from ..utils import levels_to_images, multi_apply
  from .None import ATSSHead
label_desc: Use image node_id 4 for calling the PAAHead obj's underlying member method code with example usage: obj.paa_reassign(pos_losses, label, label_weight, bbox_weight, pos_inds, pos_gt_inds, anchors) and returns: label,  label_weight,  bbox_weight,  num_pos, label,  label_weight,  bbox_weight,  int