class_docstr: Target Speaker Extraction Frontend model
class_docstr_tok: ["Target","Speaker","Extraction","Frontend","model"]
code: def forward_loss(
      self,
      speech_pre: torch.Tensor,
      speech_lengths: torch.Tensor,
      feature_mix: torch.Tensor,
      feature_pre: torch.Tensor,
      others: OrderedDict,
      speech_ref: torch.Tensor,
  ) -> Tuple[torch.Tensor, Dict[str, torch.Tensor], torch.Tensor]:
      loss = 0.0
      stats = {}
      o = {}
      perm = None
      for loss_wrapper in self.loss_wrappers:
          criterion = loss_wrapper.criterion
          if (
              getattr(criterion, "only_for_test", False)
              and self.training
          ):
              continue
  
          zero_weight = loss_wrapper.weight == 0.0
          if isinstance(criterion, TimeDomainLoss):
              assert speech_pre is not None
              sref, spre = self._align_ref_pre_channels(
                  speech_ref, speech_pre, ch_dim=2, force_1ch=True
              )
              # for the time domain criterions
              with torch.no_grad() if zero_weight else contextlib.ExitStack():
                  l, s, o = loss_wrapper(sref, spre, {**others, **o})
          elif isinstance(criterion, FrequencyDomainLoss):
              sref, spre = self._align_ref_pre_channels(
                  speech_ref, speech_pre, ch_dim=2, force_1ch=False
              )
              # for the time-frequency domain criterions
              if criterion.compute_on_mask:
                  # compute loss on masks
                  tf_ref, tf_pre = self._get_speech_masks(
                      criterion,
                      feature_mix,
                      None,
                      speech_ref,
                      speech_pre,
                      speech_lengths,
                      others,
                  )
              else:
                  # compute on spectrum
                  tf_ref = [
                      self.encoder(sr, speech_lengths)[0] for sr in sref
                  ]
                  tf_pre = [
                      self.encoder(sp, speech_lengths)[0] for sp in spre
                  ]
  
              with torch.no_grad() if zero_weight else contextlib.ExitStack():
                  l, s, o = loss_wrapper(
                      tf_ref, tf_pre, {**others, **o}
                  )
          else:
              raise NotImplementedError(
                  "Unsupported loss type: %s" % str(criterion)
              )
  
          loss += l * loss_wrapper.weight
          stats.update(s)
  
          if perm is None and "perm" in o:
              perm = o["perm"]
  
      if self.training and isinstance(loss, float):
          raise AttributeError(
              "At least one criterion must satisfy: only_for_test=False"
          )
      stats["loss"] = loss.detach()
  
      # force_gatherable: to-device and to-tensor if scalar for DataParallel
      batch_size = speech_ref[0].shape[0]
      loss, stats, weight = force_gatherable(
          (loss, stats, batch_size), loss.device
      )
      return loss, stats, weight, perm
  
imports: import contextlib
  from typing import Dict, List, Optional, OrderedDict, Tuple
  import torch
  from typeguard import check_argument_types
  from espnet2.enh.decoder.abs_decoder import AbsDecoder
  from espnet2.enh.encoder.abs_encoder import AbsEncoder
  from espnet2.enh.extractor.abs_extractor import AbsExtractor
  from espnet2.enh.loss.criterions.tf_domain import FrequencyDomainLoss
  from espnet2.enh.loss.criterions.time_domain import TimeDomainLoss
  from espnet2.enh.loss.wrappers.abs_wrapper import AbsLossWrapper
  from espnet2.torch_utils.device_funcs import force_gatherable
  from espnet2.train.abs_espnet_model import AbsESPnetModel
label_desc: Use image node_id 4 for calling the ESPnetExtractionModel obj's underlying member method code with example usage: obj.forward_loss(speech_pre, speech_lengths, feature_mix, feature_pre, others, speech_ref) and returns: loss,  stats,  weight,  perm