class_docstr: ATSS head with visual-language fusion module.
  
  Args:
      early_fuse (bool): Whether to fuse visual and language features
          Defaults to False.
      use_checkpoint (bool): Whether to use checkpoint. Defaults to False.
      num_dyhead_blocks (int): Number of dynamic head blocks. Defaults to 6.
      lang_model_name (str): Name of the language model.
          Defaults to 'bert-base-uncased'.
class_docstr_tok: ["ATSS","head","with","visual-language","fusion","module",".","Args",":","early_fuse","(","bool",")",":","Whether","to","fuse","visual","and","language","features","Defaults","to","False",".","use_checkpoint","(","bool",")",":","Whether","to","use","checkpoint",".","Defaults","to","False",".","num_dyhead_blocks","(","int",")",":","Number","of","dynamic","head","blocks",".","Defaults","to","6.","lang_model_name","(","str",")",":","Name","of","the","language","model",".","Defaults","to","'bert-base-uncased","'","."]
docstr: Calculate the loss of all scale level based on the features
  extracted by the detection head.
  
  Returns:
      dict[str, Tensor]: A dictionary of loss components.
docstr_tok: ["Calculate","the","loss","of","all","scale","level","based","on","the","features","extracted","by","the","detection","head",".","Returns",":","dict","[","str",",","Tensor","]",":","A","dictionary","of","loss","components","."]
code: def _loss_by_feat(
      self,
      anchors: Tensor,
      cls_score: Tensor,
      bbox_pred: Tensor,
      centerness: Tensor,
      labels: Tensor,
      label_weights: Tensor,
      bbox_targets: Tensor,
      avg_factor: float,
  ) -> dict:
      """Calculate the loss of all scale level based on the features
      extracted by the detection head.
  
      Returns:
          dict[str, Tensor]: A dictionary of loss components.
      """
  
      anchors = anchors.reshape(-1, 4)
  
      # ===== this change =====
      pos_inds = (labels.sum(-1) > 0).reshape(-1)
  
      # Loss is not computed for the padded regions of the text.
      assert self.text_masks.dim() == 2
      text_mask = (self.text_masks > 0).unsqueeze(1)
      text_mask = text_mask.repeat(1, cls_score.size(1), 1)
      cls_score = torch.masked_select(cls_score, text_mask).contiguous()
      labels = torch.masked_select(labels, text_mask)
      label_weights = label_weights[..., None].repeat(
          1, 1, text_mask.size(-1)
      )
      label_weights = torch.masked_select(label_weights, text_mask)
  
      bbox_pred = bbox_pred.reshape(-1, 4)
      centerness = centerness.reshape(-1)
      bbox_targets = bbox_targets.reshape(-1, 4)
      labels = labels.reshape(-1)
      label_weights = label_weights.reshape(-1)
  
      # classification loss
      loss_cls = self.loss_cls(
          cls_score, labels, label_weights, avg_factor=avg_factor
      )
  
      if pos_inds.sum() > 0:
          pos_bbox_targets = bbox_targets[pos_inds]
          pos_bbox_pred = bbox_pred[pos_inds]
          pos_anchors = anchors[pos_inds]
          pos_centerness = centerness[pos_inds]
  
          centerness_targets = self.centerness_target(
              pos_anchors, pos_bbox_targets
          )
  
          if torch.isnan(centerness_targets).any():
              print("=====Centerness includes NaN=====")
              mask = ~torch.isnan(centerness_targets)
              centerness_targets = centerness_targets[mask]
              pos_centerness = pos_centerness[mask]
              pos_anchors = pos_anchors[mask]
              pos_bbox_targets = pos_bbox_targets[mask]
              pos_bbox_pred = pos_bbox_pred[mask]
  
              if pos_bbox_targets.shape[0] == 0:
                  loss_bbox = bbox_pred.sum() * 0
                  loss_centerness = centerness.sum() * 0
                  centerness_targets = bbox_targets.new_tensor(0.0)
                  return (
                      loss_cls,
                      loss_bbox,
                      loss_centerness,
                      centerness_targets.sum(),
                  )
  
          # The decoding process takes the offset into consideration.
          pos_anchors[:, 2:] += 1
          pos_decode_bbox_pred = self.bbox_coder.decode(
              pos_anchors, pos_bbox_pred
          )
  
          # regression loss
          loss_bbox = self.loss_bbox(
              pos_decode_bbox_pred,
              pos_bbox_targets,
              weight=centerness_targets,
              avg_factor=1.0,
          )
  
          # centerness loss
          loss_centerness = self.loss_centerness(
              pos_centerness, centerness_targets, avg_factor=avg_factor
          )
      else:
          loss_bbox = bbox_pred.sum() * 0
          loss_centerness = centerness.sum() * 0
          centerness_targets = bbox_targets.new_tensor(0.0)
  
      return (
          loss_cls,
          loss_bbox,
          loss_centerness,
          centerness_targets.sum(),
      )
  
imports: import copy
  import math
  from typing import Callable, List, Optional, Sequence, Tuple, Union
  import torch
  import torch.nn
  import torch.nn.functional
  from mmcv.cnn import Scale
  from mmcv.ops.modulated_deform_conv import ModulatedDeformConv2d
  from mmengine.config import ConfigDict
  from mmengine.model import BaseModel
  from mmengine.structures import InstanceData
  from torch import Tensor
  from mmdet.registry import MODELS
  from mmdet.structures.bbox import cat_boxes
  from mmdet.utils import InstanceList, OptInstanceList, reduce_mean
  from ..utils import BertEncoderLayer, VLFuse, filter_scores_and_topk, permute_and_flatten, select_single_mlvl, unpack_gt_instances
  from ..utils.vlfuse_helper import MAX_CLAMP_VALUE
  from .atss_head import ATSSHead
label_desc: Use image node_id 6 for calling the ATSSVLFusionHead obj's underlying member method code with example usage: obj._loss_by_feat(anchors, cls_score, bbox_pred, centerness, labels, label_weights, bbox_targets, avg_factor) and returns: loss_cls,  loss_bbox,  loss_centerness,  centerness_targets, loss_cls,  loss_bbox,  loss_centerness,  centerness_targets