code: def train_gluon():
      if args.save_dir:
          save_dir = args.save_dir
          save_dir = os.path.expanduser(save_dir)
          makedirs(save_dir)
      else:
          save_dir = "./"
          save_frequency = 0
  
      def evaluate(epoch):
          acc_top1 = mx.metric.Accuracy()
          acc_top5 = mx.metric.TopKAccuracy(5)
          for _, batch in enumerate(val_data):
              data, label = val_batch_fn(batch, context)
              output = net(data.astype(args.dtype, copy=False))
              acc_top1.update([label], [output])
              acc_top5.update([label], [output])
  
          top1_name, top1_acc = acc_top1.get()
          top5_name, top5_acc = acc_top5.get()
          if MPI is not None:
              comm = MPI.COMM_WORLD
              res1 = comm.gather(top1_acc, root=0)
              res2 = comm.gather(top5_acc, root=0)
          if rank == 0:
              if MPI is not None:
                  # logging.info('MPI gather res1: {}'.format(res1))
                  top1_acc = sum(res1) / len(res1)
                  top5_acc = sum(res2) / len(res2)
              logging.info(
                  "Epoch[%d] Rank[%d]\tValidation-%s=%f\tValidation-%s=%f",
                  epoch,
                  rank,
                  top1_name,
                  top1_acc,
                  top5_name,
                  top5_acc,
              )
  
      # Hybridize and initialize model
      net.hybridize()
      # net.initialize(initializer, ctx=context)
      if args.resume_params != "":
          net.load_parameters(args.resume_params, ctx=context)
  
      else:
          net.initialize(initializer, ctx=context)
  
      if args.no_wd:
          for k, v in net.collect_params(
              ".*beta|.*gamma|.*bias"
          ).items():
              v.wd_mult = 0.0
  
      # Horovod: fetch and broadcast parameters
      params = net.collect_params()
      if params is not None:
          hvd.broadcast_parameters(params, root_rank=0)
  
      # Create optimizer
      optimizer = "nag"
      optimizer_params = {
          "wd": args.wd,
          "momentum": args.momentum,
          "lr_scheduler": lr_sched,
      }
      if args.dtype == "float16":
          optimizer_params["multi_precision"] = True
      opt = mx.optimizer.create(optimizer, **optimizer_params)
  
      # Horovod: create DistributedTrainer, a subclass of gluon.Trainer
      trainer = hvd.DistributedTrainer(params, opt)
      if args.resume_states != "":
          trainer.load_states(args.resume_states)
  
      # Create loss function and train metric
      if args.label_smoothing or args.mixup:
          sparse_label_loss = False
      else:
          sparse_label_loss = True
  
      distillation = args.teacher is not None and args.hard_weight < 1.0
      if distillation:
          teacher = get_model(
              args.teacher,
              pretrained=True,
              classes=num_classes,
              ctx=context,
          )
          teacher.hybridize()
          teacher.cast(args.dtype)
          loss_fn = gcv.loss.DistillationSoftmaxCrossEntropyLoss(
              temperature=args.temperature,
              hard_weight=args.hard_weight,
              sparse_label=sparse_label_loss,
          )
          if rank == 0:
              logging.info("Using Distillation")
      else:
          loss_fn = gluon.loss.SoftmaxCrossEntropyLoss(
              sparse_label=sparse_label_loss
          )
      if args.mixup:
          train_metric = mx.metric.RMSE()
      else:
          train_metric = mx.metric.Accuracy()
  
      def mixup_transform(label, classes, lam=1, eta=0.0):
          if isinstance(label, mx.nd.NDArray):
              label = [label]
          res = []
          for l in label:
              y1 = l.one_hot(
                  classes,
                  on_value=1 - eta + eta / classes,
                  off_value=eta / classes,
              )
              y2 = l[::-1].one_hot(
                  classes,
                  on_value=1 - eta + eta / classes,
                  off_value=eta / classes,
              )
              res.append(lam * y1 + (1 - lam) * y2)
          return res
  
      def smooth(label, classes, eta=0.1):
          if isinstance(label, mx.NDArray):
              label = [label]
          smoothed = []
          for l in label:
              res = l.one_hot(
                  classes,
                  on_value=1 - eta + eta / classes,
                  off_value=eta / classes,
              )
              smoothed.append(res)
          return smoothed
  
      # Train model
      for epoch in range(args.resume_epoch, args.num_epochs):
          drop_scheduler(epoch)
          tic = time.time()
          train_metric.reset()
  
          btic = time.time()
          for nbatch, batch in enumerate(train_data, start=1):
              data, label = train_batch_fn(batch, context)
              data, label = [data], [label]
              if args.mixup:
                  lam = np.random.beta(
                      args.mixup_alpha, args.mixup_alpha
                  )
                  if epoch >= args.num_epochs - args.mixup_off_epoch:
                      lam = 1
                  data = [lam * X + (1 - lam) * X[::-1] for X in data]
  
                  if args.label_smoothing:
                      eta = 0.1
                  else:
                      eta = 0.0
                  label = mixup_transform(label, num_classes, lam, eta)
  
              elif args.label_smoothing:
                  hard_label = label
                  label = smooth(label, num_classes)
  
              if distillation:
                  teacher_prob = [
                      mx.nd.softmax(
                          teacher(X.astype(args.dtype, copy=False))
                          / args.temperature
                      )
                      for X in data
                  ]
  
              with autograd.record():
                  outputs = [
                      net(X.astype(args.dtype, copy=False))
                      for X in data
                  ]
                  if distillation:
                      loss = [
                          loss_fn(
                              yhat.astype("float32", copy=False),
                              y.astype("float32", copy=False),
                              p.astype("float32", copy=False),
                          )
                          for yhat, y, p in zip(
                              outputs, label, teacher_prob
                          )
                      ]
                  else:
                      loss = [
                          loss_fn(
                              yhat, y.astype(args.dtype, copy=False)
                          )
                          for yhat, y in zip(outputs, label)
                      ]
              for l in loss:
                  l.backward()
              trainer.step(batch_size)
  
              if args.mixup:
                  output_softmax = [
                      mx.nd.SoftmaxActivation(
                          out.astype("float32", copy=False)
                      )
                      for out in outputs
                  ]
                  train_metric.update(label, output_softmax)
              else:
                  if args.label_smoothing:
                      train_metric.update(hard_label, outputs)
                  else:
                      train_metric.update(label, outputs)
  
              if args.log_interval and nbatch % args.log_interval == 0:
                  if rank == 0:
                      logging.info(
                          "Epoch[%d] Batch[%d] Loss[%.3f]",
                          epoch,
                          nbatch,
                          loss[0].mean().asnumpy()[0],
                      )
  
                      (
                          train_metric_name,
                          train_metric_score,
                      ) = train_metric.get()
                      logging.info(
                          "Epoch[%d] Rank[%d] Batch[%d]\t%s=%f\tlr=%f",
                          epoch,
                          rank,
                          nbatch,
                          train_metric_name,
                          train_metric_score,
                          trainer.learning_rate,
                      )
                      # batch_speed = num_workers * batch_size * args.log_interval / (time.time() - btic)
                      # logging.info('Epoch[%d] Batch[%d]\tSpeed: %.2f samples/sec',
                      #             epoch, nbatch, batch_speed)
                  btic = time.time()
  
          # Report metrics
          elapsed = time.time() - tic
          _, acc = train_metric.get()
          if rank == 0:
              logging.info(
                  "Epoch[%d] Rank[%d] Batch[%d]\tTime cost=%.2f\tTrain-metric=%f",
                  epoch,
                  rank,
                  nbatch,
                  elapsed,
                  acc,
              )
              epoch_speed = num_workers * batch_size * nbatch / elapsed
              logging.info(
                  "Epoch[%d]\tSpeed: %.2f samples/sec",
                  epoch,
                  epoch_speed,
              )
  
          # Evaluate performance
          if (
              args.eval_frequency
              and (epoch + 1) % args.eval_frequency == 0
          ):
              evaluate(epoch)
  
          # Save model
          if (
              args.save_frequency
              and (epoch + 1) % args.save_frequency == 0
          ):
              net.save_parameters(
                  "%s/imagenet-%s-%d.params"
                  % (save_dir, args.model, epoch)
              )
              trainer.save_states(
                  "%s/imagenet-%s-%d.states"
                  % (save_dir, args.model, epoch)
              )
  
      # Evaluate performance at the end of training
      evaluate(epoch)
  
      net.save_parameters(
          "%s/imagenet-%s-%d.params"
          % (save_dir, args.model, args.num_epochs - 1)
      )
      trainer.save_states(
          "%s/imagenet-%s-%d.states"
          % (save_dir, args.model, args.num_epochs - 1)
      )
  
imports: import os
  import argparse
  import logging
  import math
  import time
  import random
  import gluoncv
  from gluoncv.model_zoo import get_model
  from gluoncv.utils import makedirs
  import horovod.mxnet
  import mxnet
  import numpy
  from mxnet import autograd, gluon, lr_scheduler
  from mxnet.io import DataBatch, DataIter
  from mxnet.gluon.data.vision import transforms
  from PIL import Image
  from gluoncv.nn.dropblock import DropBlockScheduler
label_desc: Use image node_id 3 for calling a global function with example usage: train_gluon() and returns: res, smoothed