code: # Copyright 2019 The TensorFlow Authors. All Rights Reserved.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  # ==============================================================================
  """Run BERT on SQuAD 1.1 and SQuAD 2.0 in TF 2.x."""
  
  from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  
  import json
  import os
  import time
  
  # Import libraries
  from absl import app
  from absl import flags
  from absl import logging
  import gin
  import tensorflow as tf
  from official.common import distribute_utils
  from official.nlp.bert import configs as bert_configs
  from official.nlp.bert import run_squad_helper
  from official.nlp.bert import tokenization
  from official.nlp.data import squad_lib as squad_lib_wp
  from official.utils.misc import keras_utils
  
  
  flags.DEFINE_string('vocab_file', None,
                      'The vocabulary file that the BERT model was trained on.')
  
  # More flags can be found in run_squad_helper.
  run_squad_helper.define_common_squad_flags()
  
  FLAGS = flags.FLAGS
  
  
  def train_squad(strategy,
                  input_meta_data,
                  custom_callbacks=None,
                  run_eagerly=False,
                  init_checkpoint=None,
                  sub_model_export_name=None):
    """Run bert squad training."""
    bert_config = bert_configs.BertConfig.from_json_file(FLAGS.bert_config_file)
    init_checkpoint = init_checkpoint or FLAGS.init_checkpoint
    run_squad_helper.train_squad(strategy, input_meta_data, bert_config,
                                 custom_callbacks, run_eagerly, init_checkpoint,
                                 sub_model_export_name=sub_model_export_name)
  
  
  def predict_squad(strategy, input_meta_data):
    """Makes predictions for the squad dataset."""
    bert_config = bert_configs.BertConfig.from_json_file(FLAGS.bert_config_file)
    tokenizer = tokenization.FullTokenizer(
        vocab_file=FLAGS.vocab_file, do_lower_case=FLAGS.do_lower_case)
    run_squad_helper.predict_squad(
        strategy, input_meta_data, tokenizer, bert_config, squad_lib_wp)
  
  
  def eval_squad(strategy, input_meta_data):
    """Evaluate on the squad dataset."""
    bert_config = bert_configs.BertConfig.from_json_file(FLAGS.bert_config_file)
    tokenizer = tokenization.FullTokenizer(
        vocab_file=FLAGS.vocab_file, do_lower_case=FLAGS.do_lower_case)
    eval_metrics = run_squad_helper.eval_squad(
        strategy, input_meta_data, tokenizer, bert_config, squad_lib_wp)
    return eval_metrics
  
  
  def export_squad(model_export_path, input_meta_data):
    """Exports a trained model as a `SavedModel` for inference.
  
    Args:
      model_export_path: a string specifying the path to the SavedModel directory.
      input_meta_data: dictionary containing meta data about input and model.
  
    Raises:
      Export path is not specified, got an empty string or None.
    """
    bert_config = bert_configs.BertConfig.from_json_file(FLAGS.bert_config_file)
    run_squad_helper.export_squad(model_export_path, input_meta_data, bert_config)
  
  
  def main(_):
    gin.parse_config_files_and_bindings(FLAGS.gin_file, FLAGS.gin_param)
  
    with tf.io.gfile.GFile(FLAGS.input_meta_data_path, 'rb') as reader:
      input_meta_data = json.loads(reader.read().decode('utf-8'))
  
    if FLAGS.mode == 'export_only':
      export_squad(FLAGS.model_export_path, input_meta_data)
      return
  
    # Configures cluster spec for multi-worker distribution strategy.
    if FLAGS.num_gpus > 0:
      _ = distribute_utils.configure_cluster(FLAGS.worker_hosts, FLAGS.task_index)
    strategy = distribute_utils.get_distribution_strategy(
        distribution_strategy=FLAGS.distribution_strategy,
        num_gpus=FLAGS.num_gpus,
        all_reduce_alg=FLAGS.all_reduce_alg,
        tpu_address=FLAGS.tpu)
  
    if 'train' in FLAGS.mode:
      if FLAGS.log_steps:
        custom_callbacks = [keras_utils.TimeHistory(
            batch_size=FLAGS.train_batch_size,
            log_steps=FLAGS.log_steps,
            logdir=FLAGS.model_dir,
        )]
      else:
        custom_callbacks = None
  
      train_squad(
          strategy,
          input_meta_data,
          custom_callbacks=custom_callbacks,
          run_eagerly=FLAGS.run_eagerly,
          sub_model_export_name=FLAGS.sub_model_export_name,
      )
    if 'predict' in FLAGS.mode:
      predict_squad(strategy, input_meta_data)
    if 'eval' in FLAGS.mode:
      eval_metrics = eval_squad(strategy, input_meta_data)
      f1_score = eval_metrics['final_f1']
      logging.info('SQuAD eval F1-score: %f', f1_score)
      summary_dir = os.path.join(FLAGS.model_dir, 'summaries', 'eval')
      summary_writer = tf.summary.create_file_writer(summary_dir)
      with summary_writer.as_default():
        # TODO(lehou): write to the correct step number.
        tf.summary.scalar('F1-score', f1_score, step=0)
        summary_writer.flush()
      # Also write eval_metrics to json file.
      squad_lib_wp.write_to_json_files(
          eval_metrics, os.path.join(summary_dir, 'eval_metrics.json'))
      time.sleep(60)
  
  
  if __name__ == '__main__':
    flags.mark_flag_as_required('bert_config_file')
    flags.mark_flag_as_required('model_dir')
    app.run(main)
   # Copyright 2019 The TensorFlow Authors. All Rights Reserved.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  # ==============================================================================
  
  """Tensorflow Example proto decoder for object detection.
  
  A decoder to decode string tensors containing serialized tensorflow.Example
  protos for object detection.
  """
  import tensorflow as tf
  
  
  class TfExampleDecoder(object):
    """Tensorflow Example proto decoder."""
  
    def __init__(self, include_mask=False):
      self._include_mask = include_mask
      self._keys_to_features = {
          'image/encoded':
              tf.io.FixedLenFeature((), tf.string),
          'image/source_id':
              tf.io.FixedLenFeature((), tf.string),
          'image/height':
              tf.io.FixedLenFeature((), tf.int64),
          'image/width':
              tf.io.FixedLenFeature((), tf.int64),
          'image/object/bbox/xmin':
              tf.io.VarLenFeature(tf.float32),
          'image/object/bbox/xmax':
              tf.io.VarLenFeature(tf.float32),
          'image/object/bbox/ymin':
              tf.io.VarLenFeature(tf.float32),
          'image/object/bbox/ymax':
              tf.io.VarLenFeature(tf.float32),
          'image/object/class/label':
              tf.io.VarLenFeature(tf.int64),
          'image/object/area':
              tf.io.VarLenFeature(tf.float32),
          'image/object/is_crowd':
              tf.io.VarLenFeature(tf.int64),
      }
      if include_mask:
        self._keys_to_features.update({
            'image/object/mask':
                tf.io.VarLenFeature(tf.string),
        })
  
    def _decode_image(self, parsed_tensors):
      """Decodes the image and set its static shape."""
      image = tf.io.decode_image(parsed_tensors['image/encoded'], channels=3)
      image.set_shape([None, None, 3])
      return image
  
    def _decode_boxes(self, parsed_tensors):
      """Concat box coordinates in the format of [ymin, xmin, ymax, xmax]."""
      xmin = parsed_tensors['image/object/bbox/xmin']
      xmax = parsed_tensors['image/object/bbox/xmax']
      ymin = parsed_tensors['image/object/bbox/ymin']
      ymax = parsed_tensors['image/object/bbox/ymax']
      return tf.stack([ymin, xmin, ymax, xmax], axis=-1)
  
    def _decode_masks(self, parsed_tensors):
      """Decode a set of PNG masks to the tf.float32 tensors."""
      def _decode_png_mask(png_bytes):
        mask = tf.squeeze(
            tf.io.decode_png(png_bytes, channels=1, dtype=tf.uint8), axis=-1)
        mask = tf.cast(mask, dtype=tf.float32)
        mask.set_shape([None, None])
        return mask
  
      height = parsed_tensors['image/height']
      width = parsed_tensors['image/width']
      masks = parsed_tensors['image/object/mask']
      return tf.cond(
          pred=tf.greater(tf.size(input=masks), 0),
          true_fn=lambda: tf.map_fn(_decode_png_mask, masks, dtype=tf.float32),
          false_fn=lambda: tf.zeros([0, height, width], dtype=tf.float32))
  
    def _decode_areas(self, parsed_tensors):
      xmin = parsed_tensors['image/object/bbox/xmin']
      xmax = parsed_tensors['image/object/bbox/xmax']
      ymin = parsed_tensors['image/object/bbox/ymin']
      ymax = parsed_tensors['image/object/bbox/ymax']
      return tf.cond(
          tf.greater(tf.shape(parsed_tensors['image/object/area'])[0], 0),
          lambda: parsed_tensors['image/object/area'],
          lambda: (xmax - xmin) * (ymax - ymin))
  
    def decode(self, serialized_example):
      """Decode the serialized example.
  
      Args:
        serialized_example: a single serialized tf.Example string.
  
      Returns:
        decoded_tensors: a dictionary of tensors with the following fields:
          - image: a uint8 tensor of shape [None, None, 3].
          - source_id: a string scalar tensor.
          - height: an integer scalar tensor.
          - width: an integer scalar tensor.
          - groundtruth_classes: a int64 tensor of shape [None].
          - groundtruth_is_crowd: a bool tensor of shape [None].
          - groundtruth_area: a float32 tensor of shape [None].
          - groundtruth_boxes: a float32 tensor of shape [None, 4].
          - groundtruth_instance_masks: a float32 tensor of shape
              [None, None, None].
          - groundtruth_instance_masks_png: a string tensor of shape [None].
      """
      parsed_tensors = tf.io.parse_single_example(
          serialized=serialized_example, features=self._keys_to_features)
      for k in parsed_tensors:
        if isinstance(parsed_tensors[k], tf.SparseTensor):
          if parsed_tensors[k].dtype == tf.string:
            parsed_tensors[k] = tf.sparse.to_dense(
                parsed_tensors[k], default_value='')
          else:
            parsed_tensors[k] = tf.sparse.to_dense(
                parsed_tensors[k], default_value=0)
  
      image = self._decode_image(parsed_tensors)
      boxes = self._decode_boxes(parsed_tensors)
      areas = self._decode_areas(parsed_tensors)
      is_crowds = tf.cond(
          tf.greater(tf.shape(parsed_tensors['image/object/is_crowd'])[0], 0),
          lambda: tf.cast(parsed_tensors['image/object/is_crowd'], dtype=tf.bool),
          lambda: tf.zeros_like(parsed_tensors['image/object/class/label'], dtype=tf.bool))  # pylint: disable=line-too-long
      if self._include_mask:
        masks = self._decode_masks(parsed_tensors)
  
      decoded_tensors = {
          'image': image,
          'source_id': parsed_tensors['image/source_id'],
          'height': parsed_tensors['image/height'],
          'width': parsed_tensors['image/width'],
          'groundtruth_classes': parsed_tensors['image/object/class/label'],
          'groundtruth_is_crowd': is_crowds,
          'groundtruth_area': areas,
          'groundtruth_boxes': boxes,
      }
      if self._include_mask:
        decoded_tensors.update({
            'groundtruth_instance_masks': masks,
            'groundtruth_instance_masks_png': parsed_tensors['image/object/mask'],
        })
      return decoded_tensors
   # Lint as: python2, python3
  # Copyright 2018 The TensorFlow Authors. All Rights Reserved.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  # ==============================================================================
  """Exports an SSD detection model to use with tf-lite.
  
  See export_tflite_ssd_graph.py for usage.
  """
  import os
  import tempfile
  import numpy as np
  import tensorflow.compat.v1 as tf
  from tensorflow.core.framework import attr_value_pb2
  from tensorflow.core.framework import types_pb2
  from tensorflow.core.protobuf import saver_pb2
  from object_detection import exporter
  from object_detection.builders import graph_rewriter_builder
  from object_detection.builders import model_builder
  from object_detection.builders import post_processing_builder
  from object_detection.core import box_list
  from object_detection.utils import tf_version
  
  _DEFAULT_NUM_CHANNELS = 3
  _DEFAULT_NUM_COORD_BOX = 4
  
  if tf_version.is_tf1():
    from tensorflow.tools.graph_transforms import TransformGraph  # pylint: disable=g-import-not-at-top
  
  
  def get_const_center_size_encoded_anchors(anchors):
    """Exports center-size encoded anchors as a constant tensor.
  
    Args:
      anchors: a float32 tensor of shape [num_anchors, 4] containing the anchor
        boxes
  
    Returns:
      encoded_anchors: a float32 constant tensor of shape [num_anchors, 4]
      containing the anchor boxes.
    """
    anchor_boxlist = box_list.BoxList(anchors)
    y, x, h, w = anchor_boxlist.get_center_coordinates_and_sizes()
    num_anchors = y.get_shape().as_list()
  
    with tf.Session() as sess:
      y_out, x_out, h_out, w_out = sess.run([y, x, h, w])
    encoded_anchors = tf.constant(
        np.transpose(np.stack((y_out, x_out, h_out, w_out))),
        dtype=tf.float32,
        shape=[num_anchors[0], _DEFAULT_NUM_COORD_BOX],
        name='anchors')
    return encoded_anchors
  
  
  def append_postprocessing_op(frozen_graph_def,
                               max_detections,
                               max_classes_per_detection,
                               nms_score_threshold,
                               nms_iou_threshold,
                               num_classes,
                               scale_values,
                               detections_per_class=100,
                               use_regular_nms=False,
                               additional_output_tensors=()):
    """Appends postprocessing custom op.
  
    Args:
      frozen_graph_def: Frozen GraphDef for SSD model after freezing the
        checkpoint
      max_detections: Maximum number of detections (boxes) to show
      max_classes_per_detection: Number of classes to display per detection
      nms_score_threshold: Score threshold used in Non-maximal suppression in
        post-processing
      nms_iou_threshold: Intersection-over-union threshold used in Non-maximal
        suppression in post-processing
      num_classes: number of classes in SSD detector
      scale_values: scale values is a dict with following key-value pairs
        {y_scale: 10, x_scale: 10, h_scale: 5, w_scale: 5} that are used in decode
          centersize boxes
      detections_per_class: In regular NonMaxSuppression, number of anchors used
        for NonMaxSuppression per class
      use_regular_nms: Flag to set postprocessing op to use Regular NMS instead of
        Fast NMS.
      additional_output_tensors: Array of additional tensor names to output.
        Tensors are appended after postprocessing output.
  
    Returns:
      transformed_graph_def: Frozen GraphDef with postprocessing custom op
      appended
      TFLite_Detection_PostProcess custom op node has four outputs:
      detection_boxes: a float32 tensor of shape [1, num_boxes, 4] with box
      locations
      detection_classes: a float32 tensor of shape [1, num_boxes]
      with class indices
      detection_scores: a float32 tensor of shape [1, num_boxes]
      with class scores
      num_boxes: a float32 tensor of size 1 containing the number of detected
      boxes
    """
    new_output = frozen_graph_def.node.add()
    new_output.op = 'TFLite_Detection_PostProcess'
    new_output.name = 'TFLite_Detection_PostProcess'
    new_output.attr['_output_quantized'].CopyFrom(
        attr_value_pb2.AttrValue(b=True))
    new_output.attr['_output_types'].list.type.extend([
        types_pb2.DT_FLOAT, types_pb2.DT_FLOAT, types_pb2.DT_FLOAT,
        types_pb2.DT_FLOAT
    ])
    new_output.attr['_support_output_type_float_in_quantized_op'].CopyFrom(
        attr_value_pb2.AttrValue(b=True))
    new_output.attr['max_detections'].CopyFrom(
        attr_value_pb2.AttrValue(i=max_detections))
    new_output.attr['max_classes_per_detection'].CopyFrom(
        attr_value_pb2.AttrValue(i=max_classes_per_detection))
    new_output.attr['nms_score_threshold'].CopyFrom(
        attr_value_pb2.AttrValue(f=nms_score_threshold.pop()))
    new_output.attr['nms_iou_threshold'].CopyFrom(
        attr_value_pb2.AttrValue(f=nms_iou_threshold.pop()))
    new_output.attr['num_classes'].CopyFrom(
        attr_value_pb2.AttrValue(i=num_classes))
  
    new_output.attr['y_scale'].CopyFrom(
        attr_value_pb2.AttrValue(f=scale_values['y_scale'].pop()))
    new_output.attr['x_scale'].CopyFrom(
        attr_value_pb2.AttrValue(f=scale_values['x_scale'].pop()))
    new_output.attr['h_scale'].CopyFrom(
        attr_value_pb2.AttrValue(f=scale_values['h_scale'].pop()))
    new_output.attr['w_scale'].CopyFrom(
        attr_value_pb2.AttrValue(f=scale_values['w_scale'].pop()))
    new_output.attr['detections_per_class'].CopyFrom(
        attr_value_pb2.AttrValue(i=detections_per_class))
    new_output.attr['use_regular_nms'].CopyFrom(
        attr_value_pb2.AttrValue(b=use_regular_nms))
  
    new_output.input.extend(
        ['raw_outputs/box_encodings', 'raw_outputs/class_predictions', 'anchors'])
    # Transform the graph to append new postprocessing op
    input_names = []
    output_names = ['TFLite_Detection_PostProcess'
                   ] + list(additional_output_tensors)
    transforms = ['strip_unused_nodes']
    transformed_graph_def = TransformGraph(frozen_graph_def, input_names,
                                           output_names, transforms)
    return transformed_graph_def
  
  
  def export_tflite_graph(pipeline_config,
                          trained_checkpoint_prefix,
                          output_dir,
                          add_postprocessing_op,
                          max_detections,
                          max_classes_per_detection,
                          detections_per_class=100,
                          use_regular_nms=False,
                          binary_graph_name='tflite_graph.pb',
                          txt_graph_name='tflite_graph.pbtxt',
                          additional_output_tensors=()):
    """Exports a tflite compatible graph and anchors for ssd detection model.
  
    Anchors are written to a tensor and tflite compatible graph
    is written to output_dir/tflite_graph.pb.
  
    Args:
      pipeline_config: a pipeline.proto object containing the configuration for
        SSD model to export.
      trained_checkpoint_prefix: a file prefix for the checkpoint containing the
        trained parameters of the SSD model.
      output_dir: A directory to write the tflite graph and anchor file to.
      add_postprocessing_op: If add_postprocessing_op is true: frozen graph adds a
        TFLite_Detection_PostProcess custom op
      max_detections: Maximum number of detections (boxes) to show
      max_classes_per_detection: Number of classes to display per detection
      detections_per_class: In regular NonMaxSuppression, number of anchors used
        for NonMaxSuppression per class
      use_regular_nms: Flag to set postprocessing op to use Regular NMS instead of
        Fast NMS.
      binary_graph_name: Name of the exported graph file in binary format.
      txt_graph_name: Name of the exported graph file in text format.
      additional_output_tensors: Array of additional tensor names to output.
        Additional tensors are appended to the end of output tensor list.
  
    Raises:
      ValueError: if the pipeline config contains models other than ssd or uses an
        fixed_shape_resizer and provides a shape as well.
    """
    tf.gfile.MakeDirs(output_dir)
    if pipeline_config.model.WhichOneof('model') != 'ssd':
      raise ValueError('Only ssd models are supported in tflite. '
                       'Found {} in config'.format(
                           pipeline_config.model.WhichOneof('model')))
  
    num_classes = pipeline_config.model.ssd.num_classes
    nms_score_threshold = {
        pipeline_config.model.ssd.post_processing.batch_non_max_suppression
        .score_threshold
    }
    nms_iou_threshold = {
        pipeline_config.model.ssd.post_processing.batch_non_max_suppression
        .iou_threshold
    }
    scale_values = {}
    scale_values['y_scale'] = {
        pipeline_config.model.ssd.box_coder.faster_rcnn_box_coder.y_scale
    }
    scale_values['x_scale'] = {
        pipeline_config.model.ssd.box_coder.faster_rcnn_box_coder.x_scale
    }
    scale_values['h_scale'] = {
        pipeline_config.model.ssd.box_coder.faster_rcnn_box_coder.height_scale
    }
    scale_values['w_scale'] = {
        pipeline_config.model.ssd.box_coder.faster_rcnn_box_coder.width_scale
    }
  
    image_resizer_config = pipeline_config.model.ssd.image_resizer
    image_resizer = image_resizer_config.WhichOneof('image_resizer_oneof')
    num_channels = _DEFAULT_NUM_CHANNELS
    if image_resizer == 'fixed_shape_resizer':
      height = image_resizer_config.fixed_shape_resizer.height
      width = image_resizer_config.fixed_shape_resizer.width
      if image_resizer_config.fixed_shape_resizer.convert_to_grayscale:
        num_channels = 1
      shape = [1, height, width, num_channels]
    else:
      raise ValueError(
          'Only fixed_shape_resizer'
          'is supported with tflite. Found {}'.format(
              image_resizer_config.WhichOneof('image_resizer_oneof')))
  
    image = tf.placeholder(
        tf.float32, shape=shape, name='normalized_input_image_tensor')
  
    detection_model = model_builder.build(
        pipeline_config.model, is_training=False)
    predicted_tensors = detection_model.predict(image, true_image_shapes=None)
    # The score conversion occurs before the post-processing custom op
    _, score_conversion_fn = post_processing_builder.build(
        pipeline_config.model.ssd.post_processing)
    class_predictions = score_conversion_fn(
        predicted_tensors['class_predictions_with_background'])
  
    with tf.name_scope('raw_outputs'):
      # 'raw_outputs/box_encodings': a float32 tensor of shape [1, num_anchors, 4]
      #  containing the encoded box predictions. Note that these are raw
      #  predictions and no Non-Max suppression is applied on them and
      #  no decode center size boxes is applied to them.
      tf.identity(predicted_tensors['box_encodings'], name='box_encodings')
      # 'raw_outputs/class_predictions': a float32 tensor of shape
      #  [1, num_anchors, num_classes] containing the class scores for each anchor
      #  after applying score conversion.
      tf.identity(class_predictions, name='class_predictions')
    # 'anchors': a float32 tensor of shape
    #   [4, num_anchors] containing the anchors as a constant node.
    tf.identity(
        get_const_center_size_encoded_anchors(predicted_tensors['anchors']),
        name='anchors')
  
    # Add global step to the graph, so we know the training step number when we
    # evaluate the model.
    tf.train.get_or_create_global_step()
  
    # graph rewriter
    is_quantized = pipeline_config.HasField('graph_rewriter')
    if is_quantized:
      graph_rewriter_config = pipeline_config.graph_rewriter
      graph_rewriter_fn = graph_rewriter_builder.build(
          graph_rewriter_config, is_training=False)
      graph_rewriter_fn()
  
    if pipeline_config.model.ssd.feature_extractor.HasField('fpn'):
      exporter.rewrite_nn_resize_op(is_quantized)
  
    # freeze the graph
    saver_kwargs = {}
    if pipeline_config.eval_config.use_moving_averages:
      saver_kwargs['write_version'] = saver_pb2.SaverDef.V1
      moving_average_checkpoint = tempfile.NamedTemporaryFile()
      exporter.replace_variable_values_with_moving_averages(
          tf.get_default_graph(), trained_checkpoint_prefix,
          moving_average_checkpoint.name)
      checkpoint_to_use = moving_average_checkpoint.name
    else:
      checkpoint_to_use = trained_checkpoint_prefix
  
    saver = tf.train.Saver(**saver_kwargs)
    input_saver_def = saver.as_saver_def()
    frozen_graph_def = exporter.freeze_graph_with_def_protos(
        input_graph_def=tf.get_default_graph().as_graph_def(),
        input_saver_def=input_saver_def,
        input_checkpoint=checkpoint_to_use,
        output_node_names=','.join([
            'raw_outputs/box_encodings', 'raw_outputs/class_predictions',
            'anchors'
        ] + list(additional_output_tensors)),
        restore_op_name='save/restore_all',
        filename_tensor_name='save/Const:0',
        clear_devices=True,
        output_graph='',
        initializer_nodes='')
  
    # Add new operation to do post processing in a custom op (TF Lite only)
    if add_postprocessing_op:
      transformed_graph_def = append_postprocessing_op(
          frozen_graph_def,
          max_detections,
          max_classes_per_detection,
          nms_score_threshold,
          nms_iou_threshold,
          num_classes,
          scale_values,
          detections_per_class,
          use_regular_nms,
          additional_output_tensors=additional_output_tensors)
    else:
      # Return frozen without adding post-processing custom op
      transformed_graph_def = frozen_graph_def
  
    binary_graph = os.path.join(output_dir, binary_graph_name)
    with tf.gfile.GFile(binary_graph, 'wb') as f:
      f.write(transformed_graph_def.SerializeToString())
    txt_graph = os.path.join(output_dir, txt_graph_name)
    with tf.gfile.GFile(txt_graph, 'w') as f:
      f.write(str(transformed_graph_def))
   # Copyright 2018 The TensorFlow Authors. All Rights Reserved.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  # ==============================================================================
  """Contains the definition for the PNASNet classification networks.
  
  Paper: https://arxiv.org/abs/1712.00559
  """
  
  from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  
  import copy
  import tensorflow.compat.v1 as tf
  import tf_slim as slim
  from tensorflow.contrib import training as contrib_training
  
  from nets.nasnet import nasnet
  from nets.nasnet import nasnet_utils
  
  arg_scope = slim.arg_scope
  
  
  def large_imagenet_config():
    """Large ImageNet configuration based on PNASNet-5."""
    return contrib_training.HParams(
        stem_multiplier=3.0,
        dense_dropout_keep_prob=0.5,
        num_cells=12,
        filter_scaling_rate=2.0,
        num_conv_filters=216,
        drop_path_keep_prob=0.6,
        use_aux_head=1,
        num_reduction_layers=2,
        data_format='NHWC',
        skip_reduction_layer_input=1,
        total_training_steps=250000,
        use_bounded_activation=False,
    )
  
  
  def mobile_imagenet_config():
    """Mobile ImageNet configuration based on PNASNet-5."""
    return contrib_training.HParams(
        stem_multiplier=1.0,
        dense_dropout_keep_prob=0.5,
        num_cells=9,
        filter_scaling_rate=2.0,
        num_conv_filters=54,
        drop_path_keep_prob=1.0,
        use_aux_head=1,
        num_reduction_layers=2,
        data_format='NHWC',
        skip_reduction_layer_input=1,
        total_training_steps=250000,
        use_bounded_activation=False,
    )
  
  
  def pnasnet_large_arg_scope(weight_decay=4e-5, batch_norm_decay=0.9997,
                              batch_norm_epsilon=0.001):
    """Default arg scope for the PNASNet Large ImageNet model."""
    return nasnet.nasnet_large_arg_scope(
        weight_decay, batch_norm_decay, batch_norm_epsilon)
  
  
  def pnasnet_mobile_arg_scope(weight_decay=4e-5,
                               batch_norm_decay=0.9997,
                               batch_norm_epsilon=0.001):
    """Default arg scope for the PNASNet Mobile ImageNet model."""
    return nasnet.nasnet_mobile_arg_scope(weight_decay, batch_norm_decay,
                                          batch_norm_epsilon)
  
  
  def _build_pnasnet_base(images,
                          normal_cell,
                          num_classes,
                          hparams,
                          is_training,
                          final_endpoint=None):
    """Constructs a PNASNet image model."""
  
    end_points = {}
  
    def add_and_check_endpoint(endpoint_name, net):
      end_points[endpoint_name] = net
      return final_endpoint and (endpoint_name == final_endpoint)
  
    # Find where to place the reduction cells or stride normal cells
    reduction_indices = nasnet_utils.calc_reduction_layers(
        hparams.num_cells, hparams.num_reduction_layers)
  
    # pylint: disable=protected-access
    stem = lambda: nasnet._imagenet_stem(images, hparams, normal_cell)
    # pylint: enable=protected-access
    net, cell_outputs = stem()
    if add_and_check_endpoint('Stem', net):
      return net, end_points
  
    # Setup for building in the auxiliary head.
    aux_head_cell_idxes = []
    if len(reduction_indices) >= 2:
      aux_head_cell_idxes.append(reduction_indices[1] - 1)
  
    # Run the cells
    filter_scaling = 1.0
    # true_cell_num accounts for the stem cells
    true_cell_num = 2
    activation_fn = tf.nn.relu6 if hparams.use_bounded_activation else tf.nn.relu
    for cell_num in range(hparams.num_cells):
      is_reduction = cell_num in reduction_indices
      stride = 2 if is_reduction else 1
      if is_reduction: filter_scaling *= hparams.filter_scaling_rate
      if hparams.skip_reduction_layer_input or not is_reduction:
        prev_layer = cell_outputs[-2]
      net = normal_cell(
          net,
          scope='cell_{}'.format(cell_num),
          filter_scaling=filter_scaling,
          stride=stride,
          prev_layer=prev_layer,
          cell_num=true_cell_num)
      if add_and_check_endpoint('Cell_{}'.format(cell_num), net):
        return net, end_points
      true_cell_num += 1
      cell_outputs.append(net)
  
      if (hparams.use_aux_head and cell_num in aux_head_cell_idxes and
          num_classes and is_training):
        aux_net = activation_fn(net)
        # pylint: disable=protected-access
        nasnet._build_aux_head(aux_net, end_points, num_classes, hparams,
                               scope='aux_{}'.format(cell_num))
        # pylint: enable=protected-access
  
    # Final softmax layer
    with tf.variable_scope('final_layer'):
      net = activation_fn(net)
      net = nasnet_utils.global_avg_pool(net)
      if add_and_check_endpoint('global_pool', net) or not num_classes:
        return net, end_points
      net = slim.dropout(net, hparams.dense_dropout_keep_prob, scope='dropout')
      logits = slim.fully_connected(net, num_classes)
  
      if add_and_check_endpoint('Logits', logits):
        return net, end_points
  
      predictions = tf.nn.softmax(logits, name='predictions')
      if add_and_check_endpoint('Predictions', predictions):
        return net, end_points
    return logits, end_points
  
  
  def build_pnasnet_large(images,
                          num_classes,
                          is_training=True,
                          final_endpoint=None,
                          config=None):
    """Build PNASNet Large model for the ImageNet Dataset."""
    hparams = copy.deepcopy(config) if config else large_imagenet_config()
    # pylint: disable=protected-access
    nasnet._update_hparams(hparams, is_training)
    # pylint: enable=protected-access
  
    if tf.test.is_gpu_available() and hparams.data_format == 'NHWC':
      tf.logging.info(
          'A GPU is available on the machine, consider using NCHW '
          'data format for increased speed on GPU.')
  
    if hparams.data_format == 'NCHW':
      images = tf.transpose(a=images, perm=[0, 3, 1, 2])
  
    # Calculate the total number of cells in the network.
    # There is no distinction between reduction and normal cells in PNAS so the
    # total number of cells is equal to the number normal cells plus the number
    # of stem cells (two by default).
    total_num_cells = hparams.num_cells + 2
  
    normal_cell = PNasNetNormalCell(hparams.num_conv_filters,
                                    hparams.drop_path_keep_prob, total_num_cells,
                                    hparams.total_training_steps,
                                    hparams.use_bounded_activation)
    with arg_scope(
        [slim.dropout, nasnet_utils.drop_path, slim.batch_norm],
        is_training=is_training):
      with arg_scope([slim.avg_pool2d, slim.max_pool2d, slim.conv2d,
                      slim.batch_norm, slim.separable_conv2d,
                      nasnet_utils.factorized_reduction,
                      nasnet_utils.global_avg_pool,
                      nasnet_utils.get_channel_index,
                      nasnet_utils.get_channel_dim],
                     data_format=hparams.data_format):
        return _build_pnasnet_base(
            images,
            normal_cell=normal_cell,
            num_classes=num_classes,
            hparams=hparams,
            is_training=is_training,
            final_endpoint=final_endpoint)
  build_pnasnet_large.default_image_size = 331
  
  
  def build_pnasnet_mobile(images,
                           num_classes,
                           is_training=True,
                           final_endpoint=None,
                           config=None):
    """Build PNASNet Mobile model for the ImageNet Dataset."""
    hparams = copy.deepcopy(config) if config else mobile_imagenet_config()
    # pylint: disable=protected-access
    nasnet._update_hparams(hparams, is_training)
    # pylint: enable=protected-access
  
    if tf.test.is_gpu_available() and hparams.data_format == 'NHWC':
      tf.logging.info(
          'A GPU is available on the machine, consider using NCHW '
          'data format for increased speed on GPU.')
  
    if hparams.data_format == 'NCHW':
      images = tf.transpose(a=images, perm=[0, 3, 1, 2])
  
    # Calculate the total number of cells in the network.
    # There is no distinction between reduction and normal cells in PNAS so the
    # total number of cells is equal to the number normal cells plus the number
    # of stem cells (two by default).
    total_num_cells = hparams.num_cells + 2
  
    normal_cell = PNasNetNormalCell(hparams.num_conv_filters,
                                    hparams.drop_path_keep_prob, total_num_cells,
                                    hparams.total_training_steps,
                                    hparams.use_bounded_activation)
    with arg_scope(
        [slim.dropout, nasnet_utils.drop_path, slim.batch_norm],
        is_training=is_training):
      with arg_scope(
          [
              slim.avg_pool2d, slim.max_pool2d, slim.conv2d, slim.batch_norm,
              slim.separable_conv2d, nasnet_utils.factorized_reduction,
              nasnet_utils.global_avg_pool, nasnet_utils.get_channel_index,
              nasnet_utils.get_channel_dim
          ],
          data_format=hparams.data_format):
        return _build_pnasnet_base(
            images,
            normal_cell=normal_cell,
            num_classes=num_classes,
            hparams=hparams,
            is_training=is_training,
            final_endpoint=final_endpoint)
  
  
  build_pnasnet_mobile.default_image_size = 224
  
  
  class PNasNetNormalCell(nasnet_utils.NasNetABaseCell):
    """PNASNet Normal Cell."""
  
    def __init__(self, num_conv_filters, drop_path_keep_prob, total_num_cells,
                 total_training_steps, use_bounded_activation=False):
      # Configuration for the PNASNet-5 model.
      operations = [
          'separable_5x5_2', 'max_pool_3x3', 'separable_7x7_2', 'max_pool_3x3',
          'separable_5x5_2', 'separable_3x3_2', 'separable_3x3_2', 'max_pool_3x3',
          'separable_3x3_2', 'none'
      ]
      used_hiddenstates = [1, 1, 0, 0, 0, 0, 0]
      hiddenstate_indices = [1, 1, 0, 0, 0, 0, 4, 0, 1, 0]
  
      super(PNasNetNormalCell, self).__init__(
          num_conv_filters, operations, used_hiddenstates, hiddenstate_indices,
          drop_path_keep_prob, total_num_cells, total_training_steps,
          use_bounded_activation)
  
apis: tensorflow.summary.scalar tensorflow.summary.create_file_writer tensorflow.io.gfile.GFile
apis: tensorflow.size tensorflow.io.parse_single_example tensorflow.zeros tensorflow.stack tensorflow.shape tensorflow.sparse.to_dense tensorflow.map_fn tensorflow.io.decode_png tensorflow.io.decode_image tensorflow.zeros_like tensorflow.cast tensorflow.io.FixedLenFeature tensorflow.io.VarLenFeature
apis: tensorflow.compat.v1.placeholder tensorflow.compat.v1.train.Saver tensorflow.compat.v1.Session tensorflow.tools.graph_transforms.TransformGraph tensorflow.compat.v1.identity tensorflow.core.framework.attr_value_pb2.AttrValue tensorflow.compat.v1.gfile.GFile numpy.stack tensorflow.compat.v1.get_default_graph tensorflow.compat.v1.train.get_or_create_global_step tensorflow.compat.v1.gfile.MakeDirs tensorflow.compat.v1.name_scope
apis: tensorflow.compat.v1.test.is_gpu_available tensorflow.compat.v1.transpose tensorflow.compat.v1.nn.softmax tensorflow.compat.v1.variable_scope tensorflow.contrib.training.HParams tensorflow.compat.v1.logging.info