docstr: Validation Loop. Pytorch Lightning calls this inside the validation loop with the data from the validation dataloader
  passed in as `batch`.
  
  Args:
      batch: batches of data from DataLoader
      batch_idx: batch idx from DataLoader
  
  Returns: 
      None
docstr_tok: ["Validation","Loop",".","Pytorch","Lightning","calls","this","inside","the","validation","loop","with","the","data","from","the","validation","dataloader","passed","in","as","`","batch","`",".","Args",":","batch",":","batches","of","data","from","DataLoader","batch_idx",":","batch","idx","from","DataLoader","Returns",":","None"]
code: def validation_step(self, batch, batch_idx) -> None:
      """
      Validation Loop. Pytorch Lightning calls this inside the validation loop with the data from the validation dataloader
      passed in as `batch`.
  
      Args:
          batch: batches of data from DataLoader
          batch_idx: batch idx from DataLoader
  
      Returns:
          None
      """
      (
          input_ids,
          input_type_ids,
          input_mask,
          loss_mask,
          subtokens_mask,
          intent_labels,
          slot_labels,
      ) = batch
      intent_logits, slot_logits = self(
          input_ids=input_ids,
          token_type_ids=input_type_ids,
          attention_mask=input_mask,
      )
  
      # calculate combined loss for intents and slots
      intent_loss = self.intent_loss(
          logits=intent_logits, labels=intent_labels
      )
      slot_loss = self.slot_loss(
          logits=slot_logits, labels=slot_labels, loss_mask=loss_mask
      )
      val_loss = self.total_loss(loss_1=intent_loss, loss_2=slot_loss)
  
      intent_probabilities = torch.round(torch.sigmoid(intent_logits))
  
      self.intent_classification_report.update(
          intent_probabilities, intent_labels
      )
      # slots
      subtokens_mask = subtokens_mask > 0.5
      preds = torch.argmax(slot_logits, axis=-1)[subtokens_mask]
      slot_labels = slot_labels[subtokens_mask]
      self.slot_classification_report.update(preds, slot_labels)
  
      loss = {
          "val_loss": val_loss,
          "intent_tp": self.intent_classification_report.tp,
          "intent_fn": self.intent_classification_report.fn,
          "intent_fp": self.intent_classification_report.fp,
          "slot_tp": self.slot_classification_report.tp,
          "slot_fn": self.slot_classification_report.fn,
          "slot_fp": self.slot_classification_report.fp,
      }
      self.validation_step_outputs.append(loss)
      return loss
  
imports: import os
  from typing import List, Optional, Tuple
  import numpy
  import numpy.typing
  import torch
  from omegaconf import DictConfig, OmegaConf
  from pytorch_lightning import Trainer
  from sklearn.metrics import f1_score, precision_score, recall_score
  from torch.utils.data import DataLoader
  from nemo.collections.common.losses import AggregatorLoss, BCEWithLogitsLoss, CrossEntropyLoss
  from nemo.collections.nlp.data.intent_slot_classification import MultiLabelIntentSlotClassificationDataset, MultiLabelIntentSlotDataDesc
  from nemo.collections.nlp.metrics.classification_report import ClassificationReport, MultiLabelClassificationReport
  from nemo.collections.nlp.models.intent_slot_classification import IntentSlotClassificationModel
  from nemo.collections.nlp.modules.common import SequenceTokenClassifier
  from nemo.collections.nlp.parts.utils_funcs import tensor2list
  from nemo.core.classes.common import PretrainedModelInfo
  from nemo.utils import logging
label_desc: Use image node_id 4 for calling the MultiLabelIntentSlotClassificationModel obj's underlying member method code with example usage: obj.validation_step(batch, batch_idx) and returns: loss