code: def SGD(sym, data_inputs, X, Y, X_test, Y_test, total_iter_num,
          lr=None,
          lr_scheduler=None, prior_precision=1,
          out_grad_f=None,
          initializer=None,
          minibatch_size=100, dev=mx.gpu()):
      
      if out_grad_f is None:
          label_key = list(set(data_inputs.keys()) - set(['data']))[0]
      exe, params, params_grad, _ = get_executor(sym, dev, data_inputs, initializer)
      optimizer = mx.optimizer.create('sgd', learning_rate=lr,
                                      rescale_grad=X.shape[0] / minibatch_size,
                                      lr_scheduler=lr_scheduler,
                                      wd=prior_precision)
      updater = mx.optimizer.get_updater(optimizer)
      start = time.time()
      for i in range(total_iter_num):
          indices = numpy.random.randint(X.shape[0], size=minibatch_size)
          X_batch = X[indices]
          Y_batch = Y[indices]
          exe.arg_dict['data'][:] = X_batch
          if out_grad_f is None:
              exe.arg_dict[label_key][:] = Y_batch
              exe.forward(is_train=True)
              exe.backward()
          else:
              exe.forward(is_train=True)
              exe.backward(out_grad_f(exe.outputs, nd.array(Y_batch, ctx=dev)))
          for k in params:
              updater(k, params_grad[k], params[k])
          if (i + 1) % 500 == 0:
              end = time.time()
              print("Current Iter Num: %d" % (i + 1), "Time Spent: %f" % (end - start))
              sample_test_acc(exe, X=X_test, Y=Y_test, label_num=10, minibatch_size=100)
              start = time.time()
      return exe, params, params_grad
docs: Generate the implementation of SGD