class_docstr: TOODHead used in `TOOD: Task-aligned One-stage Object Detection.
  
  <https://arxiv.org/abs/2108.07755>`_.
  
  TOOD uses Task-aligned head (T-head) and is optimized by Task Alignment
  Learning (TAL).
  
  Args:
      num_classes (int): Number of categories excluding the background
          category.
      in_channels (int): Number of channels in the input feature map.
      num_dcn (int): Number of deformable convolution in the head.
          Defaults to 0.
      anchor_type (str): If set to ``anchor_free``, the head will use centers
          to regress bboxes. If set to ``anchor_based``, the head will
          regress bboxes based on anchors. Defaults to ``anchor_free``.
      initial_loss_cls (:obj:`ConfigDict` or dict): Config of initial loss.
  
  Example:
      >>> self = TOODHead(11, 7)
      >>> feats = [torch.rand(1, 7, s, s) for s in [4, 8, 16, 32, 64]]
      >>> cls_score, bbox_pred = self.forward(feats)
      >>> assert len(cls_score) == len(self.scales)
class_docstr_tok: ["TOODHead","used","in","`","TOOD",":","Task-aligned","One-stage","Object","Detection",".","<","https",":","\/\/arxiv.org\/abs\/2108.07755",">","`","_",".","TOOD","uses","Task-aligned","head","(","T-head",")","and","is","optimized","by","Task","Alignment","Learning","(","TAL",")",".","Args",":","num_classes","(","int",")",":","Number","of","categories","excluding","the","background","category",".","in_channels","(","int",")",":","Number","of","channels","in","the","input","feature","map",".","num_dcn","(","int",")",":","Number","of","deformable","convolution","in","the","head",".","Defaults","to","0.","anchor_type","(","str",")",":","If","set","to","``","anchor_free","``",",","the","head","will","use","centers","to","regress","bboxes",".","If","set","to","``","anchor_based","``",",","the","head","will","regress","bboxes","based","on","anchors",".","Defaults","to","``","anchor_free","``",".","initial_loss_cls","(",":","obj",":","`","ConfigDict","`","or","dict",")",":","Config","of","initial","loss",".","Example",":",">",">",">","self","=","TOODHead","(","11",",","7",")",">",">",">","feats","=","[","torch.rand","(","1",",","7",",","s",",","s",")","for","s","in","[","4",",","8",",","16",",","32",",","64","]","]",">",">",">","cls_score",",","bbox_pred","=","self.forward","(","feats",")",">",">",">","assert","len","(","cls_score",")","==","len","(","self.scales",")"]
docstr: Forward features from the upstream network.
  
  Args:
      feats (tuple[Tensor]): Features from the upstream network, each is
          a 4D-tensor.
  
  Returns:
      tuple: Usually a tuple of classification scores and bbox prediction
          cls_scores (list[Tensor]): Classification scores for all scale
              levels, each is a 4D-tensor, the channels number is
              num_anchors * num_classes.
          bbox_preds (list[Tensor]): Decoded box for all scale levels,
              each is a 4D-tensor, the channels number is
              num_anchors * 4. In [tl_x, tl_y, br_x, br_y] format.
docstr_tok: ["Forward","features","from","the","upstream","network",".","Args",":","feats","(","tuple","[","Tensor","]",")",":","Features","from","the","upstream","network",",","each","is","a","4D-tensor",".","Returns",":","tuple",":","Usually","a","tuple","of","classification","scores","and","bbox","prediction","cls_scores","(","list","[","Tensor","]",")",":","Classification","scores","for","all","scale","levels",",","each","is","a","4D-tensor",",","the","channels","number","is","num_anchors","*","num_classes",".","bbox_preds","(","list","[","Tensor","]",")",":","Decoded","box","for","all","scale","levels",",","each","is","a","4D-tensor",",","the","channels","number","is","num_anchors","*","4",".","In","[","tl_x",",","tl_y",",","br_x",",","br_y","]","format","."]
code: def forward(self, feats: Tuple[Tensor]) -> Tuple[List[Tensor]]:
      """Forward features from the upstream network.
  
      Args:
          feats (tuple[Tensor]): Features from the upstream network, each is
              a 4D-tensor.
  
      Returns:
          tuple: Usually a tuple of classification scores and bbox prediction
              cls_scores (list[Tensor]): Classification scores for all scale
                  levels, each is a 4D-tensor, the channels number is
                  num_anchors * num_classes.
              bbox_preds (list[Tensor]): Decoded box for all scale levels,
                  each is a 4D-tensor, the channels number is
                  num_anchors * 4. In [tl_x, tl_y, br_x, br_y] format.
      """
      cls_scores = []
      bbox_preds = []
      for idx, (x, scale, stride) in enumerate(
          zip(feats, self.scales, self.prior_generator.strides)
      ):
          b, c, h, w = x.shape
          anchor = self.prior_generator.single_level_grid_priors(
              (h, w), idx, device=x.device
          )
          anchor = torch.cat([anchor for _ in range(b)])
          # extract task interactive features
          inter_feats = []
          for inter_conv in self.inter_convs:
              x = inter_conv(x)
              inter_feats.append(x)
          feat = torch.cat(inter_feats, 1)
  
          # task decomposition
          avg_feat = F.adaptive_avg_pool2d(feat, (1, 1))
          cls_feat = self.cls_decomp(feat, avg_feat)
          reg_feat = self.reg_decomp(feat, avg_feat)
  
          # cls prediction and alignment
          cls_logits = self.tood_cls(cls_feat)
          cls_prob = self.cls_prob_module(feat)
          cls_score = sigmoid_geometric_mean(cls_logits, cls_prob)
  
          # reg prediction and alignment
          if self.anchor_type == "anchor_free":
              reg_dist = scale(self.tood_reg(reg_feat).exp()).float()
              reg_dist = reg_dist.permute(0, 2, 3, 1).reshape(-1, 4)
              reg_bbox = (
                  distance2bbox(
                      self.anchor_center(anchor) / stride[0], reg_dist
                  )
                  .reshape(b, h, w, 4)
                  .permute(0, 3, 1, 2)
              )  # (b, c, h, w)
          elif self.anchor_type == "anchor_based":
              reg_dist = scale(self.tood_reg(reg_feat)).float()
              reg_dist = reg_dist.permute(0, 2, 3, 1).reshape(-1, 4)
              reg_bbox = (
                  self.bbox_coder.decode(anchor, reg_dist)
                  .reshape(b, h, w, 4)
                  .permute(0, 3, 1, 2)
                  / stride[0]
              )
          else:
              raise NotImplementedError(
                  f"Unknown anchor type: {self.anchor_type}."
                  f"Please use `anchor_free` or `anchor_based`."
              )
          reg_offset = self.reg_offset_module(feat)
          bbox_pred = self.deform_sampling(
              reg_bbox.contiguous(), reg_offset.contiguous()
          )
  
          # After deform_sampling, some boxes will become invalid (The
          # left-top point is at the right or bottom of the right-bottom
          # point), which will make the GIoULoss negative.
          invalid_bbox_idx = (bbox_pred[:, [0]] > bbox_pred[:, [2]]) | (
              bbox_pred[:, [1]] > bbox_pred[:, [3]]
          )
          invalid_bbox_idx = invalid_bbox_idx.expand_as(bbox_pred)
          bbox_pred = torch.where(invalid_bbox_idx, reg_bbox, bbox_pred)
  
          cls_scores.append(cls_score)
          bbox_preds.append(bbox_pred)
      return tuple(cls_scores), tuple(bbox_preds)
  
imports: from typing import List, Optional, Tuple
  import torch
  import torch.nn
  import torch.nn.functional
  from mmcv.cnn import ConvModule, Scale
  from mmcv.ops import deform_conv2d
  from mmengine import MessageHub
  from mmengine.config import ConfigDict
  from mmengine.model import bias_init_with_prob, normal_init
  from mmengine.structures import InstanceData
  from torch import Tensor
  from mmdet.registry import MODELS, TASK_UTILS
  from mmdet.structures.bbox import distance2bbox
  from mmdet.utils import ConfigType, InstanceList, OptConfigType, OptInstanceList, reduce_mean
  from ..task_modules.prior_generators import anchor_inside_flags
  from ..utils import filter_scores_and_topk, images_to_levels, multi_apply, sigmoid_geometric_mean, unmap
  from .atss_head import ATSSHead
label_desc: Use image node_id 4 for calling the TOODHead obj's underlying member method code with example usage: obj.forward(feats) and returns: tuple,  tuple