code: def run(
      train_batch_size,
      val_batch_size,
      epochs,
      lr,
      momentum,
      log_interval,
      log_dir,
      checkpoint_every,
      resume_from,
      crash_iteration=-1,
      deterministic=False,
  ):
      # Setup seed to have same model's initialization:
      manual_seed(75)
  
      train_loader, val_loader = get_data_loaders(
          train_batch_size, val_batch_size
      )
      model = Net()
      writer = SummaryWriter(log_dir=log_dir)
      device = "cpu"
  
      if torch.cuda.is_available():
          device = "cuda"
  
      model.to(device)  # Move model before creating optimizer
      criterion = nn.NLLLoss()
      optimizer = SGD(model.parameters(), lr=lr, momentum=momentum)
      lr_scheduler = StepLR(optimizer, step_size=1, gamma=0.5)
  
      # Setup trainer and evaluator
      if deterministic:
          tqdm.write("Setup deterministic trainer")
      trainer = create_supervised_trainer(
          model,
          optimizer,
          criterion,
          device=device,
          deterministic=deterministic,
      )
      running_loss = RunningAverage(output_transform=lambda x: x)
      running_loss.attach(trainer, "rloss")
  
      metrics = {"accuracy": Accuracy(), "nll": Loss(criterion)}
      evaluator = create_supervised_evaluator(model, metrics, device)
  
      # Apply learning rate scheduling
      @trainer.on(Events.EPOCH_COMPLETED)
      def lr_step(engine):
          lr_scheduler.step()
  
      pbar = tqdm(
          initial=0,
          leave=False,
          total=len(train_loader),
          desc=f"Epoch {0} - loss: {0:.4f} - lr: {lr:.4f}",
      )
  
      @trainer.on(Events.ITERATION_COMPLETED(every=log_interval))
      def log_training_loss(engine):
          lr = optimizer.param_groups[0]["lr"]
          rloss = engine.state.metrics["rloss"]
          pbar.desc = f"Epoch {engine.state.epoch} - loss: {rloss:.4f} - lr: {lr:.4f}"
          pbar.update(log_interval)
          writer.add_scalar(
              "training/running_loss", rloss, engine.state.iteration
          )
          writer.add_scalar("lr", lr, engine.state.iteration)
  
      if crash_iteration > 0:
  
          @trainer.on(Events.ITERATION_COMPLETED(once=crash_iteration))
          def _(engine):
              raise Exception(f"STOP at {engine.state.iteration}")
  
      if resume_from is not None:
  
          @trainer.on(Events.STARTED)
          def _(engine):
              pbar.n = (
                  engine.state.iteration % engine.state.epoch_length
              )
  
      @trainer.on(Events.EPOCH_COMPLETED)
      def log_training_results(engine):
          pbar.refresh()
          evaluator.run(train_loader)
          metrics = evaluator.state.metrics
          avg_accuracy = metrics["accuracy"]
          avg_nll = metrics["nll"]
          tqdm.write(
              f"Training Results - Epoch: {engine.state.epoch} Avg accuracy: {avg_accuracy:.2f} Avg loss: {avg_nll:.2f}"
          )
          writer.add_scalar(
              "training/avg_loss", avg_nll, engine.state.epoch
          )
          writer.add_scalar(
              "training/avg_accuracy", avg_accuracy, engine.state.epoch
          )
  
      # Compute and log validation metrics
      @trainer.on(Events.EPOCH_COMPLETED)
      def log_validation_results(engine):
          evaluator.run(val_loader)
          metrics = evaluator.state.metrics
          avg_accuracy = metrics["accuracy"]
          avg_nll = metrics["nll"]
          tqdm.write(
              f"Validation Results - Epoch: {engine.state.epoch} Avg accuracy: {avg_accuracy:.2f} Avg loss: {avg_nll:.2f}"
          )
          pbar.n = pbar.last_print_n = 0
          writer.add_scalar(
              "valdation/avg_loss", avg_nll, engine.state.epoch
          )
          writer.add_scalar(
              "valdation/avg_accuracy", avg_accuracy, engine.state.epoch
          )
  
      # Setup object to checkpoint
      objects_to_checkpoint = {
          "trainer": trainer,
          "model": model,
          "optimizer": optimizer,
          "lr_scheduler": lr_scheduler,
          "train_running_loss": running_loss,
          "metrics": metrics,
      }
      training_checkpoint = Checkpoint(
          to_save=objects_to_checkpoint,
          save_handler=DiskSaver(log_dir, require_empty=False),
          n_saved=None,
          global_step_transform=lambda *_: trainer.state.epoch,
      )
      trainer.add_event_handler(
          Events.EPOCH_COMPLETED(every=checkpoint_every),
          training_checkpoint,
      )
  
      # Setup logger to print and dump into file: model weights, model grads and data stats
      # - first 3 iterations
      # - 4 iterations after checkpointing
      # This helps to compare resumed training with checkpointed training
      def log_event_filter(e, event):
          if event in [1, 2, 3]:
              return True
          elif (
              0
              <= (event % (checkpoint_every * e.state.epoch_length))
              < 5
          ):
              return True
          return False
  
      fp = Path(log_dir) / (
          "run.log" if resume_from is None else "resume_run.log"
      )
      fp = fp.as_posix()
      for h in [log_data_stats, log_model_weights, log_model_grads]:
          trainer.add_event_handler(
              Events.ITERATION_COMPLETED(event_filter=log_event_filter),
              h,
              model=model,
              fp=fp,
          )
  
      if resume_from is not None:
          tqdm.write(f"Resume from the checkpoint: {resume_from}")
          checkpoint = torch.load(resume_from)
          Checkpoint.load_objects(
              to_load=objects_to_checkpoint, checkpoint=checkpoint
          )
  
      try:
          # Synchronize random states
          manual_seed(15)
          trainer.run(train_loader, max_epochs=epochs)
      except Exception as e:
          import traceback
  
          print(traceback.format_exc())
  
      pbar.close()
      writer.close()
  
imports: from argparse import ArgumentParser
  from pathlib import Path
  import torch
  import torch.nn.functional
  from torch import nn
  from torch.optim import SGD
  from torch.optim.lr_scheduler import StepLR
  from torch.utils.data import DataLoader
  from torchvision.datasets import MNIST
  from torchvision.transforms import Compose, Normalize, ToTensor
  from tqdm import tqdm
  from ignite.engine import create_supervised_evaluator, create_supervised_trainer, Events
  from ignite.handlers import Checkpoint, DiskSaver
  from ignite.metrics import Accuracy, Loss, RunningAverage
  from ignite.utils import manual_seed
label_desc: Use image node_id 5 for calling a global function with example usage: run(train_batch_size, val_batch_size, epochs, lr, momentum, log_interval, log_dir, checkpoint_every, resume_from, crash_iteration, deterministic) and returns: False, True, True