docstr: The validation loop ruunning a single validation epoch.
  
  Args:
      model: the LightningModule to evaluate
      val_loader: The dataloader yielding the validation batches.
      limit_batches: Limits the batches during this validation epoch.
          If greater than the number of batches in the ``val_loader``, this has no effect.
docstr_tok: ["The","validation","loop","ruunning","a","single","validation","epoch",".","Args",":","model",":","the","LightningModule","to","evaluate","val_loader",":","The","dataloader","yielding","the","validation","batches",".","limit_batches",":","Limits","the","batches","during","this","validation","epoch",".","If","greater","than","the","number","of","batches","in","the","``","val_loader","``",",","this","has","no","effect","."]
code: def val_loop(
      self,
      model: L.LightningModule,
      val_loader: Optional[torch.utils.data.DataLoader],
      limit_batches: Union[int, float] = float("inf"),
  ):
      """The validation loop ruunning a single validation epoch.
  
      Args:
          model: the LightningModule to evaluate
          val_loader: The dataloader yielding the validation batches.
          limit_batches: Limits the batches during this validation epoch.
              If greater than the number of batches in the ``val_loader``, this has no effect.
  
      """
      # no validation if val_loader wasn't passed
      if val_loader is None:
          return
  
      # no validation but warning if val_loader was passed, but validation_step not implemented
      if val_loader is not None and not is_overridden(
          "validation_step", _unwrap_objects(model)
      ):
          L.fabric.utilities.rank_zero_warn(
              "Your LightningModule does not have a validation_step implemented, "
              "but you passed a validation dataloder. Skipping Validation."
          )
          return
  
      self.fabric.call(
          "on_validation_model_eval"
      )  # calls `model.eval()`
  
      torch.set_grad_enabled(False)
  
      self.fabric.call("on_validation_epoch_start")
  
      iterable = self.progbar_wrapper(
          val_loader,
          total=min(len(val_loader), limit_batches),
          desc="Validation",
      )
  
      for batch_idx, batch in enumerate(iterable):
          # end epoch if stopping training completely or max batches for this epoch reached
          if self.should_stop or batch_idx >= limit_batches:
              break
  
          self.fabric.call(
              "on_validation_batch_start", batch, batch_idx
          )
  
          out = model.validation_step(batch, batch_idx)
          # avoid gradients in stored/accumulated values -> prevents potential OOM
          out = apply_to_collection(
              out, torch.Tensor, lambda x: x.detach()
          )
  
          self.fabric.call(
              "on_validation_batch_end", out, batch, batch_idx
          )
          self._current_val_return = out
  
          self._format_iterable(
              iterable, self._current_val_return, "val"
          )
  
      self.fabric.call("on_validation_epoch_end")
  
      self.fabric.call("on_validation_model_train")
      torch.set_grad_enabled(True)
  
imports: import os
  from collections.abc import Mapping
  from functools import partial
  from typing import Any, Iterable, List, Literal, Optional, Tuple, Union, cast
  import lightning
  import torch
  from lightning.fabric.accelerators import Accelerator
  from lightning.fabric.loggers import Logger
  from lightning.fabric.strategies import Strategy
  from lightning.fabric.wrappers import _unwrap_objects
  from lightning.pytorch.utilities.model_helpers import is_overridden
  from lightning_utilities import apply_to_collection
  from tqdm import tqdm
label_desc: Use image node_id 4 for calling the MyCustomTrainer obj's underlying member method code with example usage: obj.val_loop(model, val_loader, limit_batches) without return types