class_docstr: CTC module.
  
  Args:
      odim: dimension of outputs
      encoder_output_size: number of encoder projection units
      dropout_rate: dropout rate (0.0 ~ 1.0)
      ctc_type: builtin or gtnctc
      reduce: reduce the CTC loss into a scalar
      ignore_nan_grad: Same as zero_infinity (keeping for backward compatiblity)
      zero_infinity:  Whether to zero infinite losses and the associated gradients.
code: def loss_fn(
      self, th_pred, th_target, th_ilen, th_olen
  ) -> torch.Tensor:
      if self.ctc_type == "builtin" or self.ctc_type == "brctc":
          th_pred = th_pred.log_softmax(2)
          loss = self.ctc_loss(th_pred, th_target, th_ilen, th_olen)
          if self.ctc_type == "builtin":
              size = th_pred.size(1)
          else:
              size = loss.size(
                  0
              )  # some invalid examples will be excluded
  
          if self.reduce:
              # Batch-size average
              loss = loss.sum() / size
          else:
              loss = loss / size
          return loss
  
      # builtin2 ignores nan losses using the logic below, while
      # builtin relies on the zero_infinity flag in pytorch CTC
      elif self.ctc_type == "builtin2":
          th_pred = th_pred.log_softmax(2)
          loss = self.ctc_loss(th_pred, th_target, th_ilen, th_olen)
  
          if loss.requires_grad and self.ignore_nan_grad:
              # ctc_grad: (L, B, O)
              ctc_grad = loss.grad_fn(torch.ones_like(loss))
              ctc_grad = ctc_grad.sum([0, 2])
              indices = torch.isfinite(ctc_grad)
              size = indices.long().sum()
              if size == 0:
                  # Return as is
                  logging.warning(
                      "All samples in this mini-batch got nan grad."
                      " Returning nan value instead of CTC loss"
                  )
              elif size != th_pred.size(1):
                  logging.warning(
                      f"{th_pred.size(1) - size}/{th_pred.size(1)}"
                      " samples got nan grad."
                      " These were ignored for CTC loss."
                  )
  
                  # Create mask for target
                  target_mask = torch.full(
                      [th_target.size(0)],
                      1,
                      dtype=torch.bool,
                      device=th_target.device,
                  )
                  s = 0
                  for ind, le in enumerate(th_olen):
                      if not indices[ind]:
                          target_mask[s : s + le] = 0
                      s += le
  
                  # Calc loss again using maksed data
                  loss = self.ctc_loss(
                      th_pred[:, indices, :],
                      th_target[target_mask],
                      th_ilen[indices],
                      th_olen[indices],
                  )
          else:
              size = th_pred.size(1)
  
          if self.reduce:
              # Batch-size average
              loss = loss.sum() / size
          else:
              loss = loss / size
          return loss
  
      elif self.ctc_type == "gtnctc":
          log_probs = torch.nn.functional.log_softmax(th_pred, dim=2)
          return self.ctc_loss(log_probs, th_target, th_ilen, 0, "none")
  
      else:
          raise NotImplementedError
  
file_path: espnet/espnet2/asr/ctc.py
imports: import logging
  import torch
  import torch.nn.functional
  from typeguard import check_argument_types
label_desc: Use image node_id 2 for calling the CTC obj's underlying member method code with example usage: obj.loss_fn(th_pred, th_target, th_ilen, th_olen) and returns: loss, loss, self