code: def train_sub(
      sess,
      x,
      y,
      bbox_preds,
      x_sub,
      y_sub,
      nb_classes,
      nb_epochs_s,
      batch_size,
      learning_rate,
      data_aug,
      lmbda,
      aug_batch_size,
      rng,
      img_rows=28,
      img_cols=28,
      nchannels=1,
  ):
      """
      This function creates the substitute by alternatively
      augmenting the training data and training the substitute.
      :param sess: TF session
      :param x: input TF placeholder
      :param y: output TF placeholder
      :param bbox_preds: output of black-box model predictions
      :param x_sub: initial substitute training data
      :param y_sub: initial substitute training labels
      :param nb_classes: number of output classes
      :param nb_epochs_s: number of epochs to train substitute model
      :param batch_size: size of training batches
      :param learning_rate: learning rate for training
      :param data_aug: number of times substitute training data is augmented
      :param lmbda: lambda from arxiv.org/abs/1602.02697
      :param rng: numpy.random.RandomState instance
      :return:
      """
      # Define TF model graph (for the black-box model)
      model_sub = ModelSubstitute("model_s", nb_classes)
      preds_sub = model_sub.get_logits(x)
      loss_sub = CrossEntropy(model_sub, smoothing=0)
  
      print("Defined TensorFlow model graph for the substitute.")
  
      # Define the Jacobian symbolically using TensorFlow
      grads = jacobian_graph(preds_sub, x, nb_classes)
  
      # Train the substitute and augment dataset alternatively
      for rho in xrange(data_aug):
          print("Substitute training epoch #" + str(rho))
          train_params = {
              "nb_epochs": nb_epochs_s,
              "batch_size": batch_size,
              "learning_rate": learning_rate,
          }
          with TemporaryLogLevel(
              logging.WARNING, "cleverhans.utils.tf"
          ):
              train(
                  sess,
                  loss_sub,
                  x_sub,
                  to_categorical(y_sub, nb_classes),
                  init_all=False,
                  args=train_params,
                  rng=rng,
                  var_list=model_sub.get_params(),
              )
  
          # If we are not at last substitute training iteration, augment dataset
          if rho < data_aug - 1:
              print("Augmenting substitute training data.")
              # Perform the Jacobian augmentation
              lmbda_coef = 2 * int(int(rho / 3) % 2 == 0) - 1
              x_sub = jacobian_augmentation(
                  sess,
                  x,
                  x_sub,
                  y_sub,
                  grads,
                  lmbda_coef * lmbda,
                  aug_batch_size,
              )
  
              print("Labeling substitute training data.")
              # Label the newly generated synthetic points using the black-box
              y_sub = np.hstack([y_sub, y_sub])
              x_sub_prev = x_sub[int(len(x_sub) / 2) :]
              eval_params = {"batch_size": batch_size}
              bbox_val = batch_eval(
                  sess,
                  [x],
                  [bbox_preds],
                  [x_sub_prev],
                  args=eval_params,
              )[0]
              # Note here that we take the argmax because the adversary
              # only has access to the label (not the probabilities) output
              # by the black-box model
              y_sub[int(len(x_sub) / 2) :] = np.argmax(bbox_val, axis=1)
  
      return model_sub, preds_sub
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  from __future__ import unicode_literals
  import functools
  import logging
  import numpy
  from six.moves import xrange
  import tensorflow
  from cleverhans.attacks import FastGradientMethod
  from cleverhans.utils_tf import jacobian_graph, jacobian_augmentation
  from cleverhans.compat import flags
  from cleverhans.dataset import MNIST
  from cleverhans.initializers import HeReLuNormalInitializer
  from cleverhans.loss import CrossEntropy
  from cleverhans.model import Model
  from cleverhans.train import train
  from cleverhans.utils import set_log_level
  from cleverhans.utils import TemporaryLogLevel
  from cleverhans.utils import to_categorical
  from cleverhans.utils_tf import model_eval, batch_eval
  from cleverhans.model_zoo.basic_cnn import ModelBasicCNN
label_desc: Use image node_id 3 for calling a global function with example usage: train_sub(sess, x, y, bbox_preds, x_sub, y_sub, nb_classes, nb_epochs_s, batch_size, learning_rate, data_aug, lmbda, aug_batch_size, rng, img_rows, img_cols, nchannels) and returns: model_sub,  preds_sub