code: def lr_model_fn(features, labels, mode, nclasses, dim):
      """Model function for logistic regression."""
      input_layer = tf.reshape(features["x"], tuple([-1]) + dim)
      logits = tf.keras.layers.Dense(
          units=nclasses,
          kernel_regularizer=tf.keras.regularizers.L2(
              l2=FLAGS.regularizer
          ),
          bias_regularizer=tf.keras.regularizers.L2(
              l2=FLAGS.regularizer
          ),
      )(input_layer)
  
      # Calculate loss as a vector (to support microbatches in DP-SGD).
      vector_loss = (
          tf.nn.sparse_softmax_cross_entropy_with_logits(labels, logits)
          + tf.compat.v1.losses.get_regularization_loss()
      )
      # Define mean of loss across minibatch (for reporting through tf.Estimator).
      scalar_loss = tf.reduce_mean(vector_loss)
  
      # Configure the training op (for TRAIN mode).
      if mode == tf_estimator.ModeKeys.TRAIN:
          if FLAGS.dpsgd:
              # The loss function is L-Lipschitz with L = sqrt(2*(||x||^2 + 1)) where
              # ||x|| is the norm of the data.
              # We don't use microbatches (thus speeding up computation), since no
              # clipping is necessary due to data normalization.
              optimizer = (
                  dp_optimizer.DPGradientDescentGaussianOptimizer(
                      l2_norm_clip=math.sqrt(
                          2 * (FLAGS.data_l2_norm**2 + 1)
                      ),
                      noise_multiplier=FLAGS.noise_multiplier,
                      num_microbatches=1,
                      learning_rate=FLAGS.learning_rate,
                  )
              )
              opt_loss = vector_loss
          else:
              optimizer = GradientDescentOptimizer(
                  learning_rate=FLAGS.learning_rate
              )
              opt_loss = scalar_loss
          global_step = tf.compat.v1.train.get_global_step()
          train_op = optimizer.minimize(
              loss=opt_loss, global_step=global_step
          )
          # In the following, we pass the mean of the loss (scalar_loss) rather than
          # the vector_loss because tf.estimator requires a scalar loss. This is only
          # used for evaluation and debugging by tf.estimator. The actual loss being
          # minimized is opt_loss defined above and passed to optimizer.minimize().
          return tf_estimator.EstimatorSpec(
              mode=mode, loss=scalar_loss, train_op=train_op
          )
  
      # Add evaluation metrics (for EVAL mode).
      elif mode == tf_estimator.ModeKeys.EVAL:
          eval_metric_ops = {
              "accuracy": tf.compat.v1.metrics.accuracy(
                  labels=labels,
                  predictions=tf.argmax(input=logits, axis=1),
              )
          }
          return tf_estimator.EstimatorSpec(
              mode=mode,
              loss=scalar_loss,
              eval_metric_ops=eval_metric_ops,
          )
  
file_path: privacy/tutorials/mnist_lr_tutorial.py
imports: import math
  from absl import app
  from absl import flags
  from absl import logging
  import dp_accounting
  import numpy
  import tensorflow
  from tensorflow import estimator
  from tensorflow.compat.v1 import estimator
  from tensorflow_privacy.privacy.optimizers import dp_optimizer
label_desc: Use image node_id 1 for calling a global function with example usage: lr_model_fn(features, labels, mode, nclasses, dim) and returns: tf_estimator, tf_estimator