code: def train(args):
      """Train with the given args.
  
      Args:
          args (namespace): The program arguments.
  
      """
      if args.use_ddp:
          # initialize distributed environment.
          # NOTE: current implementation supports
          # only single-node training.
  
          # get process information.
          worldsize = os.environ.get("WORLD_SIZE", None)
          assert worldsize is not None
          worldsize = int(worldsize)
          assert worldsize == args.ngpu
  
          rank = os.environ.get("RANK", None)
          assert rank is not None
          rank = int(rank)
  
          localrank = os.environ.get("LOCAL_RANK", None)
          assert localrank is not None
          localrank = int(localrank)
  
          dist.init_process_group(
              backend="nccl",
              init_method="env://",
              rank=rank,
              world_size=worldsize,
          )
  
          if rank != 0:
              # Disable all logs in non-master process.
              logging.disable()
      else:
          worldsize = 1
          rank = 0
          localrank = 0
  
      set_deterministic_pytorch(args)
      if args.num_encs > 1:
          args = format_mulenc_args(args)
  
      # check cuda availability
      if not torch.cuda.is_available():
          logging.warning("cuda is not available")
  
      # get input and output dimension info
      with open(args.valid_json, "rb") as f:
          valid_json = json.load(f)["utts"]
      utts = list(valid_json.keys())
      idim_list = [
          int(valid_json[utts[0]]["input"][i]["shape"][-1])
          for i in range(args.num_encs)
      ]
      odim = int(valid_json[utts[0]]["output"][0]["shape"][-1])
      for i in range(args.num_encs):
          logging.info(
              "stream{}: input dims : {}".format(i + 1, idim_list[i])
          )
      logging.info("#output dims: " + str(odim))
  
      # specify attention, CTC, hybrid mode
      if "transducer" in args.model_module:
          if (
              getattr(args, "etype", False) == "custom"
              or getattr(args, "dtype", False) == "custom"
          ):
              mtl_mode = "custom_transducer"
          else:
              mtl_mode = "transducer"
          logging.info("Pure transducer mode")
      elif args.mtlalpha == 1.0:
          mtl_mode = "ctc"
          logging.info("Pure CTC mode")
      elif args.mtlalpha == 0.0:
          mtl_mode = "att"
          logging.info("Pure attention mode")
      else:
          mtl_mode = "mtl"
          logging.info("Multitask learning mode")
  
      if (
          args.enc_init is not None or args.dec_init is not None
      ) and args.num_encs == 1:
          model = load_trained_modules(idim_list[0], odim, args)
      else:
          model_class = dynamic_import(args.model_module)
          model = model_class(
              idim_list[0] if args.num_encs == 1 else idim_list,
              odim,
              args,
          )
      assert isinstance(model, ASRInterface)
      total_subsampling_factor = model.get_total_subsampling_factor()
  
      logging.info(
          " Total parameter of the model = "
          + str(sum(p.numel() for p in model.parameters()))
      )
  
      if args.rnnlm is not None:
          rnnlm_args = get_model_conf(args.rnnlm, args.rnnlm_conf)
          rnnlm = lm_pytorch.ClassifierWithState(
              lm_pytorch.RNNLM(
                  len(args.char_list), rnnlm_args.layer, rnnlm_args.unit
              )
          )
          torch_load(args.rnnlm, rnnlm)
          model.rnnlm = rnnlm
  
      if is_writable_process(args, worldsize, rank, localrank):
          # write model config
          if not os.path.exists(args.outdir):
              os.makedirs(args.outdir)
          model_conf = args.outdir + "/model.json"
          with open(model_conf, "wb") as f:
              logging.info(
                  "writing a model config file to " + model_conf
              )
              f.write(
                  json.dumps(
                      (
                          idim_list[0]
                          if args.num_encs == 1
                          else idim_list,
                          odim,
                          vars(args),
                      ),
                      indent=4,
                      ensure_ascii=False,
                      sort_keys=True,
                  ).encode("utf_8")
              )
      for key in sorted(vars(args).keys()):
          logging.info("ARGS: " + key + ": " + str(vars(args)[key]))
  
      reporter = model.reporter
  
      if args.use_ddp:
          if args.num_encs > 1:
              # TODO(ruizhili): implement data parallel for multi-encoder setup.
              raise NotImplementedError(
                  "Data parallel is not supported for multi-encoder setup."
              )
      else:
          # check the use of multi-gpu
          if args.ngpu > 1:
              if args.batch_size != 0:
                  logging.warning(
                      "batch size is automatically increased (%d -> %d)"
                      % (args.batch_size, args.batch_size * args.ngpu)
                  )
                  args.batch_size *= args.ngpu
              if args.num_encs > 1:
                  # TODO(ruizhili): implement data parallel for multi-encoder setup.
                  raise NotImplementedError(
                      "Data parallel is not supported for multi-encoder setup."
                  )
  
      # set torch device
      if args.use_ddp:
          device = torch.device(f"cuda:{localrank}")
      else:
          device = torch.device("cuda" if args.ngpu > 0 else "cpu")
      if args.train_dtype in ("float16", "float32", "float64"):
          dtype = getattr(torch, args.train_dtype)
      else:
          dtype = torch.float32
      model = model.to(device=device, dtype=dtype)
  
      if args.freeze_mods:
          model, model_params = freeze_modules(model, args.freeze_mods)
      else:
          model_params = model.parameters()
  
      logging.warning(
          "num. model params: {:,} (num. trained: {:,} ({:.1f}%))".format(
              sum(p.numel() for p in model.parameters()),
              sum(
                  p.numel()
                  for p in model.parameters()
                  if p.requires_grad
              ),
              sum(
                  p.numel()
                  for p in model.parameters()
                  if p.requires_grad
              )
              * 100.0
              / sum(p.numel() for p in model.parameters()),
          )
      )
  
      # Setup an optimizer
      if args.opt == "adadelta":
          optimizer = torch.optim.Adadelta(
              model_params,
              rho=0.95,
              eps=args.eps,
              weight_decay=args.weight_decay,
          )
      elif args.opt == "adam":
          optimizer = torch.optim.Adam(
              model_params, weight_decay=args.weight_decay
          )
      elif args.opt == "noam":
          from espnet.nets.pytorch_backend.transformer.optimizer import (
              get_std_opt,
          )
  
          if "transducer" in mtl_mode:
              if args.noam_adim > 0:
                  optimizer = get_std_opt(
                      model_params,
                      args.noam_adim,
                      args.optimizer_warmup_steps,
                      args.noam_lr,
                  )
              else:
                  raise ValueError(
                      "noam-adim option should be set to use Noam scheduler"
                  )
          else:
              optimizer = get_std_opt(
                  model_params,
                  args.adim,
                  args.transformer_warmup_steps,
                  args.transformer_lr,
              )
      else:
          raise NotImplementedError("unknown optimizer: " + args.opt)
  
      # setup apex.amp
      if args.train_dtype in ("O0", "O1", "O2", "O3"):
          try:
              from apex import amp
          except ImportError as e:
              logging.error(
                  f"You need to install apex for --train-dtype {args.train_dtype}. "
                  "See https://github.com/NVIDIA/apex#linux"
              )
              raise e
          if args.opt == "noam":
              model, optimizer.optimizer = amp.initialize(
                  model, optimizer.optimizer, opt_level=args.train_dtype
              )
          else:
              model, optimizer = amp.initialize(
                  model, optimizer, opt_level=args.train_dtype
              )
          use_apex = True
  
          from espnet.nets.pytorch_backend.ctc import CTC
  
          amp.register_float_function(CTC, "loss_fn")
          amp.init()
          logging.warning("register ctc as float function")
      else:
          use_apex = False
  
      # FIXME: TOO DIRTY HACK
      setattr(optimizer, "target", reporter)
      setattr(optimizer, "serialize", lambda s: reporter.serialize(s))
  
      # Setup a converter
      if args.num_encs == 1:
          converter = CustomConverter(
              subsampling_factor=model.subsample[0], dtype=dtype
          )
      else:
          converter = CustomConverterMulEnc(
              [i[0] for i in model.subsample_list], dtype=dtype
          )
  
      # read json data
      with open(args.train_json, "rb") as f:
          train_json = json.load(f)["utts"]
      with open(args.valid_json, "rb") as f:
          valid_json = json.load(f)["utts"]
  
      use_sortagrad = args.sortagrad == -1 or args.sortagrad > 0
      # make minibatch list (variable length)
      if args.use_ddp:
          # When using DDP, minimum batch size for each process is 1.
          min_batch_size = 1
      else:
          min_batch_size = args.ngpu if args.ngpu > 1 else 1
      train = make_batchset(
          train_json,
          args.batch_size,
          args.maxlen_in,
          args.maxlen_out,
          args.minibatches,
          min_batch_size=min_batch_size,
          shortest_first=use_sortagrad,
          count=args.batch_count,
          batch_bins=args.batch_bins,
          batch_frames_in=args.batch_frames_in,
          batch_frames_out=args.batch_frames_out,
          batch_frames_inout=args.batch_frames_inout,
          iaxis=0,
          oaxis=0,
      )
      valid = make_batchset(
          valid_json,
          args.batch_size,
          args.maxlen_in,
          args.maxlen_out,
          args.minibatches,
          min_batch_size=min_batch_size,
          count=args.batch_count,
          batch_bins=args.batch_bins,
          batch_frames_in=args.batch_frames_in,
          batch_frames_out=args.batch_frames_out,
          batch_frames_inout=args.batch_frames_inout,
          iaxis=0,
          oaxis=0,
      )
  
      load_tr = LoadInputsAndTargets(
          mode="asr",
          load_output=True,
          preprocess_conf=args.preprocess_conf,
          preprocess_args={
              "train": True
          },  # Switch the mode of preprocessing
      )
      load_cv = LoadInputsAndTargets(
          mode="asr",
          load_output=True,
          preprocess_conf=args.preprocess_conf,
          preprocess_args={
              "train": False
          },  # Switch the mode of preprocessing
      )
      # hack to make batchsize argument as 1
      # actual bathsize is included in a list
      # default collate function converts numpy array to pytorch tensor
      # we used an empty collate function instead which returns list
      train_ds = TransformDataset(train, Transform(converter, load_tr))
      val_ds = TransformDataset(valid, Transform(converter, load_cv))
      train_sampler = None
      val_sampler = None
      shuffle = not use_sortagrad
      if args.use_ddp:
          train_sampler = DistributedSampler(train_ds)
          val_sampler = DistributedSampler(val_ds)
          shuffle = False
  
      train_iter = ChainerDataLoader(
          dataset=train_ds,
          batch_size=1,
          num_workers=args.n_iter_processes,
          shuffle=shuffle,
          sampler=train_sampler,
          collate_fn=ChainerDataLoader.get_first_element,
      )
      valid_iter = ChainerDataLoader(
          dataset=val_ds,
          batch_size=1,
          shuffle=False,
          sampler=val_sampler,
          collate_fn=ChainerDataLoader.get_first_element,
          num_workers=args.n_iter_processes,
      )
  
      # Set up a trainer
      if args.use_ddp:
          model = DDP(model, device_ids=[localrank])
      updater = CustomUpdater(
          model,
          args.grad_clip,
          {"main": train_iter},
          optimizer,
          device,
          args.ngpu,
          args.grad_noise,
          args.accum_grad,
          use_apex=use_apex,
          use_ddp=args.use_ddp,
      )
      trainer = training.Trainer(
          updater, (args.epochs, "epoch"), out=args.outdir
      )
  
      # call DistributedSampler.set_epoch at begining of each epoch.
      if args.use_ddp:
  
          @training.make_extension(trigger=(1, "epoch"))
          def set_epoch_to_distributed_sampler(trainer):
              # NOTE: at the first time when this fuction is called,
              # `sampler.epoch` should be 0, and a given trainer object
              # has 1 as a `trainer.updater.epoch`.
              # This means that, in the first epoch,
              # dataset is shuffled with random seed and a value 0,
              # and, in the second epoch, dataset is shuffled
              # with the same random seed and a value 1.
              #
              # See a link below for more details.
              # https://pytorch.org/docs/stable/data.html#torch.utils.data.distributed.DistributedSampler
              train_sampler.set_epoch(trainer.updater.epoch)
              val_sampler.set_epoch(trainer.updater.epoch)
  
          trainer.extend(set_epoch_to_distributed_sampler)
  
      if use_sortagrad:
          trainer.extend(
              ShufflingEnabler([train_iter]),
              trigger=(
                  args.sortagrad
                  if args.sortagrad != -1
                  else args.epochs,
                  "epoch",
              ),
          )
  
      # Resume from a snapshot
      if args.resume:
          logging.info("resumed from %s" % args.resume)
          torch_resume(args.resume, trainer)
  
      # Evaluate the model with the test dataset for each epoch
      if args.save_interval_iters > 0:
          trainer.extend(
              CustomEvaluator(
                  model,
                  {"main": valid_iter},
                  reporter,
                  device,
                  args.ngpu,
                  args.use_ddp,
              ),
              trigger=(args.save_interval_iters, "iteration"),
          )
      else:
          trainer.extend(
              CustomEvaluator(
                  model,
                  {"main": valid_iter},
                  reporter,
                  device,
                  args.ngpu,
                  args.use_ddp,
              )
          )
  
      if is_writable_process(args, worldsize, rank, localrank):
          # Save attention weight each epoch
          is_attn_plot = (
              "transformer" in args.model_module
              or "conformer" in args.model_module
              or mtl_mode in ["att", "mtl", "custom_transducer"]
          )
  
          if args.num_save_attention > 0 and is_attn_plot:
              data = sorted(
                  list(valid_json.items())[: args.num_save_attention],
                  key=lambda x: int(x[1]["input"][0]["shape"][1]),
                  reverse=True,
              )
              if hasattr(model, "module"):
                  att_vis_fn = model.module.calculate_all_attentions
                  plot_class = model.module.attention_plot_class
              else:
                  att_vis_fn = model.calculate_all_attentions
                  plot_class = model.attention_plot_class
              att_reporter = plot_class(
                  att_vis_fn,
                  data,
                  args.outdir + "/att_ws",
                  converter=converter,
                  transform=load_cv,
                  device=device,
                  subsampling_factor=total_subsampling_factor,
              )
              trainer.extend(att_reporter, trigger=(1, "epoch"))
          else:
              att_reporter = None
  
          # Save CTC prob at each epoch
          if mtl_mode in ["ctc", "mtl"] and args.num_save_ctc > 0:
              # NOTE: sort it by output lengths
              data = sorted(
                  list(valid_json.items())[: args.num_save_ctc],
                  key=lambda x: int(x[1]["output"][0]["shape"][0]),
                  reverse=True,
              )
              if hasattr(model, "module"):
                  ctc_vis_fn = model.module.calculate_all_ctc_probs
                  plot_class = model.module.ctc_plot_class
              else:
                  ctc_vis_fn = model.calculate_all_ctc_probs
                  plot_class = model.ctc_plot_class
              ctc_reporter = plot_class(
                  ctc_vis_fn,
                  data,
                  args.outdir + "/ctc_prob",
                  converter=converter,
                  transform=load_cv,
                  device=device,
                  subsampling_factor=total_subsampling_factor,
              )
              trainer.extend(ctc_reporter, trigger=(1, "epoch"))
          else:
              ctc_reporter = None
  
          # Make a plot for training and validation values
          if args.num_encs > 1:
              report_keys_loss_ctc = [
                  "main/loss_ctc{}".format(i + 1)
                  for i in range(model.num_encs)
              ] + [
                  "validation/main/loss_ctc{}".format(i + 1)
                  for i in range(model.num_encs)
              ]
              report_keys_cer_ctc = [
                  "main/cer_ctc{}".format(i + 1)
                  for i in range(model.num_encs)
              ] + [
                  "validation/main/cer_ctc{}".format(i + 1)
                  for i in range(model.num_encs)
              ]
  
          if hasattr(model, "is_transducer"):
              trans_keys = [
                  "main/loss",
                  "validation/main/loss",
                  "main/loss_trans",
                  "validation/main/loss_trans",
              ]
  
              ctc_keys = (
                  ["main/loss_ctc", "validation/main/loss_ctc"]
                  if args.use_ctc_loss
                  else []
              )
  
              aux_trans_keys = (
                  [
                      "main/loss_aux_trans",
                      "validation/main/loss_aux_trans",
                  ]
                  if args.use_aux_transducer_loss
                  else []
              )
  
              symm_kl_div_keys = (
                  [
                      "main/loss_symm_kl_div",
                      "validation/main/loss_symm_kl_div",
                  ]
                  if args.use_symm_kl_div_loss
                  else []
              )
  
              lm_keys = (
                  [
                      "main/loss_lm",
                      "validation/main/loss_lm",
                  ]
                  if args.use_lm_loss
                  else []
              )
  
              transducer_keys = (
                  trans_keys
                  + ctc_keys
                  + aux_trans_keys
                  + symm_kl_div_keys
                  + lm_keys
              )
  
              trainer.extend(
                  extensions.PlotReport(
                      transducer_keys,
                      "epoch",
                      file_name="loss.png",
                  )
              )
          else:
              trainer.extend(
                  extensions.PlotReport(
                      [
                          "main/loss",
                          "validation/main/loss",
                          "main/loss_ctc",
                          "validation/main/loss_ctc",
                          "main/loss_att",
                          "validation/main/loss_att",
                      ]
                      + (
                          []
                          if args.num_encs == 1
                          else report_keys_loss_ctc
                      ),
                      "epoch",
                      file_name="loss.png",
                  )
              )
  
          trainer.extend(
              extensions.PlotReport(
                  ["main/acc", "validation/main/acc"],
                  "epoch",
                  file_name="acc.png",
              )
          )
          trainer.extend(
              extensions.PlotReport(
                  ["main/cer_ctc", "validation/main/cer_ctc"]
                  + (
                      [] if args.num_encs == 1 else report_keys_loss_ctc
                  ),
                  "epoch",
                  file_name="cer.png",
              )
          )
  
          # Save best models
          trainer.extend(
              snapshot_object(model, "model.loss.best"),
              trigger=training.triggers.MinValueTrigger(
                  "validation/main/loss"
              ),
          )
          if mtl_mode not in ["ctc", "transducer", "custom_transducer"]:
              trainer.extend(
                  snapshot_object(model, "model.acc.best"),
                  trigger=training.triggers.MaxValueTrigger(
                      "validation/main/acc"
                  ),
              )
  
          # save snapshot which contains model and optimizer states
          if args.save_interval_iters > 0:
              trainer.extend(
                  torch_snapshot(
                      filename="snapshot.iter.{.updater.iteration}"
                  ),
                  trigger=(args.save_interval_iters, "iteration"),
              )
  
          # save snapshot at every epoch - for model averaging
          trainer.extend(torch_snapshot(), trigger=(1, "epoch"))
  
      # epsilon decay in the optimizer
      if args.opt == "adadelta":
          if args.criterion == "acc" and mtl_mode != "ctc":
              trainer.extend(
                  restore_snapshot(
                      model,
                      args.outdir + "/model.acc.best",
                      load_fn=torch_load,
                  ),
                  trigger=CompareValueTrigger(
                      "validation/main/acc",
                      lambda best_value, current_value: best_value
                      > current_value,
                  ),
              )
              trainer.extend(
                  adadelta_eps_decay(args.eps_decay),
                  trigger=CompareValueTrigger(
                      "validation/main/acc",
                      lambda best_value, current_value: best_value
                      > current_value,
                  ),
              )
          elif args.criterion == "loss":
              trainer.extend(
                  restore_snapshot(
                      model,
                      args.outdir + "/model.loss.best",
                      load_fn=torch_load,
                  ),
                  trigger=CompareValueTrigger(
                      "validation/main/loss",
                      lambda best_value, current_value: best_value
                      < current_value,
                  ),
              )
              trainer.extend(
                  adadelta_eps_decay(args.eps_decay),
                  trigger=CompareValueTrigger(
                      "validation/main/loss",
                      lambda best_value, current_value: best_value
                      < current_value,
                  ),
              )
          # NOTE: In some cases, it may take more than one epoch for the model's loss
          # to escape from a local minimum.
          # Thus, restore_snapshot extension is not used here.
          # see details in https://github.com/espnet/espnet/pull/2171
          elif args.criterion == "loss_eps_decay_only":
              trainer.extend(
                  adadelta_eps_decay(args.eps_decay),
                  trigger=CompareValueTrigger(
                      "validation/main/loss",
                      lambda best_value, current_value: best_value
                      < current_value,
                  ),
              )
  
      if is_writable_process(args, worldsize, rank, localrank):
          # Write a log of evaluation statistics for each epoch
          trainer.extend(
              extensions.LogReport(
                  trigger=(args.report_interval_iters, "iteration")
              )
          )
  
          if hasattr(model, "is_transducer"):
              report_keys = (
                  [
                      "epoch",
                      "iteration",
                  ]
                  + transducer_keys
                  + ["elapsed_time"]
              )
          else:
              report_keys = [
                  "epoch",
                  "iteration",
                  "main/loss",
                  "main/loss_ctc",
                  "main/loss_att",
                  "validation/main/loss",
                  "validation/main/loss_ctc",
                  "validation/main/loss_att",
                  "main/acc",
                  "validation/main/acc",
                  "main/cer_ctc",
                  "validation/main/cer_ctc",
                  "elapsed_time",
              ] + (
                  []
                  if args.num_encs == 1
                  else report_keys_cer_ctc + report_keys_loss_ctc
              )
  
          if args.opt == "adadelta":
              trainer.extend(
                  extensions.observe_value(
                      "eps",
                      lambda trainer: trainer.updater.get_optimizer(
                          "main"
                      ).param_groups[0]["eps"],
                  ),
                  trigger=(args.report_interval_iters, "iteration"),
              )
              report_keys.append("eps")
          if args.report_cer:
              report_keys.append("validation/main/cer")
          if args.report_wer:
              report_keys.append("validation/main/wer")
          trainer.extend(
              extensions.PrintReport(report_keys),
              trigger=(args.report_interval_iters, "iteration"),
          )
  
          trainer.extend(
              extensions.ProgressBar(
                  update_interval=args.report_interval_iters
              )
          )
      set_early_stop(trainer, args)
  
      if is_writable_process(args, worldsize, rank, localrank):
          if (
              args.tensorboard_dir is not None
              and args.tensorboard_dir != ""
          ):
              from torch.utils.tensorboard import SummaryWriter
  
              trainer.extend(
                  TensorboardLogger(
                      SummaryWriter(args.tensorboard_dir),
                      att_reporter=att_reporter,
                      ctc_reporter=ctc_reporter,
                  ),
                  trigger=(args.report_interval_iters, "iteration"),
              )
  
      if args.use_ddp:
          # To avoid busy wait on non-main processes
          # during a main process is writing plot, logs, etc,
          # one additional extension must be added at the last.
          # Within this additional extension,
          # a main process will send a notification tensor
          # to other processes when the main process finishes
          # all operations like writing plot, log, etc.
          src_rank = 0  # TODO(lazykyama): removing hard-coded value.
  
          @training.make_extension(trigger=(1, "epoch"))
          def barrier_extension_per_epoch(trainer):
              notification = torch.zeros(1, device=device)
              dist.broadcast(notification, src=src_rank)
              torch.cuda.synchronize(device=device)
  
          trainer.extend(barrier_extension_per_epoch)
  
      # Run the training
      trainer.run()
      if is_writable_process(args, worldsize, rank, localrank):
          check_early_stop(trainer, args.epochs)
  
imports: import copy
  import itertools
  import json
  import logging
  import math
  import os
  import numpy
  import torch
  import torch.distributed
  from chainer import reporter
  from chainer import training
  from chainer.training import extensions
  from chainer.training.updater import StandardUpdater
  from packaging.version import parse
  from torch.nn.parallel import DistributedDataParallel
  from torch.nn.parallel import data_parallel
  from torch.utils.data.distributed import DistributedSampler
  import espnet.lm.pytorch_backend.extlm
  import espnet.nets.pytorch_backend.lm.default
  from espnet.asr.asr_utils import CompareValueTrigger, adadelta_eps_decay, add_results_to_json, format_mulenc_args, get_model_conf, plot_spectrogram, restore_snapshot, snapshot_object, torch_load, torch_resume, torch_snapshot
  from espnet.asr.pytorch_backend.asr_init import freeze_modules, load_trained_model, load_trained_modules
  from espnet.nets.asr_interface import ASRInterface
  from espnet.nets.beam_search_transducer import BeamSearchTransducer
  from espnet.nets.pytorch_backend.e2e_asr import pad_list
  from espnet.nets.pytorch_backend.streaming.segment import SegmentStreamingE2E
  from espnet.nets.pytorch_backend.streaming.window import WindowStreamingE2E
  from espnet.transform.spectrogram import IStft
  from espnet.transform.transformation import Transformation
  from espnet.utils.cli_writers import file_writer_helper
  from espnet.utils.dataset import ChainerDataLoader, Transform, TransformDataset
  from espnet.utils.deterministic_utils import set_deterministic_pytorch
  from espnet.utils.dynamic_import import dynamic_import
  from espnet.utils.io_utils import LoadInputsAndTargets
  from espnet.utils.training.batchfy import make_batchset
  from espnet.utils.training.evaluator import BaseEvaluator
  from espnet.utils.training.iterators import ShufflingEnabler
  from espnet.utils.training.tensorboard_logger import TensorboardLogger
  from espnet.utils.training.train_utils import check_early_stop, set_early_stop
label_desc: Use image node_id 3 for calling a global function with example usage: train(args) without return types