class_docstr: This is a classification model that selects the best heteronym option out of possible dictionary entries.
  Supports only heteronyms, no OOV.
code: def on_validation_epoch_end(self):
      split = "test" if self.trainer.testing else "val"
      if split == "val":
          avg_loss = torch.stack(
              [x[f"{split}_loss"] for x in self.validation_step_outputs]
          ).mean()
      elif split == "test":
          avg_loss = torch.stack(
              [x[f"{split}_loss"] for x in self.test_step_outputs]
          ).mean()
  
      # calculate metrics and classification report
      (
          precision,
          recall,
          f1,
          report,
      ) = self.classification_report.compute()
  
      # remove examples with support=0
      report = "\n".join(
          [
              x
              for x in report.split("\n")
              if not x.endswith("          0")
              and "100.00     100.00     100.00" not in x
          ]
      )
      logging.info(f"{split}_report: {report}")
      logging.info(f"{split}_f1: {f1:.2f}%")
      self.log(f"{split}_loss", avg_loss, prog_bar=True)
      self.log(f"{split}_precision", precision)
      self.log(f"{split}_f1", f1)
      self.log(f"{split}_recall", recall)
  
      f1_macro = (
          report[report.index("macro") :]
          .split("\n")[0]
          .replace("macro avg", "")
          .strip()
          .split()[-2]
      )
      f1_micro = (
          report[report.index("micro") :]
          .split("\n")[0]
          .replace("micro avg", "")
          .strip()
          .split()[-2]
      )
      self.log(f"{split}_f1_macro", torch.Tensor([float(f1_macro)]))
      self.log(f"{split}_f1_micro", torch.Tensor([float(f1_micro)]))
  
      self.classification_report.reset()
  
      if split == "val":
          self.validation_step_outputs.clear()  # free memory
      elif split == "test":
          self.test_step_outputs.clear()
  
imports: import json
  import os
  from typing import List, Optional
  import torch
  from hydra.utils import instantiate
  from omegaconf import DictConfig
  from pytorch_lightning import Trainer
  from nemo.collections.common.losses import CrossEntropyLoss
  from nemo.collections.nlp.metrics.classification_report import ClassificationReport
  from nemo.collections.nlp.modules.common import TokenClassifier
  from nemo.collections.nlp.parts.utils_funcs import tensor2list
  from nemo.collections.tts.g2p.data.heteronym_classification import HeteronymClassificationDataset
  from nemo.collections.tts.g2p.utils import get_heteronym_spans, get_wordid_to_phonemes, read_wordids
  from nemo.core.classes.common import PretrainedModelInfo
  from nemo.utils import logging
label_desc: Use image node_id 7 for calling the HeteronymClassificationModel obj's underlying member method code with example usage: obj.on_validation_epoch_end() without return types