code: def create_trainer(
      model,
      optimizer,
      criterion,
      train_sampler,
      config,
      logger,
      with_clearml,
  ):
      device = config.device
      prepare_batch = data.prepare_image_mask
  
      # Setup trainer
      accumulation_steps = config.get("accumulation_steps", 1)
      model_output_transform = config.get(
          "model_output_transform", lambda x: x
      )
  
      with_amp = config.get("with_amp", True)
      scaler = GradScaler(enabled=with_amp)
  
      def forward_pass(batch):
          model.train()
          x, y = prepare_batch(batch, device=device, non_blocking=True)
          with autocast(enabled=with_amp):
              y_pred = model(x)
              y_pred = model_output_transform(y_pred)
              loss = criterion(y_pred, y) / accumulation_steps
          return loss
  
      def amp_backward_pass(engine, loss):
          scaler.scale(loss).backward()
          if engine.state.iteration % accumulation_steps == 0:
              scaler.step(optimizer)
              scaler.update()
              optimizer.zero_grad()
  
      def hvd_amp_backward_pass(engine, loss):
          scaler.scale(loss).backward()
          optimizer.synchronize()
          with optimizer.skip_synchronize():
              scaler.step(optimizer)
              scaler.update()
          optimizer.zero_grad()
  
      if idist.backend() == "horovod" and with_amp:
          backward_pass = hvd_amp_backward_pass
      else:
          backward_pass = amp_backward_pass
  
      def training_step(engine, batch):
          loss = forward_pass(batch)
          output = {"supervised batch loss": loss.item()}
          backward_pass(engine, loss)
          return output
  
      trainer = Engine(training_step)
      trainer.logger = logger
  
      output_names = [
          "supervised batch loss",
      ]
      lr_scheduler = config.lr_scheduler
  
      to_save = {
          "model": model,
          "optimizer": optimizer,
          "lr_scheduler": lr_scheduler,
          "trainer": trainer,
          "amp": scaler,
      }
  
      save_every_iters = config.get("save_every_iters", 1000)
  
      common.setup_common_training_handlers(
          trainer,
          train_sampler,
          to_save=to_save,
          save_every_iters=save_every_iters,
          save_handler=utils.get_save_handler(
              config.output_path.as_posix(), with_clearml
          ),
          lr_scheduler=lr_scheduler,
          output_names=output_names,
          with_pbars=not with_clearml,
          log_every_iters=1,
      )
  
      resume_from = config.get("resume_from", None)
      if resume_from is not None:
          checkpoint_fp = Path(resume_from)
          assert (
              checkpoint_fp.exists()
          ), f"Checkpoint '{checkpoint_fp.as_posix()}' is not found"
          logger.info(
              f"Resume from a checkpoint: {checkpoint_fp.as_posix()}"
          )
          checkpoint = torch.load(
              checkpoint_fp.as_posix(), map_location="cpu"
          )
          Checkpoint.load_objects(
              to_load=to_save, checkpoint=checkpoint
          )
  
      return trainer
  
imports: import os
  from functools import partial
  from pathlib import Path
  import fire
  import torch
  import dataflow
  import utils
  import vis
  from py_config_runner import ConfigObject, get_params, InferenceConfigSchema, TrainvalConfigSchema
  import ignite.distributed
  from ignite.contrib.engines import common
  from ignite.engine import Engine, Events
  from ignite.handlers import Checkpoint
  from ignite.metrics import ConfusionMatrix, IoU, mIoU
  from ignite.utils import manual_seed, setup_logger
label_desc: Use image node_id 4 for calling a global function with example usage: create_trainer(model, optimizer, criterion, train_sampler, config, logger, with_clearml) and returns: trainer, loss, output