class_docstr: Machine translation model which supports bottleneck architecture,
  NLL, VAE, and MIM loss.
  
  Supported losses:
    1) nll - Conditional cross entropy (the usual NMT loss)
    2) mim - MIM learning framework. A latent variable model with good
                    reconstruction and compressed latent representation.
                    https://arxiv.org/pdf/2003.02645.pdf
    3) vae - VAE learning framework. A latent variable model which learns
                    good probability estimation over observations and
                    a regularized latent representation.
                    https://arxiv.org/pdf/1312.6114.pdf
class_docstr_tok: ["Machine","translation","model","which","supports","bottleneck","architecture",",","NLL",",","VAE",",","and","MIM","loss",".","Supported","losses",":","1",")","nll","-","Conditional","cross","entropy","(","the","usual","NMT","loss",")","2",")","mim","-","MIM","learning","framework",".","A","latent","variable","model","with","good","reconstruction","and","compressed","latent","representation",".","https",":","\/\/arxiv.org\/pdf\/2003.02645.pdf","3",")","vae","-","VAE","learning","framework",".","A","latent","variable","model","which","learns","good","probability","estimation","over","observations","and","a","regularized","latent","representation",".","https",":","\/\/arxiv.org\/pdf\/1312.6114.pdf"]
code: def eval_epoch_end(self, outputs, mode, global_rank):
      # call parent for logging
      super().eval_epoch_end(outputs, mode, global_rank)
  
      # if user specifies one validation dataloader, then PTL reverts to giving a list of dictionary instead of a list of list of dictionary
      if isinstance(outputs[0], dict):
          outputs = [outputs]
  
      for dataloader_idx, output in enumerate(outputs):
          # add logs if available in outputs
          log_dict = {}
          for x in output:
              if "log" in x:
                  for k, v in x["log"].items():
                      log_dict[k] = log_dict.get(k, []) + [v]
  
          for k, v in log_dict.items():
              if dataloader_idx == 0:
                  self.log(f"{mode}_{k}", np.mean(v), sync_dist=True)
              else:
                  self.log(
                      f"{mode}_{k}_dl_index_{dataloader_idx}",
                      np.mean(v),
                      sync_dist=True,
                  )
  
imports: from typing import Dict, Optional
  import numpy
  import torch
  from pytorch_lightning import Trainer
  from nemo.collections.common.losses import NLLLoss
  from nemo.collections.nlp.models.machine_translation.mt_enc_dec_config import MTBottleneckModelConfig
  from nemo.collections.nlp.models.machine_translation.mt_enc_dec_model import MTEncDecModel
  from nemo.core.classes.common import typecheck
  from nemo.utils import timers
label_desc: Use image node_id 3 for calling the MTBottleneckModel obj's underlying member method code with example usage: obj.eval_epoch_end(outputs, mode, global_rank) without return types