code: def train(epochs, ctx):
      # Collect all parameters from net and its children, then initialize them.
      net.initialize(mx.init.Xavier(magnitude=2.24), ctx=ctx)
      net.hybridize()
  
      # Trainer is for updating parameters with gradient.
      trainer = gluon.Trainer(
          net.collect_params(),
          "sgd",
          {"learning_rate": opt.lr, "momentum": opt.momentum},
      )
      metric = mx.metric.Accuracy()
      loss = gluon.loss.SoftmaxCrossEntropyLoss()
  
      # collect parameter names for logging the gradients of parameters in each epoch
      params = net.collect_params()
      param_names = params.keys()
  
      # define a summary writer that logs data and flushes to the file every 5 seconds
      sw = SummaryWriter(logdir="./logs", flush_secs=5)
  
      global_step = 0
      for epoch in range(epochs):
          # reset data iterator and metric at begining of epoch.
          metric.reset()
          for i, (data, label) in enumerate(train_data):
              # Copy data to ctx if necessary
              data = data.as_in_context(ctx)
              label = label.as_in_context(ctx)
              # Start recording computation graph with record() section.
              # Recorded graphs can then be differentiated with backward.
              with autograd.record():
                  output = net(data)
                  L = loss(output, label)
              sw.add_scalar(
                  tag="cross_entropy",
                  value=L.mean().asscalar(),
                  global_step=global_step,
              )
              global_step += 1
              L.backward()
  
              # take a gradient step with batch_size equal to data.shape[0]
              trainer.step(data.shape[0])
              # update metric at last.
              metric.update([label], [output])
  
              if i % opt.log_interval == 0 and i > 0:
                  name, train_acc = metric.get()
                  print(
                      "[Epoch %d Batch %d] Training: %s=%f"
                      % (epoch, i, name, train_acc)
                  )
  
              # Log the first batch of images of each epoch
              if i == 0:
                  sw.add_image(
                      "minist_first_minibatch",
                      data.reshape((opt.batch_size, 1, 28, 28)),
                      epoch,
                  )
  
          if epoch == 0:
              sw.add_graph(net)
  
          grads = [i.grad() for i in net.collect_params().values()]
          assert len(grads) == len(param_names)
          # logging the gradients of parameters for checking convergence
          for i, name in enumerate(param_names):
              sw.add_histogram(
                  tag=name,
                  values=grads[i],
                  global_step=epoch,
                  bins=1000,
              )
  
          name, train_acc = metric.get()
          print("[Epoch %d] Training: %s=%f" % (epoch, name, train_acc))
          # logging training accuracy
          sw.add_scalar(
              tag="accuracy_curves",
              value=("train_acc", train_acc),
              global_step=epoch,
          )
  
          name, val_acc = test(ctx)
          print("[Epoch %d] Validation: %s=%f" % (epoch, name, val_acc))
          # logging the validation accuracy
          sw.add_scalar(
              tag="accuracy_curves",
              value=("valid_acc", val_acc),
              global_step=epoch,
          )
  
      sw.export_scalars("scalar_dict.json")
      sw.close()
  
file_path: mxboard/examples/mnist/train_mnist.py
imports: from __future__ import print_function
  import argparse
  import logging
  import numpy
  import mxnet
  from mxnet import gluon, autograd
  from mxnet.gluon import nn
  from mxboard import SummaryWriter
label_desc: Use image node_id 3 for calling a global function with example usage: train(epochs, ctx) without return types