class_docstr: Anchor-free head used in `FSAF <https://arxiv.org/abs/1903.00621>`_.
  
  The head contains two subnetworks. The first classifies anchor boxes and
  the second regresses deltas for the anchors (num_anchors is 1 for anchor-
  free methods)
  
  Args:
      *args: Same as its base class in :class:`RetinaHead`
      score_threshold (float, optional): The score_threshold to calculate
          positive recall. If given, prediction scores lower than this value
          is counted as incorrect prediction. Defaults to None.
      init_cfg (:obj:`ConfigDict` or dict or list[:obj:`ConfigDict` or             dict]): Initialization config dict.
      **kwargs: Same as its base class in :class:`RetinaHead`
  
  Example:
      >>> import torch
      >>> self = FSAFHead(11, 7)
      >>> x = torch.rand(1, 7, 32, 32)
      >>> cls_score, bbox_pred = self.forward_single(x)
      >>> # Each anchor predicts a score for each class except background
      >>> cls_per_anchor = cls_score.shape[1] / self.num_anchors
      >>> box_per_anchor = bbox_pred.shape[1] / self.num_anchors
      >>> assert cls_per_anchor == self.num_classes
      >>> assert box_per_anchor == 4
class_docstr_tok: ["Anchor-free","head","used","in","`","FSAF","<","https",":","\/\/arxiv.org\/abs\/1903.00621",">","`","_",".","The","head","contains","two","subnetworks",".","The","first","classifies","anchor","boxes","and","the","second","regresses","deltas","for","the","anchors","(","num_anchors","is","1","for","anchor-","free","methods",")","Args",":","*","args",":","Same","as","its","base","class","in",":","class",":","`","RetinaHead","`","score_threshold","(","float",",","optional",")",":","The","score_threshold","to","calculate","positive","recall",".","If","given",",","prediction","scores","lower","than","this","value","is","counted","as","incorrect","prediction",".","Defaults","to","None",".","init_cfg","(",":","obj",":","`","ConfigDict","`","or","dict","or","list","[",":","obj",":","`","ConfigDict","`","or","dict","]",")",":","Initialization","config","dict",".","*","*","kwargs",":","Same","as","its","base","class","in",":","class",":","`","RetinaHead","`","Example",":",">",">",">","import","torch",">",">",">","self","=","FSAFHead","(","11",",","7",")",">",">",">","x","=","torch.rand","(","1",",","7",",","32",",","32",")",">",">",">","cls_score",",","bbox_pred","=","self.forward_single","(","x",")",">",">",">","#","Each","anchor","predicts","a","score","for","each","class","except","background",">",">",">","cls_per_anchor","=","cls_score.shape","[","1","]","\/","self.num_anchors",">",">",">","box_per_anchor","=","bbox_pred.shape","[","1","]","\/","self.num_anchors",">",">",">","assert","cls_per_anchor","==","self.num_classes",">",">",">","assert","box_per_anchor","==","4"]
docstr: Compute loss of the head.
  
  Args:
      cls_scores (list[Tensor]): Box scores for each scale level
          Has shape (N, num_points * num_classes, H, W).
      bbox_preds (list[Tensor]): Box energies / deltas for each scale
          level with shape (N, num_points * 4, H, W).
      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: ["Compute","loss","of","the","head",".","Args",":","cls_scores","(","list","[","Tensor","]",")",":","Box","scores","for","each","scale","level","Has","shape","(","N",",","num_points","*","num_classes",",","H",",","W",")",".","bbox_preds","(","list","[","Tensor","]",")",":","Box","energies","\/","deltas","for","each","scale","level","with","shape","(","N",",","num_points","*","4",",","H",",","W",")",".","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],
      batch_gt_instances: InstanceList,
      batch_img_metas: List[dict],
      batch_gt_instances_ignore: OptInstanceList = None,
  ) -> Dict[str, Tensor]:
      """Compute loss of the head.
  
      Args:
          cls_scores (list[Tensor]): Box scores for each scale level
              Has shape (N, num_points * num_classes, H, W).
          bbox_preds (list[Tensor]): Box energies / deltas for each scale
              level with shape (N, num_points * 4, H, W).
          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.
      """
      for i in range(len(bbox_preds)):  # loop over fpn level
          # avoid 0 area of the predicted bbox
          bbox_preds[i] = bbox_preds[i].clamp(min=1e-4)
      # TODO: It may directly use the base-class loss function.
      featmap_sizes = [featmap.size()[-2:] for featmap in cls_scores]
      assert len(featmap_sizes) == self.prior_generator.num_levels
      batch_size = len(batch_img_metas)
      device = cls_scores[0].device
      anchor_list, valid_flag_list = self.get_anchors(
          featmap_sizes, batch_img_metas, device=device
      )
      cls_reg_targets = self.get_targets(
          anchor_list,
          valid_flag_list,
          batch_gt_instances,
          batch_img_metas,
          batch_gt_instances_ignore=batch_gt_instances_ignore,
          return_sampling_results=True,
      )
      (
          labels_list,
          label_weights_list,
          bbox_targets_list,
          bbox_weights_list,
          avg_factor,
          sampling_results_list,
          pos_assigned_gt_inds_list,
      ) = cls_reg_targets
  
      num_gts = np.array(list(map(len, batch_gt_instances)))
      # anchor number of multi levels
      num_level_anchors = [
          anchors.size(0) for anchors in anchor_list[0]
      ]
      # concat all level anchors and flags to a single tensor
      concat_anchor_list = []
      for i in range(len(anchor_list)):
          concat_anchor_list.append(torch.cat(anchor_list[i]))
      all_anchor_list = images_to_levels(
          concat_anchor_list, num_level_anchors
      )
      losses_cls, losses_bbox = multi_apply(
          self.loss_by_feat_single,
          cls_scores,
          bbox_preds,
          all_anchor_list,
          labels_list,
          label_weights_list,
          bbox_targets_list,
          bbox_weights_list,
          avg_factor=avg_factor,
      )
  
      # `pos_assigned_gt_inds_list` (length: fpn_levels) stores the assigned
      # gt index of each anchor bbox in each fpn level.
      cum_num_gts = list(np.cumsum(num_gts))  # length of batch_size
      for i, assign in enumerate(pos_assigned_gt_inds_list):
          # loop over fpn levels
          for j in range(1, batch_size):
              # loop over batch size
              # Convert gt indices in each img to those in the batch
              assign[j][assign[j] >= 0] += int(cum_num_gts[j - 1])
          pos_assigned_gt_inds_list[i] = assign.flatten()
          labels_list[i] = labels_list[i].flatten()
      num_gts = num_gts.sum()  # total number of gt in the batch
      # The unique label index of each gt in the batch
      label_sequence = torch.arange(num_gts, device=device)
      # Collect the average loss of each gt in each level
      with torch.no_grad():
          (loss_levels,) = multi_apply(
              self.collect_loss_level_single,
              losses_cls,
              losses_bbox,
              pos_assigned_gt_inds_list,
              labels_seq=label_sequence,
          )
          # Shape: (fpn_levels, num_gts). Loss of each gt at each fpn level
          loss_levels = torch.stack(loss_levels, dim=0)
          # Locate the best fpn level for loss back-propagation
          if loss_levels.numel() == 0:  # zero gt
              argmin = loss_levels.new_empty(
                  (num_gts,), dtype=torch.long
              )
          else:
              _, argmin = loss_levels.min(dim=0)
  
      # Reweight the loss of each (anchor, label) pair, so that only those
      #  at the best gt level are back-propagated.
      losses_cls, losses_bbox, pos_inds = multi_apply(
          self.reweight_loss_single,
          losses_cls,
          losses_bbox,
          pos_assigned_gt_inds_list,
          labels_list,
          list(range(len(losses_cls))),
          min_levels=argmin,
      )
      num_pos = torch.cat(pos_inds, 0).sum().float()
      pos_recall = self.calculate_pos_recall(
          cls_scores, labels_list, pos_inds
      )
  
      if num_pos == 0:  # No gt
          num_total_neg = sum(
              [results.num_neg for results in sampling_results_list]
          )
          avg_factor = num_pos + num_total_neg
      else:
          avg_factor = num_pos
      for i in range(len(losses_cls)):
          losses_cls[i] /= avg_factor
          losses_bbox[i] /= avg_factor
      return dict(
          loss_cls=losses_cls,
          loss_bbox=losses_bbox,
          num_pos=num_pos / batch_size,
          pos_recall=pos_recall,
      )
  
imports: from typing import Dict, List, Optional, Tuple
  import numpy
  import torch
  from mmengine.structures import InstanceData
  from torch import Tensor
  from mmdet.registry import MODELS
  from mmdet.utils import InstanceList, OptInstanceList, OptMultiConfig
  from ..losses.accuracy import accuracy
  from ..losses.utils import weight_reduce_loss
  from ..task_modules.prior_generators import anchor_inside_flags
  from ..utils import images_to_levels, multi_apply, unmap
  from .retina_head import RetinaHead
label_desc: Use image node_id 4 for calling the FSAFHead obj's underlying member method code with example usage: obj.loss_by_feat(cls_scores, bbox_preds, batch_gt_instances, batch_img_metas, batch_gt_instances_ignore) and returns: dict