class_docstr: AutoAssignHead head used in AutoAssign.
  
  More details can be found in the `paper
  <https://arxiv.org/abs/2007.03496>`_ .
  
  Args:
      force_topk (bool): Used in center prior initialization to
          handle extremely small gt. Default is False.
      topk (int): The number of points used to calculate the
          center prior when no point falls in gt_bbox. Only work when
          force_topk if True. Defaults to 9.
      pos_loss_weight (float): The loss weight of positive loss
          and with default value 0.25.
      neg_loss_weight (float): The loss weight of negative loss
          and with default value 0.75.
      center_loss_weight (float): The loss weight of center prior
          loss and with default value 0.75.
class_docstr_tok: ["AutoAssignHead","head","used","in","AutoAssign",".","More","details","can","be","found","in","the","`","paper","<","https",":","\/\/arxiv.org\/abs\/2007.03496",">","`","_",".","Args",":","force_topk","(","bool",")",":","Used","in","center","prior","initialization","to","handle","extremely","small","gt",".","Default","is","False",".","topk","(","int",")",":","The","number","of","points","used","to","calculate","the","center","prior","when","no","point","falls","in","gt_bbox",".","Only","work","when","force_topk","if","True",".","Defaults","to","9.","pos_loss_weight","(","float",")",":","The","loss","weight","of","positive","loss","and","with","default","value","0.25.","neg_loss_weight","(","float",")",":","The","loss","weight","of","negative","loss","and","with","default","value","0.75.","center_loss_weight","(","float",")",":","The","loss","weight","of","center","prior","loss","and","with","default","value","0.75","."]
docstr: Calculate the loss based on the features extracted by the detection
  head.
  
  Args:
      cls_scores (list[Tensor]): Box scores for each scale level,
          each is a 4D-tensor, the channel number is
          num_points * num_classes.
      bbox_preds (list[Tensor]): Box energies / deltas for each scale
          level, each is a 4D-tensor, the channel number is
          num_points * 4.
      objectnesses (list[Tensor]): objectness for each scale level, each
          is a 4D-tensor, the channel number is num_points * 1.
      batch_gt_instances (list[:obj:`InstanceData`]): Batch of
          gt_instance. It usually includes ``bboxes`` and ``labels``
          attributes.
      batch_img_metas (list[dict]): Meta information of each image, e.g.,
          image size, scaling factor, etc.
      batch_gt_instances_ignore (list[:obj:`InstanceData`], optional):
          Batch of gt_instances_ignore. It includes ``bboxes`` attribute
          data that is ignored during training and testing.
          Defaults to None.
  
  Returns:
      dict[str, Tensor]: A dictionary of loss components.
docstr_tok: ["Calculate","the","loss","based","on","the","features","extracted","by","the","detection","head",".","Args",":","cls_scores","(","list","[","Tensor","]",")",":","Box","scores","for","each","scale","level",",","each","is","a","4D-tensor",",","the","channel","number","is","num_points","*","num_classes",".","bbox_preds","(","list","[","Tensor","]",")",":","Box","energies","\/","deltas","for","each","scale","level",",","each","is","a","4D-tensor",",","the","channel","number","is","num_points","*","4.","objectnesses","(","list","[","Tensor","]",")",":","objectness","for","each","scale","level",",","each","is","a","4D-tensor",",","the","channel","number","is","num_points","*","1.","batch_gt_instances","(","list","[",":","obj",":","`","InstanceData","`","]",")",":","Batch","of","gt_instance",".","It","usually","includes","``","bboxes","``","and","``","labels","``","attributes",".","batch_img_metas","(","list","[","dict","]",")",":","Meta","information","of","each","image",",","e.g.",",","image","size",",","scaling","factor",",","etc",".","batch_gt_instances_ignore","(","list","[",":","obj",":","`","InstanceData","`","]",",","optional",")",":","Batch","of","gt_instances_ignore",".","It","includes","``","bboxes","``","attribute","data","that","is","ignored","during","training","and","testing",".","Defaults","to","None",".","Returns",":","dict","[","str",",","Tensor","]",":","A","dictionary","of","loss","components","."]
code: def loss_by_feat(
      self,
      cls_scores: List[Tensor],
      bbox_preds: List[Tensor],
      objectnesses: List[Tensor],
      batch_gt_instances: InstanceList,
      batch_img_metas: List[dict],
      batch_gt_instances_ignore: OptInstanceList = None,
  ) -> Dict[str, Tensor]:
      """Calculate the loss based on the features extracted by the detection
      head.
  
      Args:
          cls_scores (list[Tensor]): Box scores for each scale level,
              each is a 4D-tensor, the channel number is
              num_points * num_classes.
          bbox_preds (list[Tensor]): Box energies / deltas for each scale
              level, each is a 4D-tensor, the channel number is
              num_points * 4.
          objectnesses (list[Tensor]): objectness for each scale level, each
              is a 4D-tensor, the channel number is num_points * 1.
          batch_gt_instances (list[:obj:`InstanceData`]): Batch of
              gt_instance. It usually includes ``bboxes`` and ``labels``
              attributes.
          batch_img_metas (list[dict]): Meta information of each image, e.g.,
              image size, scaling factor, etc.
          batch_gt_instances_ignore (list[:obj:`InstanceData`], optional):
              Batch of gt_instances_ignore. It includes ``bboxes`` attribute
              data that is ignored during training and testing.
              Defaults to None.
  
      Returns:
          dict[str, Tensor]: A dictionary of loss components.
      """
  
      assert len(cls_scores) == len(bbox_preds) == len(objectnesses)
      all_num_gt = sum([len(item) for item in batch_gt_instances])
      featmap_sizes = [featmap.size()[-2:] for featmap in cls_scores]
      all_level_points = self.prior_generator.grid_priors(
          featmap_sizes,
          dtype=bbox_preds[0].dtype,
          device=bbox_preds[0].device,
      )
      inside_gt_bbox_mask_list, bbox_targets_list = self.get_targets(
          all_level_points, batch_gt_instances
      )
  
      center_prior_weight_list = []
      temp_inside_gt_bbox_mask_list = []
      for gt_instances, inside_gt_bbox_mask in zip(
          batch_gt_instances, inside_gt_bbox_mask_list
      ):
          center_prior_weight, inside_gt_bbox_mask = self.center_prior(
              all_level_points, gt_instances, inside_gt_bbox_mask
          )
          center_prior_weight_list.append(center_prior_weight)
          temp_inside_gt_bbox_mask_list.append(inside_gt_bbox_mask)
      inside_gt_bbox_mask_list = temp_inside_gt_bbox_mask_list
      mlvl_points = torch.cat(all_level_points, dim=0)
      bbox_preds = levels_to_images(bbox_preds)
      cls_scores = levels_to_images(cls_scores)
      objectnesses = levels_to_images(objectnesses)
  
      reg_loss_list = []
      ious_list = []
      num_points = len(mlvl_points)
  
      for bbox_pred, encoded_targets, inside_gt_bbox_mask in zip(
          bbox_preds, bbox_targets_list, inside_gt_bbox_mask_list
      ):
          temp_num_gt = encoded_targets.size(1)
          expand_mlvl_points = (
              mlvl_points[:, None, :]
              .expand(num_points, temp_num_gt, 2)
              .reshape(-1, 2)
          )
          encoded_targets = encoded_targets.reshape(-1, 4)
          expand_bbox_pred = (
              bbox_pred[:, None, :]
              .expand(num_points, temp_num_gt, 4)
              .reshape(-1, 4)
          )
          decoded_bbox_preds = self.bbox_coder.decode(
              expand_mlvl_points, expand_bbox_pred
          )
          decoded_target_preds = self.bbox_coder.decode(
              expand_mlvl_points, encoded_targets
          )
          with torch.no_grad():
              ious = bbox_overlaps(
                  decoded_bbox_preds,
                  decoded_target_preds,
                  is_aligned=True,
              )
              ious = ious.reshape(num_points, temp_num_gt)
              if temp_num_gt:
                  ious = ious.max(dim=-1, keepdim=True).values.repeat(
                      1, temp_num_gt
                  )
              else:
                  ious = ious.new_zeros(num_points, temp_num_gt)
              ious[~inside_gt_bbox_mask] = 0
              ious_list.append(ious)
          loss_bbox = self.loss_bbox(
              decoded_bbox_preds,
              decoded_target_preds,
              weight=None,
              reduction_override="none",
          )
          reg_loss_list.append(
              loss_bbox.reshape(num_points, temp_num_gt)
          )
  
      cls_scores = [item.sigmoid() for item in cls_scores]
      objectnesses = [item.sigmoid() for item in objectnesses]
      (pos_loss_list,) = multi_apply(
          self.get_pos_loss_single,
          cls_scores,
          objectnesses,
          reg_loss_list,
          batch_gt_instances,
          center_prior_weight_list,
      )
      pos_avg_factor = reduce_mean(
          bbox_pred.new_tensor(all_num_gt)
      ).clamp_(min=1)
      pos_loss = sum(pos_loss_list) / pos_avg_factor
  
      (neg_loss_list,) = multi_apply(
          self.get_neg_loss_single,
          cls_scores,
          objectnesses,
          batch_gt_instances,
          ious_list,
          inside_gt_bbox_mask_list,
      )
      neg_avg_factor = sum(
          item.data.sum() for item in center_prior_weight_list
      )
      neg_avg_factor = reduce_mean(neg_avg_factor).clamp_(min=1)
      neg_loss = sum(neg_loss_list) / neg_avg_factor
  
      center_loss = []
      for i in range(len(batch_img_metas)):
          if inside_gt_bbox_mask_list[i].any():
              center_loss.append(
                  len(batch_gt_instances[i])
                  / center_prior_weight_list[i].sum().clamp_(min=EPS)
              )
          # when width or height of gt_bbox is smaller than stride of p3
          else:
              center_loss.append(center_prior_weight_list[i].sum() * 0)
  
      center_loss = (
          torch.stack(center_loss).mean() * self.center_loss_weight
      )
  
      # avoid dead lock in DDP
      if all_num_gt == 0:
          pos_loss = bbox_preds[0].sum() * 0
          dummy_center_prior_loss = (
              self.center_prior.mean.sum() * 0
              + self.center_prior.sigma.sum() * 0
          )
          center_loss = (
              objectnesses[0].sum() * 0 + dummy_center_prior_loss
          )
  
      loss = dict(
          loss_pos=pos_loss, loss_neg=neg_loss, loss_center=center_loss
      )
  
      return loss
  
imports: from typing import Dict, List, Sequence, Tuple
  import torch
  import torch.nn
  import torch.nn.functional
  from mmcv.cnn import Scale
  from mmengine.model import bias_init_with_prob, normal_init
  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, OptInstanceList, reduce_mean
  from ..task_modules.prior_generators import MlvlPointGenerator
  from ..utils import levels_to_images, multi_apply
  from .fcos_head import FCOSHead
label_desc: Use image node_id 6 for calling the AutoAssignHead obj's underlying member method code with example usage: obj.loss_by_feat(cls_scores, bbox_preds, objectnesses, batch_gt_instances, batch_img_metas, batch_gt_instances_ignore) and returns: loss