code: def train(logger):
      """
      perform the training routine for a given fold. saves plots and selected parameters to the experiment dir
      specified in the configs.
      """
      logger.info(
          "performing training in {}D over fold {} on experiment {} with model {}".format(
              cf.dim, cf.fold, cf.exp_dir, cf.model
          )
      )
  
      net = model.net(cf, logger).cuda()
      optimizer = torch.optim.Adam(
          net.parameters(),
          lr=cf.learning_rate[0],
          weight_decay=cf.weight_decay,
      )
      model_selector = utils.ModelSelector(cf, logger)
      train_evaluator = Evaluator(cf, logger, mode="train")
      val_evaluator = Evaluator(cf, logger, mode=cf.val_mode)
  
      starting_epoch = 1
  
      # prepare monitoring
      monitor_metrics, TrainingPlot = utils.prepare_monitoring(cf)
  
      if cf.resume_to_checkpoint:
          starting_epoch, monitor_metrics = utils.load_checkpoint(
              cf.resume_to_checkpoint, net, optimizer
          )
          logger.info(
              "resumed to checkpoint {} at epoch {}".format(
                  cf.resume_to_checkpoint, starting_epoch
              )
          )
  
      logger.info(
          "loading dataset and initializing batch generators..."
      )
      batch_gen = data_loader.get_train_generators(cf, logger)
  
      for epoch in range(starting_epoch, cf.num_epochs + 1):
          logger.info("starting training epoch {}".format(epoch))
          for param_group in optimizer.param_groups:
              param_group["lr"] = cf.learning_rate[epoch - 1]
  
          start_time = time.time()
  
          net.train()
          train_results_list = []
  
          for bix in range(cf.num_train_batches):
              batch = next(batch_gen["train"])
              tic_fw = time.time()
              results_dict = net.train_forward(batch)
              tic_bw = time.time()
              optimizer.zero_grad()
              results_dict["torch_loss"].backward()
              optimizer.step()
              logger.info(
                  "tr. batch {0}/{1} (ep. {2}) fw {3:.3f}s / bw {4:.3f}s / total {5:.3f}s || ".format(
                      bix + 1,
                      cf.num_train_batches,
                      epoch,
                      tic_bw - tic_fw,
                      time.time() - tic_bw,
                      time.time() - tic_fw,
                  )
                  + results_dict["logger_string"]
              )
              train_results_list.append(
                  [results_dict["boxes"], batch["pid"]]
              )
              monitor_metrics["train"]["monitor_values"][epoch].append(
                  results_dict["monitor_values"]
              )
  
          (
              _,
              monitor_metrics["train"],
          ) = train_evaluator.evaluate_predictions(
              train_results_list, monitor_metrics["train"]
          )
          train_time = time.time() - start_time
  
          logger.info(
              "starting validation in mode {}.".format(cf.val_mode)
          )
          with torch.no_grad():
              net.eval()
              if cf.do_validation:
                  val_results_list = []
                  val_predictor = Predictor(cf, net, logger, mode="val")
                  for _ in range(batch_gen["n_val"]):
                      batch = next(batch_gen[cf.val_mode])
                      if cf.val_mode == "val_patient":
                          results_dict = val_predictor.predict_patient(
                              batch
                          )
                      elif cf.val_mode == "val_sampling":
                          results_dict = net.train_forward(
                              batch, is_validation=True
                          )
                      val_results_list.append(
                          [results_dict["boxes"], batch["pid"]]
                      )
                      monitor_metrics["val"]["monitor_values"][
                          epoch
                      ].append(results_dict["monitor_values"])
  
                  (
                      _,
                      monitor_metrics["val"],
                  ) = val_evaluator.evaluate_predictions(
                      val_results_list, monitor_metrics["val"]
                  )
                  model_selector.run_model_selection(
                      net, optimizer, monitor_metrics, epoch
                  )
  
              # update monitoring and prediction plots
              TrainingPlot.update_and_save(monitor_metrics, epoch)
              epoch_time = time.time() - start_time
              logger.info(
                  "trained epoch {}: took {} sec. ({} train / {} val)".format(
                      epoch,
                      epoch_time,
                      train_time,
                      epoch_time - train_time,
                  )
              )
              batch = next(batch_gen["val_sampling"])
              results_dict = net.train_forward(
                  batch, is_validation=True
              )
              logger.info(
                  "plotting predictions from validation sampling."
              )
              plot_batch_prediction(batch, results_dict, cf)
  
file_path: medicaldetectiontoolkit/exec.py
imports: import argparse
  import os
  import time
  import torch
  import utils.exp_utils
  from evaluator import Evaluator
  from predictor import Predictor
  from plotting import plot_batch_prediction
label_desc: Use image node_id 1 for calling a global function with example usage: train(logger) without return types