class_docstr: Encoder-Decoder model
docstr: Frontend + Encoder + Decoder + Calc loss
  
  Args:
      text: (Batch, Length)
      text_lengths: (Batch,)
      src_text: (Batch, length)
      src_text_lengths: (Batch,)
      kwargs: "utt_id" is among the input.
docstr_tok: ["Frontend","+","Encoder","+","Decoder","+","Calc","loss","Args",":","text",":","(","Batch",",","Length",")","text_lengths",":","(","Batch",",",")","src_text",":","(","Batch",",","length",")","src_text_lengths",":","(","Batch",",",")","kwargs",":","``","utt_id","''","is","among","the","input","."]
code: def forward(
      self,
      text: torch.Tensor,
      text_lengths: torch.Tensor,
      src_text: torch.Tensor,
      src_text_lengths: torch.Tensor,
      **kwargs,
  ) -> Tuple[torch.Tensor, Dict[str, torch.Tensor], torch.Tensor]:
      """Frontend + Encoder + Decoder + Calc loss
  
      Args:
          text: (Batch, Length)
          text_lengths: (Batch,)
          src_text: (Batch, length)
          src_text_lengths: (Batch,)
          kwargs: "utt_id" is among the input.
      """
      assert text_lengths.dim() == 1, text_lengths.shape
      # Check that batch_size is unified
      assert (
          text.shape[0]
          == text_lengths.shape[0]
          == src_text.shape[0]
          == src_text_lengths.shape[0]
      ), (
          text.shape,
          text_lengths.shape,
          src_text.shape,
          src_text_lengths.shape,
      )
  
      batch_size = src_text.shape[0]
  
      # for data-parallel
      text = text[:, : text_lengths.max()]
      src_text = src_text[:, : src_text_lengths.max()]
  
      # 1. Encoder
      encoder_out, encoder_out_lens = self.encode(
          src_text, src_text_lengths
      )
  
      # 2a. Attention-decoder branch (MT)
      loss_mt_att, acc_mt_att, bleu_mt_att = self._calc_mt_att_loss(
          encoder_out, encoder_out_lens, text, text_lengths
      )
  
      # 3. Loss computation
      loss = loss_mt_att
  
      stats = dict(
          loss=loss.detach(),
          acc=acc_mt_att,
          bleu=bleu_mt_att,
      )
  
      # force_gatherable: to-device and to-tensor if scalar for DataParallel
      loss, stats, weight = force_gatherable(
          (loss, stats, batch_size), loss.device
      )
      return loss, stats, weight
  
imports: import logging
  from contextlib import contextmanager
  from typing import Dict, List, Optional, Tuple, Union
  import torch
  from packaging.version import parse
  from typeguard import check_argument_types
  from espnet2.asr.decoder.abs_decoder import AbsDecoder
  from espnet2.asr.encoder.abs_encoder import AbsEncoder
  from espnet2.asr.frontend.abs_frontend import AbsFrontend
  from espnet2.asr.postencoder.abs_postencoder import AbsPostEncoder
  from espnet2.asr.preencoder.abs_preencoder import AbsPreEncoder
  from espnet2.torch_utils.device_funcs import force_gatherable
  from espnet2.train.abs_espnet_model import AbsESPnetModel
  from espnet.nets.e2e_mt_common import ErrorCalculator
  from espnet.nets.pytorch_backend.nets_utils import th_accuracy
  from espnet.nets.pytorch_backend.transformer.add_sos_eos import add_sos_eos
  from espnet.nets.pytorch_backend.transformer.label_smoothing_loss import LabelSmoothingLoss
label_desc: Use image node_id 2 for calling the ESPnetMTModel obj's underlying member method code with example usage: obj.forward(text, text_lengths, src_text, src_text_lengths) and returns: loss,  stats,  weight