class_docstr: Localization distillation Head. (Short description)
  
  It utilizes the learned bbox distributions to transfer the localization
  dark knowledge from teacher to student. Original paper: `Localization
  Distillation for Object Detection. <https://arxiv.org/abs/2102.12252>`_
  
  Args:
      num_classes (int): Number of categories excluding the background
          category.
      in_channels (int): Number of channels in the input feature map.
      loss_ld (:obj:`ConfigDict` or dict): Config of Localization
          Distillation Loss (LD), T is the temperature for distillation.
class_docstr_tok: ["Localization","distillation","Head",".","(","Short","description",")","It","utilizes","the","learned","bbox","distributions","to","transfer","the","localization","dark","knowledge","from","teacher","to","student",".","Original","paper",":","`","Localization","Distillation","for","Object","Detection",".","<","https",":","\/\/arxiv.org\/abs\/2102.12252",">","`","_","Args",":","num_classes","(","int",")",":","Number","of","categories","excluding","the","background","category",".","in_channels","(","int",")",":","Number","of","channels","in","the","input","feature","map",".","loss_ld","(",":","obj",":","`","ConfigDict","`","or","dict",")",":","Config","of","Localization","Distillation","Loss","(","LD",")",",","T","is","the","temperature","for","distillation","."]
docstr: Calculate the loss of a single scale level based on the features
  extracted by the detection head.
  
  Args:
      anchors (Tensor): Box reference for each scale level with shape
          (N, num_total_anchors, 4).
      cls_score (Tensor): Cls and quality joint scores for each scale
          level has shape (N, num_classes, H, W).
      bbox_pred (Tensor): Box distribution logits for each scale
          level with shape (N, 4*(n+1), H, W), n is max value of integral
          set.
      labels (Tensor): Labels of each anchors with shape
          (N, num_total_anchors).
      label_weights (Tensor): Label weights of each anchor with shape
          (N, num_total_anchors)
      bbox_targets (Tensor): BBox regression targets of each anchor with
          shape (N, num_total_anchors, 4).
      stride (tuple): Stride in this scale level.
      soft_targets (Tensor): Soft BBox regression targets.
      avg_factor (int): Average factor that is used to average
          the loss. When using sampling method, avg_factor is usually
          the sum of positive and negative priors. When using
          `PseudoSampler`, `avg_factor` is usually equal to the number
          of positive priors.
  
  Returns:
      dict[tuple, Tensor]: Loss components and weight targets.
docstr_tok: ["Calculate","the","loss","of","a","single","scale","level","based","on","the","features","extracted","by","the","detection","head",".","Args",":","anchors","(","Tensor",")",":","Box","reference","for","each","scale","level","with","shape","(","N",",","num_total_anchors",",","4",")",".","cls_score","(","Tensor",")",":","Cls","and","quality","joint","scores","for","each","scale","level","has","shape","(","N",",","num_classes",",","H",",","W",")",".","bbox_pred","(","Tensor",")",":","Box","distribution","logits","for","each","scale","level","with","shape","(","N",",","4","*","(","n+1",")",",","H",",","W",")",",","n","is","max","value","of","integral","set",".","labels","(","Tensor",")",":","Labels","of","each","anchors","with","shape","(","N",",","num_total_anchors",")",".","label_weights","(","Tensor",")",":","Label","weights","of","each","anchor","with","shape","(","N",",","num_total_anchors",")","bbox_targets","(","Tensor",")",":","BBox","regression","targets","of","each","anchor","with","shape","(","N",",","num_total_anchors",",","4",")",".","stride","(","tuple",")",":","Stride","in","this","scale","level",".","soft_targets","(","Tensor",")",":","Soft","BBox","regression","targets",".","avg_factor","(","int",")",":","Average","factor","that","is","used","to","average","the","loss",".","When","using","sampling","method",",","avg_factor","is","usually","the","sum","of","positive","and","negative","priors",".","When","using","`","PseudoSampler","`",",","`","avg_factor","`","is","usually","equal","to","the","number","of","positive","priors",".","Returns",":","dict","[","tuple",",","Tensor","]",":","Loss","components","and","weight","targets","."]
code: def loss_by_feat_single(
      self,
      anchors: Tensor,
      cls_score: Tensor,
      bbox_pred: Tensor,
      labels: Tensor,
      label_weights: Tensor,
      bbox_targets: Tensor,
      stride: Tuple[int],
      soft_targets: Tensor,
      avg_factor: int,
  ):
      """Calculate the loss of a single scale level based on the features
      extracted by the detection head.
  
      Args:
          anchors (Tensor): Box reference for each scale level with shape
              (N, num_total_anchors, 4).
          cls_score (Tensor): Cls and quality joint scores for each scale
              level has shape (N, num_classes, H, W).
          bbox_pred (Tensor): Box distribution logits for each scale
              level with shape (N, 4*(n+1), H, W), n is max value of integral
              set.
          labels (Tensor): Labels of each anchors with shape
              (N, num_total_anchors).
          label_weights (Tensor): Label weights of each anchor with shape
              (N, num_total_anchors)
          bbox_targets (Tensor): BBox regression targets of each anchor with
              shape (N, num_total_anchors, 4).
          stride (tuple): Stride in this scale level.
          soft_targets (Tensor): Soft BBox regression targets.
          avg_factor (int): Average factor that is used to average
              the loss. When using sampling method, avg_factor is usually
              the sum of positive and negative priors. When using
              `PseudoSampler`, `avg_factor` is usually equal to the number
              of positive priors.
  
      Returns:
          dict[tuple, Tensor]: Loss components and weight targets.
      """
      assert (
          stride[0] == stride[1]
      ), "h stride is not equal to w stride!"
      anchors = anchors.reshape(-1, 4)
      cls_score = cls_score.permute(0, 2, 3, 1).reshape(
          -1, self.cls_out_channels
      )
      bbox_pred = bbox_pred.permute(0, 2, 3, 1).reshape(
          -1, 4 * (self.reg_max + 1)
      )
      soft_targets = soft_targets.permute(0, 2, 3, 1).reshape(
          -1, 4 * (self.reg_max + 1)
      )
  
      bbox_targets = bbox_targets.reshape(-1, 4)
      labels = labels.reshape(-1)
      label_weights = label_weights.reshape(-1)
  
      # FG cat_id: [0, num_classes -1], BG cat_id: num_classes
      bg_class_ind = self.num_classes
      pos_inds = (
          ((labels >= 0) & (labels < bg_class_ind)).nonzero().squeeze(1)
      )
      score = label_weights.new_zeros(labels.shape)
  
      if len(pos_inds) > 0:
          pos_bbox_targets = bbox_targets[pos_inds]
          pos_bbox_pred = bbox_pred[pos_inds]
          pos_anchors = anchors[pos_inds]
          pos_anchor_centers = (
              self.anchor_center(pos_anchors) / stride[0]
          )
  
          weight_targets = cls_score.detach().sigmoid()
          weight_targets = weight_targets.max(dim=1)[0][pos_inds]
          pos_bbox_pred_corners = self.integral(pos_bbox_pred)
          pos_decode_bbox_pred = self.bbox_coder.decode(
              pos_anchor_centers, pos_bbox_pred_corners
          )
          pos_decode_bbox_targets = pos_bbox_targets / stride[0]
          score[pos_inds] = bbox_overlaps(
              pos_decode_bbox_pred.detach(),
              pos_decode_bbox_targets,
              is_aligned=True,
          )
          pred_corners = pos_bbox_pred.reshape(-1, self.reg_max + 1)
          pos_soft_targets = soft_targets[pos_inds]
          soft_corners = pos_soft_targets.reshape(-1, self.reg_max + 1)
  
          target_corners = self.bbox_coder.encode(
              pos_anchor_centers, pos_decode_bbox_targets, self.reg_max
          ).reshape(-1)
  
          # regression loss
          loss_bbox = self.loss_bbox(
              pos_decode_bbox_pred,
              pos_decode_bbox_targets,
              weight=weight_targets,
              avg_factor=1.0,
          )
  
          # dfl loss
          loss_dfl = self.loss_dfl(
              pred_corners,
              target_corners,
              weight=weight_targets[:, None].expand(-1, 4).reshape(-1),
              avg_factor=4.0,
          )
  
          # ld loss
          loss_ld = self.loss_ld(
              pred_corners,
              soft_corners,
              weight=weight_targets[:, None].expand(-1, 4).reshape(-1),
              avg_factor=4.0,
          )
  
      else:
          loss_ld = bbox_pred.sum() * 0
          loss_bbox = bbox_pred.sum() * 0
          loss_dfl = bbox_pred.sum() * 0
          weight_targets = bbox_pred.new_tensor(0)
  
      # cls (qfl) loss
      loss_cls = self.loss_cls(
          cls_score,
          (labels, score),
          weight=label_weights,
          avg_factor=avg_factor,
      )
  
      return (
          loss_cls,
          loss_bbox,
          loss_dfl,
          loss_ld,
          weight_targets.sum(),
      )
  
file_path: mmdetection/mmdet/models/dense_heads/ld_head.py
imports: from typing import List, Tuple
  import torch
  from torch import Tensor
  from mmdet.registry import MODELS
  from mmdet.structures import SampleList
  from mmdet.structures.bbox import bbox_overlaps
  from mmdet.utils import ConfigType, InstanceList, OptInstanceList, reduce_mean
  from ..utils import multi_apply, unpack_gt_instances
  from .gfl_head import GFLHead
label_desc: Use image node_id 2 for calling the LDHead obj's underlying member method code with example usage: obj.loss_by_feat_single(anchors, cls_score, bbox_pred, labels, label_weights, bbox_targets, stride, soft_targets, avg_factor) and returns: loss_cls,  loss_bbox,  loss_dfl,  loss_ld,  weight_targets