code: def carl_loss(
      cls_score: Tensor,
      labels: Tensor,
      bbox_pred: Tensor,
      bbox_targets: Tensor,
      loss_bbox: nn.Module,
      k: float = 1,
      bias: float = 0.2,
      avg_factor: Optional[int] = None,
      sigmoid: bool = False,
      num_class: int = 80,
  ) -> dict:
      """Classification-Aware Regression Loss (CARL).
  
      Args:
          cls_score (Tensor): Predicted classification scores.
          labels (Tensor): Targets of classification.
          bbox_pred (Tensor): Predicted bbox deltas.
          bbox_targets (Tensor): Target of bbox regression.
          loss_bbox (func): Regression loss func of the head.
          bbox_coder (obj): BBox coder of the head.
          k (float): Power of the non-linear mapping. Defaults to 1.
          bias (float): Shift of the non-linear mapping. Defaults to 0.2.
          avg_factor (int, optional): Average factor used in regression loss.
          sigmoid (bool): Activation of the classification score.
          num_class (int): Number of classes, defaults to 80.
  
      Return:
          dict: CARL loss dict.
      """
      pos_label_inds = (
          ((labels >= 0) & (labels < num_class)).nonzero().reshape(-1)
      )
      if pos_label_inds.numel() == 0:
          return dict(loss_carl=cls_score.sum()[None] * 0.0)
      pos_labels = labels[pos_label_inds]
  
      # multiply pos_cls_score with the corresponding bbox weight
      # and remain gradient
      if sigmoid:
          pos_cls_score = cls_score.sigmoid()[
              pos_label_inds, pos_labels
          ]
      else:
          pos_cls_score = cls_score.softmax(-1)[
              pos_label_inds, pos_labels
          ]
      carl_loss_weights = (bias + (1 - bias) * pos_cls_score).pow(k)
  
      # normalize carl_loss_weight to make its sum equal to num positive
      num_pos = float(pos_cls_score.size(0))
      weight_ratio = num_pos / carl_loss_weights.sum()
      carl_loss_weights *= weight_ratio
  
      if avg_factor is None:
          avg_factor = bbox_targets.size(0)
      # if is class agnostic, bbox pred is in shape (N, 4)
      # otherwise, bbox pred is in shape (N, #classes, 4)
      if bbox_pred.size(-1) > 4:
          bbox_pred = bbox_pred.view(bbox_pred.size(0), -1, 4)
          pos_bbox_preds = bbox_pred[pos_label_inds, pos_labels]
      else:
          pos_bbox_preds = bbox_pred[pos_label_inds]
      ori_loss_reg = (
          loss_bbox(
              pos_bbox_preds,
              bbox_targets[pos_label_inds],
              reduction_override="none",
          )
          / avg_factor
      )
      loss_carl = (ori_loss_reg * carl_loss_weights[:, None]).sum()
      return dict(loss_carl=loss_carl[None])
  
file_path: mmdetection/mmdet/models/losses/pisa_loss.py
imports: from typing import List, Optional, Tuple
  import torch
  import torch.nn
  from torch import Tensor
  from mmdet.structures.bbox import bbox_overlaps
  from ..task_modules.coders import BaseBBoxCoder
  from ..task_modules.samplers import SamplingResult
label_desc: Use image node_id 2 for calling a global function with example usage: carl_loss(cls_score, labels, bbox_pred, bbox_targets, loss_bbox, k, bias, avg_factor, sigmoid, num_class) and returns: dict, dict