code: def add_final_retrain_ops(
      class_count,
      final_tensor_name,
      bottleneck_tensor,
      quantize_layer,
      is_training,
  ):
      """Adds a new softmax and fully-connected layer for training and eval.
  
      We need to retrain the top layer to identify our new classes, so this function
      adds the right operations to the graph, along with some variables to hold the
      weights, and then sets up all the gradients for the backward pass.
  
      The set up for the softmax and fully-connected layers is based on:
      https://www.tensorflow.org/tutorials/mnist/beginners/index.html
  
      Args:
        class_count: Integer of how many categories of things we're trying to
            recognize.
        final_tensor_name: Name string for the new final node that produces results.
        bottleneck_tensor: The output of the main CNN graph.
        quantize_layer: Boolean, specifying whether the newly added layer should be
            instrumented for quantization with TF-Lite.
        is_training: Boolean, specifying whether the newly add layer is for training
            or eval.
  
      Returns:
        The tensors for the training and cross entropy results, and tensors for the
        bottleneck input and ground truth input.
      """
      (
          batch_size,
          bottleneck_tensor_size,
      ) = bottleneck_tensor.get_shape().as_list()
      assert (
          batch_size is None
      ), "We want to work with arbitrary batch size."
      with tf.name_scope("input"):
          bottleneck_input = tf.placeholder_with_default(
              bottleneck_tensor,
              shape=[batch_size, bottleneck_tensor_size],
              name="BottleneckInputPlaceholder",
          )
  
          ground_truth_input = tf.placeholder(
              tf.int64, [batch_size], name="GroundTruthInput"
          )
  
      # Organizing the following ops so they are easier to see in TensorBoard.
      layer_name = "final_retrain_ops"
      with tf.name_scope(layer_name):
          with tf.name_scope("weights"):
              initial_value = tf.truncated_normal(
                  [bottleneck_tensor_size, class_count], stddev=0.001
              )
              layer_weights = tf.Variable(
                  initial_value, name="final_weights"
              )
              variable_summaries(layer_weights)
  
          with tf.name_scope("biases"):
              layer_biases = tf.Variable(
                  tf.zeros([class_count]), name="final_biases"
              )
              variable_summaries(layer_biases)
  
          with tf.name_scope("Wx_plus_b"):
              logits = (
                  tf.matmul(bottleneck_input, layer_weights)
                  + layer_biases
              )
              tf.summary.histogram("pre_activations", logits)
  
      final_tensor = tf.nn.softmax(logits, name=final_tensor_name)
  
      # The tf.contrib.quantize functions rewrite the graph in place for
      # quantization. The imported model graph has already been rewritten, so upon
      # calling these rewrites, only the newly added final layer will be
      # transformed.
      if quantize_layer:
          if is_training:
              contrib_quantize.create_training_graph()
          else:
              contrib_quantize.create_eval_graph()
  
      tf.summary.histogram("activations", final_tensor)
  
      # If this is an eval graph, we don't need to add loss ops or an optimizer.
      if not is_training:
          return (
              None,
              None,
              bottleneck_input,
              ground_truth_input,
              final_tensor,
          )
  
      with tf.name_scope("cross_entropy"):
          cross_entropy_mean = tf.losses.sparse_softmax_cross_entropy(
              labels=ground_truth_input, logits=logits
          )
  
      tf.summary.scalar("cross_entropy", cross_entropy_mean)
  
      with tf.name_scope("train"):
          optimizer = tf.train.GradientDescentOptimizer(
              FLAGS.learning_rate
          )
          train_step = optimizer.minimize(cross_entropy_mean)
  
      return (
          train_step,
          cross_entropy_mean,
          bottleneck_input,
          ground_truth_input,
          final_tensor,
      )
  
imports: from absl import logging
  import argparse
  import collections
  from datetime import datetime
  import hashlib
  import os.path
  import random
  import re
  import sys
  import numpy
  import tensorflow
  import tensorflow_hub
  from tensorflow.contrib import quantize
label_desc: Use image node_id 15 for calling a global function with example usage: add_final_retrain_ops(class_count, final_tensor_name, bottleneck_tensor, quantize_layer, is_training) and returns: train_step,  cross_entropy_mean,  bottleneck_input,  ground_truth_input,  final_tensor, None,  None,  bottleneck_input,  ground_truth_input,  final_tensor