class_docstr: FocalLoss is an extension of BCEWithLogitsLoss that down-weights loss from
  high confidence correct predictions.
  
  Reimplementation of the Focal Loss described in:
  
      - ["Focal Loss for Dense Object Detection"](https://arxiv.org/abs/1708.02002), T. Lin et al., ICCV 2017
      - "AnatomyNet: Deep learning for fast and fully automated whole-volume segmentation of head and neck anatomy",
        Zhu et al., Medical Physics 2018
  
  Example:
      >>> import torch
      >>> from monai.losses import FocalLoss
      >>> from torch.nn import BCEWithLogitsLoss
      >>> shape = B, N, *DIMS = 2, 3, 5, 7, 11
      >>> input = torch.rand(*shape)
      >>> target = torch.rand(*shape)
      >>> # Demonstrate equivalence to BCE when gamma=0
      >>> fl_g0_criterion = FocalLoss(reduction='none', gamma=0)
      >>> fl_g0_loss = fl_g0_criterion(input, target)
      >>> bce_criterion = BCEWithLogitsLoss(reduction='none')
      >>> bce_loss = bce_criterion(input, target)
      >>> assert torch.allclose(fl_g0_loss, bce_loss)
      >>> # Demonstrate "focus" by setting gamma > 0.
      >>> fl_g2_criterion = FocalLoss(reduction='none', gamma=2)
      >>> fl_g2_loss = fl_g2_criterion(input, target)
      >>> # Mark easy and hard cases
      >>> is_easy = (target > 0.7) & (input > 0.7)
      >>> is_hard = (target > 0.7) & (input < 0.3)
      >>> easy_loss_g0 = fl_g0_loss[is_easy].mean()
      >>> hard_loss_g0 = fl_g0_loss[is_hard].mean()
      >>> easy_loss_g2 = fl_g2_loss[is_easy].mean()
      >>> hard_loss_g2 = fl_g2_loss[is_hard].mean()
      >>> # Gamma > 0 causes the loss function to "focus" on the hard
      >>> # cases.  IE, easy cases are downweighted, so hard cases
      >>> # receive a higher proportion of the loss.
      >>> hard_to_easy_ratio_g2 = hard_loss_g2 / easy_loss_g2
      >>> hard_to_easy_ratio_g0 = hard_loss_g0 / easy_loss_g0
      >>> assert hard_to_easy_ratio_g2 > hard_to_easy_ratio_g0
class_docstr_tok: ["FocalLoss","is","an","extension","of","BCEWithLogitsLoss","that","down-weights","loss","from","high","confidence","correct","predictions",".","Reimplementation","of","the","Focal","Loss","described","in",":","-","[","``","Focal","Loss","for","Dense","Object","Detection","''","]","(","https",":","\/\/arxiv.org\/abs\/1708.02002",")",",","T.","Lin","et","al.",",","ICCV","2017","-","``","AnatomyNet",":","Deep","learning","for","fast","and","fully","automated","whole-volume","segmentation","of","head","and","neck","anatomy","''",",","Zhu","et","al.",",","Medical","Physics","2018","Example",":",">",">",">","import","torch",">",">",">","from","monai.losses","import","FocalLoss",">",">",">","from","torch.nn","import","BCEWithLogitsLoss",">",">",">","shape","=","B",",","N",",","*","DIMS","=","2",",","3",",","5",",","7",",","11",">",">",">","input","=","torch.rand","(","*","shape",")",">",">",">","target","=","torch.rand","(","*","shape",")",">",">",">","#","Demonstrate","equivalence","to","BCE","when","gamma=0",">",">",">","fl_g0_criterion","=","FocalLoss","(","reduction='none","'",",","gamma=0",")",">",">",">","fl_g0_loss","=","fl_g0_criterion","(","input",",","target",")",">",">",">","bce_criterion","=","BCEWithLogitsLoss","(","reduction='none","'",")",">",">",">","bce_loss","=","bce_criterion","(","input",",","target",")",">",">",">","assert","torch.allclose","(","fl_g0_loss",",","bce_loss",")",">",">",">","#","Demonstrate","``","focus","''","by","setting","gamma",">","0",".",">",">",">","fl_g2_criterion","=","FocalLoss","(","reduction='none","'",",","gamma=2",")",">",">",">","fl_g2_loss","=","fl_g2_criterion","(","input",",","target",")",">",">",">","#","Mark","easy","and","hard","cases",">",">",">","is_easy","=","(","target",">","0.7",")","&","(","input",">","0.7",")",">",">",">","is_hard","=","(","target",">","0.7",")","&","(","input","<","0.3",")",">",">",">","easy_loss_g0","=","fl_g0_loss","[","is_easy","]",".mean","(",")",">",">",">","hard_loss_g0","=","fl_g0_loss","[","is_hard","]",".mean","(",")",">",">",">","easy_loss_g2","=","fl_g2_loss","[","is_easy","]",".mean","(",")",">",">",">","hard_loss_g2","=","fl_g2_loss","[","is_hard","]",".mean","(",")",">",">",">","#","Gamma",">","0","causes","the","loss","function","to","``","focus","''","on","the","hard",">",">",">","#","cases",".","IE",",","easy","cases","are","downweighted",",","so","hard","cases",">",">",">","#","receive","a","higher","proportion","of","the","loss",".",">",">",">","hard_to_easy_ratio_g2","=","hard_loss_g2","\/","easy_loss_g2",">",">",">","hard_to_easy_ratio_g0","=","hard_loss_g0","\/","easy_loss_g0",">",">",">","assert","hard_to_easy_ratio_g2",">","hard_to_easy_ratio_g0"]
docstr: Args:
      input: the shape should be BNH[WD], where N is the number of classes.
          The input should be the original logits since it will be transformed by
          a sigmoid/softmax in the forward function.
      target: the shape should be BNH[WD] or B1H[WD], where N is the number of classes.
  
  Raises:
      ValueError: When input and target (after one hot transform if set)
          have different shapes.
      ValueError: When ``self.reduction`` is not one of ["mean", "sum", "none"].
      ValueError: When ``self.weight`` is a sequence and the length is not equal to the
          number of classes.
      ValueError: When ``self.weight`` is/contains a value that is less than 0.
docstr_tok: ["Args",":","input",":","the","shape","should","be","BNH","[","WD","]",",","where","N","is","the","number","of","classes",".","The","input","should","be","the","original","logits","since","it","will","be","transformed","by","a","sigmoid\/softmax","in","the","forward","function",".","target",":","the","shape","should","be","BNH","[","WD","]","or","B1H","[","WD","]",",","where","N","is","the","number","of","classes",".","Raises",":","ValueError",":","When","input","and","target","(","after","one","hot","transform","if","set",")","have","different","shapes",".","ValueError",":","When","``","self.reduction","``","is","not","one","of","[","``","mean","''",",","``","sum","''",",","``","none","''","]",".","ValueError",":","When","``","self.weight","``","is","a","sequence","and","the","length","is","not","equal","to","the","number","of","classes",".","ValueError",":","When","``","self.weight","``","is\/contains","a","value","that","is","less","than","0","."]
code: def forward(
      self, input: torch.Tensor, target: torch.Tensor
  ) -> torch.Tensor:
      """
      Args:
          input: the shape should be BNH[WD], where N is the number of classes.
              The input should be the original logits since it will be transformed by
              a sigmoid/softmax in the forward function.
          target: the shape should be BNH[WD] or B1H[WD], where N is the number of classes.
  
      Raises:
          ValueError: When input and target (after one hot transform if set)
              have different shapes.
          ValueError: When ``self.reduction`` is not one of ["mean", "sum", "none"].
          ValueError: When ``self.weight`` is a sequence and the length is not equal to the
              number of classes.
          ValueError: When ``self.weight`` is/contains a value that is less than 0.
  
      """
      n_pred_ch = input.shape[1]
  
      if self.to_onehot_y:
          if n_pred_ch == 1:
              warnings.warn(
                  "single channel prediction, `to_onehot_y=True` ignored."
              )
          else:
              target = one_hot(target, num_classes=n_pred_ch)
  
      if not self.include_background:
          if n_pred_ch == 1:
              warnings.warn(
                  "single channel prediction, `include_background=False` ignored."
              )
          else:
              # if skipping background, removing first channel
              target = target[:, 1:]
              input = input[:, 1:]
  
      if target.shape != input.shape:
          raise ValueError(
              f"ground truth has different shape ({target.shape}) from input ({input.shape})"
          )
  
      loss: Optional[torch.Tensor] = None
      input = input.float()
      target = target.float()
      if self.use_softmax:
          if not self.include_background and self.alpha is not None:
              self.alpha = None
              warnings.warn(
                  "`include_background=False`, `alpha` ignored when using softmax."
              )
          loss = softmax_focal_loss(
              input, target, self.gamma, self.alpha
          )
      else:
          loss = sigmoid_focal_loss(
              input, target, self.gamma, self.alpha
          )
  
      num_of_classes = target.shape[1]
      if self.class_weight is not None and num_of_classes != 1:
          # make sure the lengths of weights are equal to the number of classes
          if self.class_weight.ndim == 0:
              self.class_weight = torch.as_tensor(
                  [self.class_weight] * num_of_classes
              )
          else:
              if self.class_weight.shape[0] != num_of_classes:
                  raise ValueError(
                      """the length of the `weight` sequence should be the same as the number of classes.
                          If `include_background=False`, the weight should not include
                          the background category class 0."""
                  )
          if self.class_weight.min() < 0:
              raise ValueError(
                  "the value/values of the `weight` should be no less than 0."
              )
          # apply class_weight to loss
          self.class_weight = self.class_weight.to(loss)
          broadcast_dims = [-1] + [1] * len(target.shape[2:])
          self.class_weight = self.class_weight.view(broadcast_dims)
          loss = self.class_weight * loss
  
      if self.reduction == LossReduction.SUM.value:
          # Previously there was a mean over the last dimension, which did not
          # return a compatible BCE loss. To maintain backwards compatible
          # behavior we have a flag that performs this extra step, disable or
          # parameterize if necessary. (Or justify why the mean should be there)
          average_spatial_dims = True
          if average_spatial_dims:
              loss = loss.mean(dim=list(range(2, len(target.shape))))
          loss = loss.sum()
      elif self.reduction == LossReduction.MEAN.value:
          loss = loss.mean()
      elif self.reduction == LossReduction.NONE.value:
          pass
      else:
          raise ValueError(
              f'Unsupported reduction: {self.reduction}, available options are ["mean", "sum", "none"].'
          )
      return loss
  
file_path: MONAI/monai/losses/focal_loss.py
imports: from __future__ import annotations
  import warnings
  from collections.abc import Sequence
  from typing import Optional
  import torch
  import torch.nn.functional
  from torch.nn.modules.loss import _Loss
  from monai.networks import one_hot
  from monai.utils import LossReduction
label_desc: Use image node_id 2 for calling the FocalLoss obj's underlying member method code with example usage: obj.forward(input, target) and returns: loss