code: def run_training_test(
      root_dir,
      train_x,
      train_y,
      val_x,
      val_y,
      device="cuda:0",
      num_workers=10,
  ):
      monai.config.print_config()
      # define transforms for image and classification
      train_transforms = Compose(
          [
              LoadImage(image_only=True, simple_keys=True),
              EnsureChannelFirst(channel_dim="no_channel"),
              Transpose(indices=[0, 2, 1]),
              ScaleIntensity(),
              RandRotate(
                  range_x=np.pi / 12,
                  prob=0.5,
                  keep_size=True,
                  dtype=np.float64,
              ),
              RandFlip(spatial_axis=0, prob=0.5),
              RandZoom(min_zoom=0.9, max_zoom=1.1, prob=0.5),
          ]
      )
      train_transforms.set_random_state(1234)
      val_transforms = Compose(
          [
              LoadImage(image_only=True, simple_keys=True),
              EnsureChannelFirst(channel_dim="no_channel"),
              Transpose(indices=[0, 2, 1]),
              ScaleIntensity(),
          ]
      )
      y_pred_trans = Compose([Activations(softmax=True)])
      y_trans = AsDiscrete(to_onehot=len(np.unique(train_y)))
      auc_metric = ROCAUCMetric()
  
      # create train, val data loaders
      train_ds = MedNISTDataset(train_x, train_y, train_transforms)
      train_loader = DataLoader(
          train_ds,
          batch_size=300,
          shuffle=True,
          num_workers=num_workers,
      )
  
      val_ds = MedNISTDataset(val_x, val_y, val_transforms)
      val_loader = DataLoader(
          val_ds, batch_size=300, num_workers=num_workers
      )
  
      model = DenseNet121(
          spatial_dims=2,
          in_channels=1,
          out_channels=len(np.unique(train_y)),
      ).to(device)
      loss_function = torch.nn.CrossEntropyLoss()
      optimizer = torch.optim.Adam(model.parameters(), 1e-5)
      epoch_num = 4
      val_interval = 1
  
      # start training validation
      best_metric = -1
      best_metric_epoch = -1
      epoch_loss_values = []
      metric_values = []
      model_filename = os.path.join(root_dir, "best_metric_model.pth")
      for epoch in range(epoch_num):
          print("-" * 10)
          print(f"Epoch {epoch + 1}/{epoch_num}")
          model.train()
          epoch_loss = 0
          step = 0
          for batch_data in train_loader:
              step += 1
              inputs, labels = batch_data[0].to(device), batch_data[
                  1
              ].to(device)
              optimizer.zero_grad()
              outputs = model(inputs)
              loss = loss_function(outputs, labels)
              loss.backward()
              optimizer.step()
              epoch_loss += loss.item()
          epoch_loss /= step
          epoch_loss_values.append(epoch_loss)
          print(f"epoch {epoch + 1} average loss:{epoch_loss:0.4f}")
  
          if (epoch + 1) % val_interval == 0:
              with eval_mode(model):
                  y_pred = torch.tensor(
                      [], dtype=torch.float32, device=device
                  )
                  y = torch.tensor([], dtype=torch.long, device=device)
                  for val_data in val_loader:
                      val_images, val_labels = val_data[0].to(
                          device
                      ), val_data[1].to(device)
                      y_pred = torch.cat(
                          [y_pred, model(val_images)], dim=0
                      )
                      y = torch.cat([y, val_labels], dim=0)
  
                  # compute accuracy
                  acc_value = torch.eq(y_pred.argmax(dim=1), y)
                  acc_metric = acc_value.sum().item() / len(acc_value)
                  # decollate prediction and label and execute post processing
                  y_pred = [
                      y_pred_trans(i) for i in decollate_batch(y_pred)
                  ]
                  y = [
                      y_trans(i)
                      for i in decollate_batch(y, detach=False)
                  ]
                  # compute AUC
                  auc_metric(y_pred, y)
                  auc_value = auc_metric.aggregate()
                  auc_metric.reset()
                  metric_values.append(auc_value)
                  if auc_value > best_metric:
                      best_metric = auc_value
                      best_metric_epoch = epoch + 1
                      torch.save(model.state_dict(), model_filename)
                      print("saved new best metric model")
                  print(
                      f"current epoch {epoch +1} current AUC: {auc_value:0.4f} "
                      f"current accuracy: {acc_metric:0.4f} best AUC: {best_metric:0.4f} at epoch {best_metric_epoch}"
                  )
      print(
          f"train completed, best_metric: {best_metric:0.4f}  at epoch: {best_metric_epoch}"
      )
      return epoch_loss_values, best_metric, best_metric_epoch
  
imports: from __future__ import annotations
  import os
  import unittest
  import warnings
  import numpy
  import torch
  from torch.utils.data import DataLoader
  import monai
  from monai.apps import download_and_extract
  from monai.data import decollate_batch
  from monai.metrics import ROCAUCMetric
  from monai.networks import eval_mode
  from monai.networks.nets import DenseNet121
  from monai.transforms import Activations, AsDiscrete, Compose, EnsureChannelFirst, LoadImage, RandFlip, RandRotate, RandZoom, ScaleIntensity, Transpose
  from monai.utils import set_determinism
  from tests.testing_data.integration_answers import test_integration_value
  from tests.utils import DistTestCase, TimedCall, skip_if_downloading_fails, skip_if_quick, testing_data_config
label_desc: Use image node_id 1 for calling a global function with example usage: run_training_test(root_dir, train_x, train_y, val_x, val_y, device, num_workers) and returns: epoch_loss_values,  best_metric,  best_metric_epoch