def export_inference_graph(input_type,
                           pipeline_config,
                           trained_checkpoint_prefix,
                           output_directory,
                           input_shape=None,
                           optimize_graph=True,
                           output_collection_name='inference_op',
                           additional_output_tensor_names=None):
  """Exports inference graph for the model specified in the pipeline config.
  Args:
    input_type: Type of input for the graph. Can be one of [`image_tensor`,
      `tf_example`].
    pipeline_config: pipeline_pb2.TrainAndEvalPipelineConfig proto.
    trained_checkpoint_prefix: Path to the trained checkpoint file.
    output_directory: Path to write outputs.
    input_shape: Sets a fixed shape for an `image_tensor` input. If not
      specified, will default to [None, None, None, 3].
    optimize_graph: Whether to optimize graph using Grappler.
    output_collection_name: Name of collection to add output tensors to.
      If None, does not add output tensors to a collection.
    additional_output_tensor_names: list of additional output
    tensors to include in the frozen graph.
  """
  detection_model = model_builder.build(pipeline_config.model,
                                        is_training=False)
  _export_inference_graph(input_type, detection_model,
                          pipeline_config.eval_config.use_moving_averages,
                          trained_checkpoint_prefix,
                          output_directory, additional_output_tensor_names,
                          input_shape, optimize_graph, output_collection_name)
Exemple #2
0
def export_inference_graph(input_type,
                           pipeline_config,
                           trained_checkpoint_prefix,
                           output_directory,
                           input_shape=None,
                           output_collection_name='inference_op',
                           additional_output_tensor_names=None):
  """Exports inference graph for the model specified in the pipeline config.

  Args:
    input_type: Type of input for the graph. Can be one of [`image_tensor`,
      `tf_example`].
    pipeline_config: pipeline_pb2.TrainAndEvalPipelineConfig proto.
    trained_checkpoint_prefix: Path to the trained checkpoint file.
    output_directory: Path to write outputs.
    input_shape: Sets a fixed shape for an `image_tensor` input. If not
      specified, will default to [None, None, None, 3].
    output_collection_name: Name of collection to add output tensors to.
      If None, does not add output tensors to a collection.
    additional_output_tensor_names: list of additional output
      tensors to include in the frozen graph.
  """
  detection_model = model_builder.build(pipeline_config.model,
                                        is_training=False)
  _export_inference_graph(input_type, detection_model,
                          pipeline_config.eval_config.use_moving_averages,
                          trained_checkpoint_prefix,
                          output_directory, additional_output_tensor_names,
                          input_shape, output_collection_name,
                          graph_hook_fn=None)
  pipeline_config.eval_config.use_moving_averages = False
  config_text = text_format.MessageToString(pipeline_config)
  with tf.gfile.Open(
      os.path.join(output_directory, 'pipeline.config'), 'wb') as f:
    f.write(config_text)
Exemple #3
0
  def test_write_graph_and_checkpoint(self):
    tmp_dir = self.get_temp_dir()
    trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt')
    self._save_checkpoint_from_mock_model(trained_checkpoint_prefix,
                                          use_moving_averages=False)
    output_directory = os.path.join(tmp_dir, 'output')
    model_path = os.path.join(output_directory, 'model.ckpt')
    meta_graph_path = model_path + '.meta'
    tf.gfile.MakeDirs(output_directory)
    with mock.patch.object(
        model_builder, 'build', autospec=True) as mock_builder:
      mock_builder.return_value = FakeModel(
          add_detection_keypoints=True, add_detection_masks=True)
      pipeline_config = pipeline_pb2.TrainEvalPipelineConfig()
      pipeline_config.eval_config.use_moving_averages = False
      detection_model = model_builder.build(pipeline_config.model,
                                            is_training=False)
      exporter._build_detection_graph(
          input_type='tf_example',
          detection_model=detection_model,
          input_shape=None,
          output_collection_name='inference_op',
          graph_hook_fn=None)
      saver = tf.train.Saver()
      input_saver_def = saver.as_saver_def()
      exporter.write_graph_and_checkpoint(
          inference_graph_def=tf.get_default_graph().as_graph_def(),
          model_path=model_path,
          input_saver_def=input_saver_def,
          trained_checkpoint_prefix=trained_checkpoint_prefix)

    tf_example_np = np.hstack([self._create_tf_example(
        np.ones((4, 4, 3)).astype(np.uint8))] * 2)
    with tf.Graph().as_default() as od_graph:
      with self.test_session(graph=od_graph) as sess:
        new_saver = tf.train.import_meta_graph(meta_graph_path)
        new_saver.restore(sess, model_path)

        tf_example = od_graph.get_tensor_by_name('tf_example:0')
        boxes = od_graph.get_tensor_by_name('detection_boxes:0')
        scores = od_graph.get_tensor_by_name('detection_scores:0')
        classes = od_graph.get_tensor_by_name('detection_classes:0')
        keypoints = od_graph.get_tensor_by_name('detection_keypoints:0')
        masks = od_graph.get_tensor_by_name('detection_masks:0')
        num_detections = od_graph.get_tensor_by_name('num_detections:0')
        (boxes_np, scores_np, classes_np, keypoints_np, masks_np,
         num_detections_np) = sess.run(
             [boxes, scores, classes, keypoints, masks, num_detections],
             feed_dict={tf_example: tf_example_np})
        self.assertAllClose(boxes_np, [[[0.0, 0.0, 0.5, 0.5],
                                        [0.5, 0.5, 0.8, 0.8]],
                                       [[0.5, 0.5, 1.0, 1.0],
                                        [0.0, 0.0, 0.0, 0.0]]])
        self.assertAllClose(scores_np, [[0.7, 0.6],
                                        [0.9, 0.0]])
        self.assertAllClose(classes_np, [[1, 2],
                                         [2, 1]])
        self.assertAllClose(keypoints_np, np.arange(48).reshape([2, 2, 6, 2]))
        self.assertAllClose(masks_np, np.arange(64).reshape([2, 2, 4, 4]))
        self.assertAllClose(num_detections_np, [2, 1])
Exemple #4
0
    def transform_and_pad_input_data_fn(tensor_dict):
      """Combines transform and pad operation."""
      data_augmentation_options = [
          preprocessor_builder.build(step)
          for step in train_config.data_augmentation_options
      ]
      data_augmentation_fn = functools.partial(
          augment_input_data,
          data_augmentation_options=data_augmentation_options)
      model = model_builder.build(model_config, is_training=True)
      image_resizer_config = config_util.get_image_resizer_config(model_config)
      image_resizer_fn = image_resizer_builder.build(image_resizer_config)
      transform_data_fn = functools.partial(
          transform_input_data, model_preprocess_fn=model.preprocess,
          image_resizer_fn=image_resizer_fn,
          num_classes=config_util.get_number_of_classes(model_config),
          data_augmentation_fn=data_augmentation_fn,
          merge_multiple_boxes=train_config.merge_multiple_label_boxes,
          retain_original_image=train_config.retain_original_images,
          use_bfloat16=train_config.use_bfloat16)

      tensor_dict = pad_input_data_to_static_shapes(
          tensor_dict=transform_data_fn(tensor_dict),
          max_num_boxes=train_input_config.max_number_of_boxes,
          num_classes=config_util.get_number_of_classes(model_config),
          spatial_image_shape=config_util.get_spatial_image_size(
              image_resizer_config))
      return (_get_features_dict(tensor_dict), _get_labels_dict(tensor_dict))
Exemple #5
0
  def _predict_input_fn(params=None):
    """Decodes serialized tf.Examples and returns `ServingInputReceiver`.

    Args:
      params: Parameter dictionary passed from the estimator.

    Returns:
      `ServingInputReceiver`.
    """
    del params
    example = tf.placeholder(dtype=tf.string, shape=[], name='input_feature')

    num_classes = config_util.get_number_of_classes(model_config)
    model = model_builder.build(model_config, is_training=False)
    image_resizer_config = config_util.get_image_resizer_config(model_config)
    image_resizer_fn = image_resizer_builder.build(image_resizer_config)

    transform_fn = functools.partial(
        transform_input_data, model_preprocess_fn=model.preprocess,
        image_resizer_fn=image_resizer_fn,
        num_classes=num_classes,
        data_augmentation_fn=None)

    decoder = tf_example_decoder.TfExampleDecoder(load_instance_masks=False)
    input_dict = transform_fn(decoder.decode(example))
    images = tf.to_float(input_dict[fields.InputDataFields.image])
    images = tf.expand_dims(images, axis=0)

    return tf.estimator.export.ServingInputReceiver(
        features={fields.InputDataFields.image: images},
        receiver_tensors={SERVING_FED_EXAMPLE_KEY: example})
Exemple #6
0
  def test_write_frozen_graph(self):
    tmp_dir = self.get_temp_dir()
    trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt')
    self._save_checkpoint_from_mock_model(trained_checkpoint_prefix,
                                          use_moving_averages=True)
    output_directory = os.path.join(tmp_dir, 'output')
    inference_graph_path = os.path.join(output_directory,
                                        'frozen_inference_graph.pb')
    tf.gfile.MakeDirs(output_directory)
    with mock.patch.object(
        model_builder, 'build', autospec=True) as mock_builder:
      mock_builder.return_value = FakeModel(add_detection_masks=True)
      pipeline_config = pipeline_pb2.TrainEvalPipelineConfig()
      pipeline_config.eval_config.use_moving_averages = False
      detection_model = model_builder.build(pipeline_config.model,
                                            is_training=False)
      outputs, _ = exporter._build_detection_graph(
          input_type='tf_example',
          detection_model=detection_model,
          input_shape=None,
          output_collection_name='inference_op',
          graph_hook_fn=None)
      output_node_names = ','.join(outputs.keys())
      saver = tf.train.Saver()
      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=trained_checkpoint_prefix,
          output_node_names=output_node_names,
          restore_op_name='save/restore_all',
          filename_tensor_name='save/Const:0',
          clear_devices=True,
          initializer_nodes='')
      exporter.write_frozen_graph(inference_graph_path, frozen_graph_def)

    inference_graph = self._load_inference_graph(inference_graph_path)
    tf_example_np = np.expand_dims(self._create_tf_example(
        np.ones((4, 4, 3)).astype(np.uint8)), axis=0)
    with self.test_session(graph=inference_graph) as sess:
      tf_example = inference_graph.get_tensor_by_name('tf_example:0')
      boxes = inference_graph.get_tensor_by_name('detection_boxes:0')
      scores = inference_graph.get_tensor_by_name('detection_scores:0')
      classes = inference_graph.get_tensor_by_name('detection_classes:0')
      masks = inference_graph.get_tensor_by_name('detection_masks:0')
      num_detections = inference_graph.get_tensor_by_name('num_detections:0')
      (boxes_np, scores_np, classes_np, masks_np, num_detections_np) = sess.run(
          [boxes, scores, classes, masks, num_detections],
          feed_dict={tf_example: tf_example_np})
      self.assertAllClose(boxes_np, [[[0.0, 0.0, 0.5, 0.5],
                                      [0.5, 0.5, 0.8, 0.8]],
                                     [[0.5, 0.5, 1.0, 1.0],
                                      [0.0, 0.0, 0.0, 0.0]]])
      self.assertAllClose(scores_np, [[0.7, 0.6],
                                      [0.9, 0.0]])
      self.assertAllClose(classes_np, [[1, 2],
                                       [2, 1]])
      self.assertAllClose(masks_np, np.arange(64).reshape([2, 2, 4, 4]))
      self.assertAllClose(num_detections_np, [2, 1])
Exemple #7
0
 def test_create_faster_rcnn_model_from_config_with_example_miner(self):
   model_text_proto = """
     faster_rcnn {
       num_classes: 3
       feature_extractor {
         type: 'faster_rcnn_inception_resnet_v2'
       }
       image_resizer {
         keep_aspect_ratio_resizer {
           min_dimension: 600
           max_dimension: 1024
         }
       }
       first_stage_anchor_generator {
         grid_anchor_generator {
           scales: [0.25, 0.5, 1.0, 2.0]
           aspect_ratios: [0.5, 1.0, 2.0]
           height_stride: 16
           width_stride: 16
         }
       }
       first_stage_box_predictor_conv_hyperparams {
         regularizer {
           l2_regularizer {
           }
         }
         initializer {
           truncated_normal_initializer {
           }
         }
       }
       second_stage_box_predictor {
         mask_rcnn_box_predictor {
           fc_hyperparams {
             op: FC
             regularizer {
               l2_regularizer {
               }
             }
             initializer {
               truncated_normal_initializer {
               }
             }
           }
         }
       }
       hard_example_miner {
         num_hard_examples: 10
         iou_threshold: 0.99
       }
     }"""
   model_proto = model_pb2.DetectionModel()
   text_format.Merge(model_text_proto, model_proto)
   model = model_builder.build(model_proto, is_training=True)
   self.assertIsNotNone(model._hard_example_miner)
Exemple #8
0
  def create_model(self, model_config):
    """Builds a DetectionModel based on the model config.

    Args:
      model_config: A model.proto object containing the config for the desired
        DetectionModel.

    Returns:
      DetectionModel based on the config.
    """
    return model_builder.build(model_config, is_training=True)
def export_inference_graph(input_type, pipeline_config, checkpoint_path,
                           inference_graph_path):
  """Exports inference graph for the model specified in the pipeline config.

  Args:
    input_type: Type of input for the graph. Can be one of [`image_tensor`,
      `tf_example`].
    pipeline_config: pipeline_pb2.TrainAndEvalPipelineConfig proto.
    checkpoint_path: Path to the checkpoint file to freeze.
    inference_graph_path: Path to write inference graph to.
  """
  detection_model = model_builder.build(pipeline_config.model,
                                        is_training=False)
  _export_inference_graph(input_type, detection_model,
                          pipeline_config.eval_config.use_moving_averages,
                          checkpoint_path, inference_graph_path)
Exemple #10
0
def export_inference_graph(input_type,
                           pipeline_config,
                           trained_checkpoint_prefix,
                           output_directory,
                           input_shape=None,
                           output_collection_name='inference_op',
                           additional_output_tensor_names=None,
                           write_inference_graph=False):
  """Exports inference graph for the model specified in the pipeline config.

  Args:
    input_type: Type of input for the graph. Can be one of ['image_tensor',
      'encoded_image_string_tensor', 'tf_example'].
    pipeline_config: pipeline_pb2.TrainAndEvalPipelineConfig proto.
    trained_checkpoint_prefix: Path to the trained checkpoint file.
    output_directory: Path to write outputs.
    input_shape: Sets a fixed shape for an `image_tensor` input. If not
      specified, will default to [None, None, None, 3].
    output_collection_name: Name of collection to add output tensors to.
      If None, does not add output tensors to a collection.
    additional_output_tensor_names: list of additional output
      tensors to include in the frozen graph.
    write_inference_graph: If true, writes inference graph to disk.
  """
  detection_model = model_builder.build(pipeline_config.model,
                                        is_training=False)
  graph_rewriter_fn = None
  if pipeline_config.HasField('graph_rewriter'):
    graph_rewriter_config = pipeline_config.graph_rewriter
    graph_rewriter_fn = graph_rewriter_builder.build(graph_rewriter_config,
                                                     is_training=False)
  _export_inference_graph(
      input_type,
      detection_model,
      pipeline_config.eval_config.use_moving_averages,
      trained_checkpoint_prefix,
      output_directory,
      additional_output_tensor_names,
      input_shape,
      output_collection_name,
      graph_hook_fn=graph_rewriter_fn,
      write_inference_graph=write_inference_graph)
  pipeline_config.eval_config.use_moving_averages = False
  config_util.save_pipeline_config(pipeline_config, output_directory)
Exemple #11
0
    def transform_and_pad_input_data_fn(tensor_dict):
      """Combines transform and pad operation."""
      num_classes = config_util.get_number_of_classes(model_config)
      model = model_builder.build(model_config, is_training=False)
      image_resizer_config = config_util.get_image_resizer_config(model_config)
      image_resizer_fn = image_resizer_builder.build(image_resizer_config)

      transform_data_fn = functools.partial(
          transform_input_data, model_preprocess_fn=model.preprocess,
          image_resizer_fn=image_resizer_fn,
          num_classes=num_classes,
          data_augmentation_fn=None,
          retain_original_image=eval_config.retain_original_images)
      tensor_dict = pad_input_data_to_static_shapes(
          tensor_dict=transform_data_fn(tensor_dict),
          max_num_boxes=eval_input_config.max_number_of_boxes,
          num_classes=config_util.get_number_of_classes(model_config),
          spatial_image_shape=config_util.get_spatial_image_size(
              image_resizer_config))
      return (_get_features_dict(tensor_dict), _get_labels_dict(tensor_dict))
def export_inference_graph(input_type,
                           pipeline_config,
                           trained_checkpoint_prefix,
                           output_directory,
                           optimize_graph=False,
                           output_collection_name='inference_op'):
  """Exports inference graph for the model specified in the pipeline config.

  Args:
    input_type: Type of input for the graph. Can be one of [`image_tensor`,
      `tf_example`].
    pipeline_config: pipeline_pb2.TrainAndEvalPipelineConfig proto.
    trained_checkpoint_prefix: Path to the trained checkpoint file.
    output_directory: Path to write outputs.
    optimize_graph: Whether to optimize graph using Grappler.
    output_collection_name: Name of collection to add output tensors to.
      If None, does not add output tensors to a collection.
  """
  detection_model = model_builder.build(pipeline_config.model,
                                        is_training=False)
  _export_inference_graph(input_type, detection_model,
                          pipeline_config.eval_config.use_moving_averages,
                          trained_checkpoint_prefix, output_directory,
                          optimize_graph, output_collection_name)
Exemple #13
0
  def test_create_ssd_resnet_v1_fpn_model_from_config(self):
    model_text_proto = """
      ssd {
        feature_extractor {
          type: 'ssd_resnet50_v1_fpn'
          conv_hyperparams {
            regularizer {
                l2_regularizer {
                }
              }
              initializer {
                truncated_normal_initializer {
                }
              }
          }
          batch_norm_trainable: true
        }
        box_coder {
          faster_rcnn_box_coder {
          }
        }
        matcher {
          argmax_matcher {
          }
        }
        similarity_calculator {
          iou_similarity {
          }
        }
        encode_background_as_zeros: true
        anchor_generator {
          multiscale_anchor_generator {
            aspect_ratios: [1.0, 2.0, 0.5]
            scales_per_octave: 2
          }
        }
        image_resizer {
          fixed_shape_resizer {
            height: 320
            width: 320
          }
        }
        box_predictor {
          weight_shared_convolutional_box_predictor {
            depth: 32
            conv_hyperparams {
              regularizer {
                l2_regularizer {
                }
              }
              initializer {
                random_normal_initializer {
                }
              }
            }
            num_layers_before_predictor: 1
          }
        }
        normalize_loss_by_num_matches: true
        normalize_loc_loss_by_codesize: true
        loss {
          classification_loss {
            weighted_sigmoid_focal {
              alpha: 0.25
              gamma: 2.0
            }
          }
          localization_loss {
            weighted_smooth_l1 {
              delta: 0.1
            }
          }
          classification_weight: 1.0
          localization_weight: 1.0
        }
      }"""
    model_proto = model_pb2.DetectionModel()
    text_format.Merge(model_text_proto, model_proto)

    for extractor_type, extractor_class in SSD_RESNET_V1_FPN_FEAT_MAPS.items():
      model_proto.ssd.feature_extractor.type = extractor_type
      model = model_builder.build(model_proto, is_training=True)
      self.assertIsInstance(model, ssd_meta_arch.SSDMetaArch)
      self.assertIsInstance(model._feature_extractor, extractor_class)
Exemple #14
0
    def test_create_ssd_resnet_v1_fpn_model_from_config(self):
        model_text_proto = """
      ssd {
        feature_extractor {
          type: 'ssd_resnet50_v1_fpn'
          conv_hyperparams {
            regularizer {
                l2_regularizer {
                }
              }
              initializer {
                truncated_normal_initializer {
                }
              }
          }
        }
        box_coder {
          faster_rcnn_box_coder {
          }
        }
        matcher {
          argmax_matcher {
          }
        }
        similarity_calculator {
          iou_similarity {
          }
        }
        encode_background_as_zeros: true
        anchor_generator {
          multiscale_anchor_generator {
            aspect_ratios: [1.0, 2.0, 0.5]
            scales_per_octave: 2
          }
        }
        image_resizer {
          fixed_shape_resizer {
            height: 320
            width: 320
          }
        }
        box_predictor {
          weight_shared_convolutional_box_predictor {
            depth: 32
            conv_hyperparams {
              regularizer {
                l2_regularizer {
                }
              }
              initializer {
                random_normal_initializer {
                }
              }
            }
            num_layers_before_predictor: 1
          }
        }
        normalize_loss_by_num_matches: true
        normalize_loc_loss_by_codesize: true
        loss {
          classification_loss {
            weighted_sigmoid_focal {
              alpha: 0.25
              gamma: 2.0
            }
          }
          localization_loss {
            weighted_smooth_l1 {
              delta: 0.1
            }
          }
          classification_weight: 1.0
          localization_weight: 1.0
        }
      }"""
        model_proto = model_pb2.DetectionModel()
        text_format.Merge(model_text_proto, model_proto)

        for extractor_type, extractor_class in SSD_RESNET_V1_FPN_FEAT_MAPS.items(
        ):
            model_proto.ssd.feature_extractor.type = extractor_type
            model = model_builder.build(model_proto, is_training=True)
            self.assertIsInstance(model, ssd_meta_arch.SSDMetaArch)
            self.assertIsInstance(model._feature_extractor, extractor_class)
Exemple #15
0
  def _eval_input_fn(params=None):
    """Returns `features` and `labels` tensor dictionaries for evaluation.

    Args:
      params: Parameter dictionary passed from the estimator.

    Returns:
      features: Dictionary of feature tensors.
        features[fields.InputDataFields.image] is a [1, H, W, C] float32 tensor
          with preprocessed images.
        features[HASH_KEY] is a [1] int32 tensor representing unique
          identifiers for the images.
        features[fields.InputDataFields.true_image_shape] is a [1, 3]
          int32 tensor representing the true image shapes, as preprocessed
          images could be padded.
        features[fields.InputDataFields.original_image] is a [1, H', W', C]
          float32 tensor with the original image.
      labels: Dictionary of groundtruth tensors.
        labels[fields.InputDataFields.groundtruth_boxes] is a [1, num_boxes, 4]
          float32 tensor containing the corners of the groundtruth boxes.
        labels[fields.InputDataFields.groundtruth_classes] is a
          [num_boxes, num_classes] float32 one-hot tensor of classes.
        labels[fields.InputDataFields.groundtruth_area] is a [1, num_boxes]
          float32 tensor containing object areas.
        labels[fields.InputDataFields.groundtruth_is_crowd] is a [1, num_boxes]
          bool tensor indicating if the boxes enclose a crowd.
        labels[fields.InputDataFields.groundtruth_difficult] is a [1, num_boxes]
          int32 tensor indicating if the boxes represent difficult instances.
        -- Optional --
        labels[fields.InputDataFields.groundtruth_instance_masks] is a
          [1, num_boxes, H, W] float32 tensor containing only binary values,
          which represent instance masks for objects.

    Raises:
      TypeError: if the `eval_config` or `eval_input_config` are not of the
        correct type.
    """
    del params
    if not isinstance(eval_config, eval_pb2.EvalConfig):
      raise TypeError('For eval mode, the `eval_config` must be a '
                      'train_pb2.EvalConfig.')
    if not isinstance(eval_input_config, input_reader_pb2.InputReader):
      raise TypeError('The `eval_input_config` must be a '
                      'input_reader_pb2.InputReader.')
    if not isinstance(model_config, model_pb2.DetectionModel):
      raise TypeError('The `model_config` must be a '
                      'model_pb2.DetectionModel.')

    num_classes = config_util.get_number_of_classes(model_config)
    model = model_builder.build(model_config, is_training=False)
    image_resizer_config = config_util.get_image_resizer_config(model_config)
    image_resizer_fn = image_resizer_builder.build(image_resizer_config)

    transform_data_fn = functools.partial(
        transform_input_data, model_preprocess_fn=model.preprocess,
        image_resizer_fn=image_resizer_fn,
        num_classes=num_classes,
        data_augmentation_fn=None,
        retain_original_image=True)
    dataset = dataset_builder.build(eval_input_config,
                                    transform_input_data_fn=transform_data_fn)
    input_dict = dataset_util.make_initializable_iterator(dataset).get_next()

    hash_from_source_id = tf.string_to_hash_bucket_fast(
        input_dict[fields.InputDataFields.source_id], HASH_BINS)
    features = {
        fields.InputDataFields.image:
            input_dict[fields.InputDataFields.image],
        fields.InputDataFields.original_image:
            input_dict[fields.InputDataFields.original_image],
        HASH_KEY: tf.cast(hash_from_source_id, tf.int32),
        fields.InputDataFields.true_image_shape:
            input_dict[fields.InputDataFields.true_image_shape]
    }

    labels = {
        fields.InputDataFields.groundtruth_boxes:
            input_dict[fields.InputDataFields.groundtruth_boxes],
        fields.InputDataFields.groundtruth_classes:
            input_dict[fields.InputDataFields.groundtruth_classes],
        fields.InputDataFields.groundtruth_area:
            input_dict[fields.InputDataFields.groundtruth_area],
        fields.InputDataFields.groundtruth_is_crowd:
            input_dict[fields.InputDataFields.groundtruth_is_crowd],
        fields.InputDataFields.groundtruth_difficult:
            tf.cast(input_dict[fields.InputDataFields.groundtruth_difficult],
                    tf.int32)
    }
    if fields.InputDataFields.groundtruth_instance_masks in input_dict:
      labels[fields.InputDataFields.groundtruth_instance_masks] = input_dict[
          fields.InputDataFields.groundtruth_instance_masks]

    # Add a batch dimension to the tensors.
    features = {
        key: tf.expand_dims(features[key], axis=0)
        for key, feature in features.items()
    }
    labels = {
        key: tf.expand_dims(labels[key], axis=0)
        for key, label in labels.items()
    }

    return features, labels
Exemple #16
0
  def _train_input_fn(params=None):
    """Returns `features` and `labels` tensor dictionaries for training.

    Args:
      params: Parameter dictionary passed from the estimator.

    Returns:
      features: Dictionary of feature tensors.
        features[fields.InputDataFields.image] is a [batch_size, H, W, C]
          float32 tensor with preprocessed images.
        features[HASH_KEY] is a [batch_size] int32 tensor representing unique
          identifiers for the images.
        features[fields.InputDataFields.true_image_shape] is a [batch_size, 3]
          int32 tensor representing the true image shapes, as preprocessed
          images could be padded.
      labels: Dictionary of groundtruth tensors.
        labels[fields.InputDataFields.num_groundtruth_boxes] is a [batch_size]
          int32 tensor indicating the number of groundtruth boxes.
        labels[fields.InputDataFields.groundtruth_boxes] is a
          [batch_size, num_boxes, 4] float32 tensor containing the corners of
          the groundtruth boxes.
        labels[fields.InputDataFields.groundtruth_classes] is a
          [batch_size, num_boxes, num_classes] float32 one-hot tensor of
          classes.
        labels[fields.InputDataFields.groundtruth_weights] is a
          [batch_size, num_boxes] float32 tensor containing groundtruth weights
          for the boxes.
        -- Optional --
        labels[fields.InputDataFields.groundtruth_instance_masks] is a
          [batch_size, num_boxes, H, W] float32 tensor containing only binary
          values, which represent instance masks for objects.
        labels[fields.InputDataFields.groundtruth_keypoints] is a
          [batch_size, num_boxes, num_keypoints, 2] float32 tensor containing
          keypoints for each box.

    Raises:
      TypeError: if the `train_config` or `train_input_config` are not of the
        correct type.
    """
    if not isinstance(train_config, train_pb2.TrainConfig):
      raise TypeError('For training mode, the `train_config` must be a '
                      'train_pb2.TrainConfig.')
    if not isinstance(train_input_config, input_reader_pb2.InputReader):
      raise TypeError('The `train_input_config` must be a '
                      'input_reader_pb2.InputReader.')
    if not isinstance(model_config, model_pb2.DetectionModel):
      raise TypeError('The `model_config` must be a '
                      'model_pb2.DetectionModel.')

    data_augmentation_options = [
        preprocessor_builder.build(step)
        for step in train_config.data_augmentation_options
    ]
    data_augmentation_fn = functools.partial(
        augment_input_data, data_augmentation_options=data_augmentation_options)

    model = model_builder.build(model_config, is_training=True)
    image_resizer_config = config_util.get_image_resizer_config(model_config)
    image_resizer_fn = image_resizer_builder.build(image_resizer_config)

    transform_data_fn = functools.partial(
        transform_input_data, model_preprocess_fn=model.preprocess,
        image_resizer_fn=image_resizer_fn,
        num_classes=config_util.get_number_of_classes(model_config),
        data_augmentation_fn=data_augmentation_fn)
    dataset = dataset_builder.build(
        train_input_config,
        transform_input_data_fn=transform_data_fn,
        batch_size=params['batch_size'] if params else train_config.batch_size,
        max_num_boxes=train_config.max_number_of_boxes,
        num_classes=config_util.get_number_of_classes(model_config),
        spatial_image_shape=config_util.get_spatial_image_size(
            image_resizer_config))
    tensor_dict = dataset_util.make_initializable_iterator(dataset).get_next()

    hash_from_source_id = tf.string_to_hash_bucket_fast(
        tensor_dict[fields.InputDataFields.source_id], HASH_BINS)
    features = {
        fields.InputDataFields.image: tensor_dict[fields.InputDataFields.image],
        HASH_KEY: tf.cast(hash_from_source_id, tf.int32),
        fields.InputDataFields.true_image_shape: tensor_dict[
            fields.InputDataFields.true_image_shape]
    }

    labels = {
        fields.InputDataFields.num_groundtruth_boxes: tensor_dict[
            fields.InputDataFields.num_groundtruth_boxes],
        fields.InputDataFields.groundtruth_boxes: tensor_dict[
            fields.InputDataFields.groundtruth_boxes],
        fields.InputDataFields.groundtruth_classes: tensor_dict[
            fields.InputDataFields.groundtruth_classes],
        fields.InputDataFields.groundtruth_weights: tensor_dict[
            fields.InputDataFields.groundtruth_weights]
    }
    if fields.InputDataFields.groundtruth_keypoints in tensor_dict:
      labels[fields.InputDataFields.groundtruth_keypoints] = tensor_dict[
          fields.InputDataFields.groundtruth_keypoints]
    if fields.InputDataFields.groundtruth_instance_masks in tensor_dict:
      labels[fields.InputDataFields.groundtruth_instance_masks] = tensor_dict[
          fields.InputDataFields.groundtruth_instance_masks]

    return features, labels
Exemple #17
0
 def test_create_faster_rcnn_resnet_v1_models_from_config(self):
     model_text_proto = """
   faster_rcnn {
     num_classes: 3
     image_resizer {
       keep_aspect_ratio_resizer {
         min_dimension: 600
         max_dimension: 1024
       }
     }
     feature_extractor {
       type: 'faster_rcnn_resnet101'
     }
     first_stage_anchor_generator {
       grid_anchor_generator {
         scales: [0.25, 0.5, 1.0, 2.0]
         aspect_ratios: [0.5, 1.0, 2.0]
         height_stride: 16
         width_stride: 16
       }
     }
     first_stage_box_predictor_conv_hyperparams {
       regularizer {
         l2_regularizer {
         }
       }
       initializer {
         truncated_normal_initializer {
         }
       }
     }
     initial_crop_size: 14
     maxpool_kernel_size: 2
     maxpool_stride: 2
     second_stage_box_predictor {
       mask_rcnn_box_predictor {
         fc_hyperparams {
           op: FC
           regularizer {
             l2_regularizer {
             }
           }
           initializer {
             truncated_normal_initializer {
             }
           }
         }
       }
     }
     second_stage_post_processing {
       batch_non_max_suppression {
         score_threshold: 0.01
         iou_threshold: 0.6
         max_detections_per_class: 100
         max_total_detections: 300
       }
       score_converter: SOFTMAX
     }
   }"""
     model_proto = model_pb2.DetectionModel()
     text_format.Merge(model_text_proto, model_proto)
     for extractor_type, extractor_class in FEATURE_EXTRACTOR_MAPS.iteritems(
     ):
         model_proto.faster_rcnn.feature_extractor.type = extractor_type
         model = model_builder.build(model_proto, is_training=True)
         self.assertIsInstance(model,
                               faster_rcnn_meta_arch.FasterRCNNMetaArch)
         self.assertIsInstance(model._feature_extractor, extractor_class)
Exemple #18
0
 def test_create_rfcn_resnet_v1_model_from_config(self):
   model_text_proto = """
     faster_rcnn {
       num_classes: 3
       image_resizer {
         keep_aspect_ratio_resizer {
           min_dimension: 600
           max_dimension: 1024
         }
       }
       feature_extractor {
         type: 'faster_rcnn_resnet101'
       }
       first_stage_anchor_generator {
         grid_anchor_generator {
           scales: [0.25, 0.5, 1.0, 2.0]
           aspect_ratios: [0.5, 1.0, 2.0]
           height_stride: 16
           width_stride: 16
         }
       }
       first_stage_box_predictor_conv_hyperparams {
         regularizer {
           l2_regularizer {
           }
         }
         initializer {
           truncated_normal_initializer {
           }
         }
       }
       initial_crop_size: 14
       maxpool_kernel_size: 2
       maxpool_stride: 2
       second_stage_box_predictor {
         rfcn_box_predictor {
           conv_hyperparams {
             op: CONV
             regularizer {
               l2_regularizer {
               }
             }
             initializer {
               truncated_normal_initializer {
               }
             }
           }
         }
       }
       second_stage_post_processing {
         batch_non_max_suppression {
           score_threshold: 0.01
           iou_threshold: 0.6
           max_detections_per_class: 100
           max_total_detections: 300
         }
         score_converter: SOFTMAX
       }
     }"""
   model_proto = model_pb2.DetectionModel()
   text_format.Merge(model_text_proto, model_proto)
   for extractor_type, extractor_class in FRCNN_RESNET_FEAT_MAPS.items():
     model_proto.faster_rcnn.feature_extractor.type = extractor_type
     model = model_builder.build(model_proto, is_training=True)
     self.assertIsInstance(model, rfcn_meta_arch.RFCNMetaArch)
     self.assertIsInstance(model._feature_extractor, extractor_class)
Exemple #19
0
 def test_create_faster_rcnn_inception_v2_model_from_config(self):
   model_text_proto = """
     faster_rcnn {
       num_classes: 3
       image_resizer {
         keep_aspect_ratio_resizer {
           min_dimension: 600
           max_dimension: 1024
         }
       }
       feature_extractor {
         type: 'faster_rcnn_inception_v2'
       }
       first_stage_anchor_generator {
         grid_anchor_generator {
           scales: [0.25, 0.5, 1.0, 2.0]
           aspect_ratios: [0.5, 1.0, 2.0]
           height_stride: 16
           width_stride: 16
         }
       }
       first_stage_box_predictor_conv_hyperparams {
         regularizer {
           l2_regularizer {
           }
         }
         initializer {
           truncated_normal_initializer {
           }
         }
       }
       initial_crop_size: 14
       maxpool_kernel_size: 2
       maxpool_stride: 2
       second_stage_box_predictor {
         mask_rcnn_box_predictor {
           fc_hyperparams {
             op: FC
             regularizer {
               l2_regularizer {
               }
             }
             initializer {
               truncated_normal_initializer {
               }
             }
           }
         }
       }
       second_stage_post_processing {
         batch_non_max_suppression {
           score_threshold: 0.01
           iou_threshold: 0.6
           max_detections_per_class: 100
           max_total_detections: 300
         }
         score_converter: SOFTMAX
       }
     }"""
   model_proto = model_pb2.DetectionModel()
   text_format.Merge(model_text_proto, model_proto)
   model = model_builder.build(model_proto, is_training=True)
   self.assertIsInstance(model, faster_rcnn_meta_arch.FasterRCNNMetaArch)
   self.assertIsInstance(model._feature_extractor,
                         frcnn_inc_v2.FasterRCNNInceptionV2FeatureExtractor)
Exemple #20
0
def eval_continuously(hparams,
                      pipeline_config_path,
                      config_override=None,
                      train_steps=None,
                      sample_1_of_n_eval_examples=1,
                      sample_1_of_n_eval_on_train_examples=1,
                      use_tpu=False,
                      override_eval_num_epochs=True,
                      postprocess_on_cpu=False,
                      export_to_tpu=None,
                      model_dir=None,
                      checkpoint_dir=None,
                      wait_interval=180,
                      **kwargs):
    """Run continuous evaluation of a detection model eagerly.

  This method builds the model, and continously restores it from the most
  recent training checkpoint in the checkpoint directory & evaluates it
  on the evaluation data.

  Args:
    hparams: A `HParams`.
    pipeline_config_path: A path to a pipeline config file.
    config_override: A pipeline_pb2.TrainEvalPipelineConfig text proto to
      override the config from `pipeline_config_path`.
    train_steps: Number of training steps. If None, the number of training steps
      is set from the `TrainConfig` proto.
    sample_1_of_n_eval_examples: Integer representing how often an eval example
      should be sampled. If 1, will sample all examples.
    sample_1_of_n_eval_on_train_examples: Similar to
      `sample_1_of_n_eval_examples`, except controls the sampling of training
      data for evaluation.
    use_tpu: Boolean, whether training and evaluation should run on TPU.
    override_eval_num_epochs: Whether to overwrite the number of epochs to 1 for
      eval_input.
    postprocess_on_cpu: When use_tpu and postprocess_on_cpu are true,
      postprocess is scheduled on the host cpu.
    export_to_tpu: When use_tpu and export_to_tpu are true,
      `export_savedmodel()` exports a metagraph for serving on TPU besides the
      one on CPU. If export_to_tpu is not provided, we will look for it in
      hparams too.
    model_dir:
      Directory to output resulting evaluation summaries to.
    checkpoint_dir:
      Directory that contains the training checkpoints.
    wait_interval:
      Terminate evaluation in no new checkpoints arrive within this wait
      interval (in seconds).
    **kwargs: Additional keyword arguments for configuration override.
  """
    get_configs_from_pipeline_file = MODEL_BUILD_UTIL_MAP[
        'get_configs_from_pipeline_file']
    merge_external_params_with_configs = MODEL_BUILD_UTIL_MAP[
        'merge_external_params_with_configs']

    configs = get_configs_from_pipeline_file(pipeline_config_path,
                                             config_override=config_override)
    kwargs.update({
        'sample_1_of_n_eval_examples':
        sample_1_of_n_eval_examples,
        'use_bfloat16':
        configs['train_config'].use_bfloat16 and use_tpu
    })
    if train_steps is not None:
        kwargs['train_steps'] = train_steps
    if override_eval_num_epochs:
        kwargs.update({'eval_num_epochs': 1})
        tf.logging.warning(
            'Forced number of epochs for all eval validations to be 1.')
    configs = merge_external_params_with_configs(configs,
                                                 hparams,
                                                 kwargs_dict=kwargs)
    model_config = configs['model']
    train_input_config = configs['train_input_config']
    eval_config = configs['eval_config']
    eval_input_configs = configs['eval_input_configs']
    eval_on_train_input_config = copy.deepcopy(train_input_config)
    eval_on_train_input_config.sample_1_of_n_examples = (
        sample_1_of_n_eval_on_train_examples)
    if override_eval_num_epochs and eval_on_train_input_config.num_epochs != 1:
        tf.logging.warning('Expected number of evaluation epochs is 1, but '
                           'instead encountered `eval_on_train_input_config'
                           '.num_epochs` = '
                           '{}. Overwriting `num_epochs` to 1.'.format(
                               eval_on_train_input_config.num_epochs))
        eval_on_train_input_config.num_epochs = 1

    detection_model = model_builder.build(model_config=model_config,
                                          is_training=True)

    # Create the inputs.
    eval_inputs = []
    for eval_input_config in eval_input_configs:
        next_eval_input = inputs.eval_input(
            eval_config=eval_config,
            eval_input_config=eval_input_config,
            model_config=model_config,
            model=detection_model)
        eval_inputs.append((eval_input_config.name, next_eval_input))

    # Read export_to_tpu from hparams if not passed.
    if export_to_tpu is None:
        export_to_tpu = hparams.get('export_to_tpu', False)
    tf.logging.info('eval_continuously: use_tpu %s, export_to_tpu %s', use_tpu,
                    export_to_tpu)

    global_step = tf.compat.v2.Variable(0,
                                        trainable=False,
                                        dtype=tf.compat.v2.dtypes.int64)

    prev_checkpoint = None
    waiting = False
    while True:
        ckpt = tf.compat.v2.train.Checkpoint(step=global_step,
                                             model=detection_model)
        manager = tf.compat.v2.train.CheckpointManager(ckpt,
                                                       checkpoint_dir,
                                                       max_to_keep=3)

        latest_checkpoint = manager.latest_checkpoint
        if prev_checkpoint == latest_checkpoint:
            if prev_checkpoint is None:
                tf.logging.info(
                    'No checkpoints found yet. Trying again in %s seconds.' %
                    wait_interval)
                time.sleep(wait_interval)
            else:
                if waiting:
                    tf.logging.info(
                        'Terminating eval after %s seconds of no new '
                        'checkpoints.' % wait_interval)
                    break
                else:
                    tf.logging.info(
                        'No new checkpoint found. Will try again '
                        'in %s seconds and terminate if no checkpoint '
                        'appears.' % wait_interval)
                    waiting = True
                    time.sleep(wait_interval)
        else:
            tf.logging.info('New checkpoint found. Starting evaluation.')
            waiting = False
            prev_checkpoint = latest_checkpoint
            ckpt.restore(latest_checkpoint)

            for eval_name, eval_input in eval_inputs:
                summary_writer = tf.compat.v2.summary.create_file_writer(
                    model_dir + '/eval' + eval_name)
                with summary_writer.as_default():
                    eager_eval_loop(detection_model,
                                    configs,
                                    eval_input,
                                    use_tpu=use_tpu,
                                    postprocess_on_cpu=postprocess_on_cpu,
                                    global_step=global_step)
Exemple #21
0
  def test_write_saved_model(self):
    tmp_dir = self.get_temp_dir()
    trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt')
    self._save_checkpoint_from_mock_model(trained_checkpoint_prefix,
                                          use_moving_averages=False)
    output_directory = os.path.join(tmp_dir, 'output')
    saved_model_path = os.path.join(output_directory, 'saved_model')
    tf.gfile.MakeDirs(output_directory)
    with mock.patch.object(
        model_builder, 'build', autospec=True) as mock_builder:
      mock_builder.return_value = FakeModel(add_detection_masks=True)
      pipeline_config = pipeline_pb2.TrainEvalPipelineConfig()
      pipeline_config.eval_config.use_moving_averages = False
      detection_model = model_builder.build(pipeline_config.model,
                                            is_training=False)
      outputs, placeholder_tensor = exporter._build_detection_graph(
          input_type='tf_example',
          detection_model=detection_model,
          input_shape=None,
          output_collection_name='inference_op',
          graph_hook_fn=None)
      output_node_names = ','.join(outputs.keys())
      saver = tf.train.Saver()
      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=trained_checkpoint_prefix,
          output_node_names=output_node_names,
          restore_op_name='save/restore_all',
          filename_tensor_name='save/Const:0',
          clear_devices=True,
          initializer_nodes='')
      exporter.write_saved_model(
          saved_model_path=saved_model_path,
          frozen_graph_def=frozen_graph_def,
          inputs=placeholder_tensor,
          outputs=outputs)

    tf_example_np = np.hstack([self._create_tf_example(
        np.ones((4, 4, 3)).astype(np.uint8))] * 2)
    with tf.Graph().as_default() as od_graph:
      with self.test_session(graph=od_graph) as sess:
        meta_graph = tf.saved_model.loader.load(
            sess, [tf.saved_model.tag_constants.SERVING], saved_model_path)

        signature = meta_graph.signature_def['serving_default']
        input_tensor_name = signature.inputs['inputs'].name
        tf_example = od_graph.get_tensor_by_name(input_tensor_name)

        boxes = od_graph.get_tensor_by_name(
            signature.outputs['detection_boxes'].name)
        scores = od_graph.get_tensor_by_name(
            signature.outputs['detection_scores'].name)
        classes = od_graph.get_tensor_by_name(
            signature.outputs['detection_classes'].name)
        masks = od_graph.get_tensor_by_name(
            signature.outputs['detection_masks'].name)
        num_detections = od_graph.get_tensor_by_name(
            signature.outputs['num_detections'].name)

        (boxes_np, scores_np, classes_np, masks_np,
         num_detections_np) = sess.run(
             [boxes, scores, classes, masks, num_detections],
             feed_dict={tf_example: tf_example_np})
        self.assertAllClose(boxes_np, [[[0.0, 0.0, 0.5, 0.5],
                                        [0.5, 0.5, 0.8, 0.8]],
                                       [[0.5, 0.5, 1.0, 1.0],
                                        [0.0, 0.0, 0.0, 0.0]]])
        self.assertAllClose(scores_np, [[0.7, 0.6],
                                        [0.9, 0.0]])
        self.assertAllClose(classes_np, [[1, 2],
                                         [2, 1]])
        self.assertAllClose(masks_np, np.arange(64).reshape([2, 2, 4, 4]))
        self.assertAllClose(num_detections_np, [2, 1])
Exemple #22
0
  def test_create_ssd_resnet_v1_ppn_model_from_config(self):
    model_text_proto = """
      ssd {
        feature_extractor {
          type: 'ssd_resnet_v1_50_ppn'
          conv_hyperparams {
            regularizer {
                l2_regularizer {
                }
              }
              initializer {
                truncated_normal_initializer {
                }
              }
          }
        }
        box_coder {
          mean_stddev_box_coder {
          }
        }
        matcher {
          bipartite_matcher {
          }
        }
        similarity_calculator {
          iou_similarity {
          }
        }
        anchor_generator {
          ssd_anchor_generator {
            aspect_ratios: 1.0
          }
        }
        image_resizer {
          fixed_shape_resizer {
            height: 320
            width: 320
          }
        }
        box_predictor {
          weight_shared_convolutional_box_predictor {
            depth: 1024
            class_prediction_bias_init: -4.6
            conv_hyperparams {
              activation: RELU_6,
              regularizer {
                l2_regularizer {
                  weight: 0.0004
                }
              }
              initializer {
                variance_scaling_initializer {
                }
              }
            }
            num_layers_before_predictor: 2
            kernel_size: 1
          }
        }
        loss {
          classification_loss {
            weighted_softmax {
            }
          }
          localization_loss {
            weighted_l2 {
            }
          }
          classification_weight: 1.0
          localization_weight: 1.0
        }
      }"""
    model_proto = model_pb2.DetectionModel()
    text_format.Merge(model_text_proto, model_proto)

    for extractor_type, extractor_class in SSD_RESNET_V1_PPN_FEAT_MAPS.items():
      model_proto.ssd.feature_extractor.type = extractor_type
      model = model_builder.build(model_proto, is_training=True)
      self.assertIsInstance(model, ssd_meta_arch.SSDMetaArch)
      self.assertIsInstance(model._feature_extractor, extractor_class)
Exemple #23
0
def eval_continuously(pipeline_config_path,
                      config_override=None,
                      train_steps=None,
                      sample_1_of_n_eval_examples=1,
                      sample_1_of_n_eval_on_train_examples=1,
                      use_tpu=False,
                      override_eval_num_epochs=True,
                      postprocess_on_cpu=False,
                      model_dir=None,
                      checkpoint_dir=None,
                      wait_interval=180,
                      timeout=3600,
                      **kwargs):
    """Run continuous evaluation of a detection model eagerly.

  This method builds the model, and continously restores it from the most
  recent training checkpoint in the checkpoint directory & evaluates it
  on the evaluation data.

  Args:
    pipeline_config_path: A path to a pipeline config file.
    config_override: A pipeline_pb2.TrainEvalPipelineConfig text proto to
      override the config from `pipeline_config_path`.
    train_steps: Number of training steps. If None, the number of training steps
      is set from the `TrainConfig` proto.
    sample_1_of_n_eval_examples: Integer representing how often an eval example
      should be sampled. If 1, will sample all examples.
    sample_1_of_n_eval_on_train_examples: Similar to
      `sample_1_of_n_eval_examples`, except controls the sampling of training
      data for evaluation.
    use_tpu: Boolean, whether training and evaluation should run on TPU.
    override_eval_num_epochs: Whether to overwrite the number of epochs to 1 for
      eval_input.
    postprocess_on_cpu: When use_tpu and postprocess_on_cpu are true,
      postprocess is scheduled on the host cpu.
    model_dir: Directory to output resulting evaluation summaries to.
    checkpoint_dir: Directory that contains the training checkpoints.
    wait_interval: The mimmum number of seconds to wait before checking for a
      new checkpoint.
    timeout: The maximum number of seconds to wait for a checkpoint. Execution
      will terminate if no new checkpoints are found after these many seconds.

    **kwargs: Additional keyword arguments for configuration override.
  """
    get_configs_from_pipeline_file = MODEL_BUILD_UTIL_MAP[
        'get_configs_from_pipeline_file']
    merge_external_params_with_configs = MODEL_BUILD_UTIL_MAP[
        'merge_external_params_with_configs']

    configs = get_configs_from_pipeline_file(pipeline_config_path,
                                             config_override=config_override)
    kwargs.update({
        'sample_1_of_n_eval_examples':
        sample_1_of_n_eval_examples,
        'use_bfloat16':
        configs['train_config'].use_bfloat16 and use_tpu
    })
    if train_steps is not None:
        kwargs['train_steps'] = train_steps
    if override_eval_num_epochs:
        kwargs.update({'eval_num_epochs': 1})
        tf.logging.warning(
            'Forced number of epochs for all eval validations to be 1.')
    configs = merge_external_params_with_configs(configs,
                                                 None,
                                                 kwargs_dict=kwargs)
    model_config = configs['model']
    train_input_config = configs['train_input_config']
    eval_config = configs['eval_config']
    eval_input_configs = configs['eval_input_configs']
    eval_on_train_input_config = copy.deepcopy(train_input_config)
    eval_on_train_input_config.sample_1_of_n_examples = (
        sample_1_of_n_eval_on_train_examples)
    if override_eval_num_epochs and eval_on_train_input_config.num_epochs != 1:
        tf.logging.warning('Expected number of evaluation epochs is 1, but '
                           'instead encountered `eval_on_train_input_config'
                           '.num_epochs` = '
                           '{}. Overwriting `num_epochs` to 1.'.format(
                               eval_on_train_input_config.num_epochs))
        eval_on_train_input_config.num_epochs = 1

    if kwargs['use_bfloat16']:
        tf.compat.v2.keras.mixed_precision.experimental.set_policy(
            'mixed_bfloat16')

    detection_model = model_builder.build(model_config=model_config,
                                          is_training=True)

    # Create the inputs.
    eval_inputs = []
    for eval_input_config in eval_input_configs:
        next_eval_input = inputs.eval_input(
            eval_config=eval_config,
            eval_input_config=eval_input_config,
            model_config=model_config,
            model=detection_model)
        eval_inputs.append((eval_input_config.name, next_eval_input))

    global_step = tf.compat.v2.Variable(0,
                                        trainable=False,
                                        dtype=tf.compat.v2.dtypes.int64)

    for latest_checkpoint in tf.train.checkpoints_iterator(
            checkpoint_dir, timeout=timeout, min_interval_secs=wait_interval):
        ckpt = tf.compat.v2.train.Checkpoint(step=global_step,
                                             model=detection_model)

        ckpt.restore(latest_checkpoint).expect_partial()

        for eval_name, eval_input in eval_inputs:
            summary_writer = tf.compat.v2.summary.create_file_writer(
                os.path.join(model_dir, 'eval', eval_name))
            with summary_writer.as_default():
                eager_eval_loop(detection_model,
                                configs,
                                eval_input,
                                use_tpu=use_tpu,
                                postprocess_on_cpu=postprocess_on_cpu,
                                global_step=global_step)
Exemple #24
0
def get_stats(model_name):
    pipeline_config = 'saved_models/inference_models/' + model_name + '/pipeline.config'
    model_dir = 'saved_models/inference_models/' + model_name + '/checkpoint/'

    # Load pipeline config and build a detection model
    configs = config_util.get_configs_from_pipeline_file(pipeline_config)
    model_config = configs['model']
    detection_model = model_builder.build(model_config=model_config,
                                          is_training=False)

    # Restore checkpoint
    ckpt = tf.compat.v2.train.Checkpoint(model=detection_model)
    ckpt.restore(os.path.join(model_dir, 'ckpt-0')).expect_partial()

    detect_fn = get_model_detection_function(detection_model)
    image_np = load_image_into_numpy_array("image.png")
    input_tensor = tf.convert_to_tensor(np.expand_dims(image_np, 0),
                                        dtype=tf.float32)

    # Number of parameters
    variables = tf.train.list_variables(model_dir)
    total_parameters = 0
    for variable in variables:
        # shape is an array of tf.Dimension
        shape = variable[1]
        variable_parameters = 1
        for dim in shape:
            variable_parameters *= dim
        total_parameters += variable_parameters

    # Memory usage
    with context.eager_mode():
        context.enable_run_metadata()
        detections, predictions_dict, shapes = detect_fn(input_tensor)

        opts = tf.compat.v1.profiler.ProfileOptionBuilder.time_and_memory()
        profiler = tf.compat.v1.profiler.Profiler()
        metadata = context.export_run_metadata()
        profiler.add_step(0, metadata)
        context.disable_run_metadata()
        tm = profiler.profile_graph(opts)
        memory = tm.total_requested_bytes

    # Number of flops
    full_model = detect_fn.get_concrete_function(
        image=tf.TensorSpec(input_tensor.shape, input_tensor.dtype))
    frozen_func = convert_variables_to_constants_v2(full_model)
    # frozen_func.graph.as_graph_def()
    # layers = [op.name for op in frozen_func.graph.get_operations()]
    stats = tf.compat.v1.profiler.profile(
        graph=frozen_func.graph,
        run_meta=metadata,
        cmd='op',
        options=tf.compat.v1.profiler.ProfileOptionBuilder.float_operation())
    flops = stats.total_float_ops

    stats = {
        'model_name': model_name,
        'parameters': total_parameters,
        'flops': flops,
        'memory': memory
    }
    return stats
Exemple #25
0
    def _train_input_fn(params=None):
        """Returns `features` and `labels` tensor dictionaries for training.

    Args:
      params: Parameter dictionary passed from the estimator.

    Returns:
      features: Dictionary of feature tensors.
        features[fields.InputDataFields.image] is a [batch_size, H, W, C]
          float32 tensor with preprocessed images.
        features[HASH_KEY] is a [batch_size] int32 tensor representing unique
          identifiers for the images.
        features[fields.InputDataFields.true_image_shape] is a [batch_size, 3]
          int32 tensor representing the true image shapes, as preprocessed
          images could be padded.
        features[fields.InputDataFields.original_image] (optional) is a
          [batch_size, H, W, C] float32 tensor with original images.
      labels: Dictionary of groundtruth tensors.
        labels[fields.InputDataFields.num_groundtruth_boxes] is a [batch_size]
          int32 tensor indicating the number of groundtruth boxes.
        labels[fields.InputDataFields.groundtruth_boxes] is a
          [batch_size, num_boxes, 4] float32 tensor containing the corners of
          the groundtruth boxes.
        labels[fields.InputDataFields.groundtruth_classes] is a
          [batch_size, num_boxes, num_classes] float32 one-hot tensor of
          classes.
        labels[fields.InputDataFields.groundtruth_weights] is a
          [batch_size, num_boxes] float32 tensor containing groundtruth weights
          for the boxes.
        -- Optional --
        labels[fields.InputDataFields.groundtruth_instance_masks] is a
          [batch_size, num_boxes, H, W] float32 tensor containing only binary
          values, which represent instance masks for objects.
        labels[fields.InputDataFields.groundtruth_keypoints] is a
          [batch_size, num_boxes, num_keypoints, 2] float32 tensor containing
          keypoints for each box.

    Raises:
      TypeError: if the `train_config`, `train_input_config` or `model_config`
        are not of the correct type.
    """
        if not isinstance(train_config, train_pb2.TrainConfig):
            raise TypeError('For training mode, the `train_config` must be a '
                            'train_pb2.TrainConfig.')
        if not isinstance(train_input_config, input_reader_pb2.InputReader):
            raise TypeError('The `train_input_config` must be a '
                            'input_reader_pb2.InputReader.')
        if not isinstance(model_config, model_pb2.DetectionModel):
            raise TypeError('The `model_config` must be a '
                            'model_pb2.DetectionModel.')

        data_augmentation_options = [
            preprocessor_builder.build(step)
            for step in train_config.data_augmentation_options
        ]
        data_augmentation_fn = functools.partial(
            augment_input_data,
            data_augmentation_options=data_augmentation_options)

        model = model_builder.build(model_config, is_training=True)
        image_resizer_config = config_util.get_image_resizer_config(
            model_config)
        image_resizer_fn = image_resizer_builder.build(image_resizer_config)

        transform_data_fn = functools.partial(
            transform_input_data,
            model_preprocess_fn=model.preprocess,
            image_resizer_fn=image_resizer_fn,
            num_classes=config_util.get_number_of_classes(model_config),
            data_augmentation_fn=data_augmentation_fn,
            retain_original_image=train_config.retain_original_images)
        dataset = INPUT_BUILDER_UTIL_MAP['dataset_build'](
            train_input_config,
            transform_input_data_fn=transform_data_fn,
            batch_size=params['batch_size']
            if params else train_config.batch_size,
            max_num_boxes=train_config.max_number_of_boxes,
            num_classes=config_util.get_number_of_classes(model_config),
            spatial_image_shape=config_util.get_spatial_image_size(
                image_resizer_config))
        input_dict = dataset_util.make_initializable_iterator(
            dataset).get_next()
        return (_get_features_dict(input_dict), _get_labels_dict(input_dict))
Exemple #26
0
    15: {
        'id': 15,
        'name': 'nigella'
    },
    16: {
        'id': 16,
        'name': 'sunflower'
    }
}

# 定义模型
configs = config_util.get_configs_from_pipeline_file(pipeline_config)
model_config = configs['model']
model_config.ssd.num_classes = num_classes
model_config.ssd.freeze_batchnorm = True
detection_model = model_builder.build(model_config=model_config,
                                      is_training=True)

# 加载tflite文件
interpreter = tf.lite.Interpreter(model_path="model.tflite")
interpreter.allocate_tensors()
label_id_offset = 1
# 定义摄像头
capture = cv2.VideoCapture(0)

while True:
    # 拍照并预处理照片
    ret, frame = capture.read()
    frame = cv2.flip(frame, 1)
    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    test = np.expand_dims(frame_rgb, axis=0)
    input_tensor = tf.convert_to_tensor(test, dtype=tf.float32)
Exemple #27
0
 def test_create_faster_rcnn_resnet101_with_mask_prediction_enabled(self):
   model_text_proto = """
     faster_rcnn {
       num_classes: 3
       image_resizer {
         keep_aspect_ratio_resizer {
           min_dimension: 600
           max_dimension: 1024
         }
       }
       feature_extractor {
         type: 'faster_rcnn_resnet101'
       }
       first_stage_anchor_generator {
         grid_anchor_generator {
           scales: [0.25, 0.5, 1.0, 2.0]
           aspect_ratios: [0.5, 1.0, 2.0]
           height_stride: 16
           width_stride: 16
         }
       }
       first_stage_box_predictor_conv_hyperparams {
         regularizer {
           l2_regularizer {
           }
         }
         initializer {
           truncated_normal_initializer {
           }
         }
       }
       initial_crop_size: 14
       maxpool_kernel_size: 2
       maxpool_stride: 2
       second_stage_box_predictor {
         mask_rcnn_box_predictor {
           fc_hyperparams {
             op: FC
             regularizer {
               l2_regularizer {
               }
             }
             initializer {
               truncated_normal_initializer {
               }
             }
           }
           conv_hyperparams {
             regularizer {
               l2_regularizer {
               }
             }
             initializer {
               truncated_normal_initializer {
               }
             }
           }
           predict_instance_masks: true
         }
       }
       second_stage_mask_prediction_loss_weight: 3.0
       second_stage_post_processing {
         batch_non_max_suppression {
           score_threshold: 0.01
           iou_threshold: 0.6
           max_detections_per_class: 100
           max_total_detections: 300
         }
         score_converter: SOFTMAX
       }
     }"""
   model_proto = model_pb2.DetectionModel()
   text_format.Merge(model_text_proto, model_proto)
   model = model_builder.build(model_proto, is_training=True)
   self.assertAlmostEqual(model._second_stage_mask_loss_weight, 3.0)
Exemple #28
0
def train_loop(pipeline_config_path,
               model_dir,
               config_override=None,
               train_steps=None,
               use_tpu=False,
               save_final_config=False,
               checkpoint_every_n=1000,
               checkpoint_max_to_keep=7,
               **kwargs):
    """Trains a model using eager + functions.

  This method:
    1. Processes the pipeline configs
    2. (Optionally) saves the as-run config
    3. Builds the model & optimizer
    4. Gets the training input data
    5. Loads a fine-tuning detection or classification checkpoint if requested
    6. Loops over the train data, executing distributed training steps inside
       tf.functions.
    7. Checkpoints the model every `checkpoint_every_n` training steps.
    8. Logs the training metrics as TensorBoard summaries.

  Args:
    pipeline_config_path: A path to a pipeline config file.
    model_dir:
      The directory to save checkpoints and summaries to.
    config_override: A pipeline_pb2.TrainEvalPipelineConfig text proto to
      override the config from `pipeline_config_path`.
    train_steps: Number of training steps. If None, the number of training steps
      is set from the `TrainConfig` proto.
    use_tpu: Boolean, whether training and evaluation should run on TPU.
    save_final_config: Whether to save final config (obtained after applying
      overrides) to `model_dir`.
    checkpoint_every_n:
      Checkpoint every n training steps.
    checkpoint_max_to_keep:
      int, the number of most recent checkpoints to keep in the model directory.
    **kwargs: Additional keyword arguments for configuration override.
  """
    ## Parse the configs
    get_configs_from_pipeline_file = MODEL_BUILD_UTIL_MAP[
        'get_configs_from_pipeline_file']
    merge_external_params_with_configs = MODEL_BUILD_UTIL_MAP[
        'merge_external_params_with_configs']
    create_pipeline_proto_from_configs = MODEL_BUILD_UTIL_MAP[
        'create_pipeline_proto_from_configs']

    configs = get_configs_from_pipeline_file(pipeline_config_path,
                                             config_override=config_override)
    kwargs.update({
        'train_steps':
        train_steps,
        'use_bfloat16':
        configs['train_config'].use_bfloat16 and use_tpu
    })
    configs = merge_external_params_with_configs(configs,
                                                 None,
                                                 kwargs_dict=kwargs)
    model_config = configs['model']
    train_config = configs['train_config']
    train_input_config = configs['train_input_config']

    unpad_groundtruth_tensors = train_config.unpad_groundtruth_tensors
    add_regularization_loss = train_config.add_regularization_loss
    clip_gradients_value = None
    if train_config.gradient_clipping_by_norm > 0:
        clip_gradients_value = train_config.gradient_clipping_by_norm

    # update train_steps from config but only when non-zero value is provided
    if train_steps is None and train_config.num_steps != 0:
        train_steps = train_config.num_steps

    if kwargs['use_bfloat16']:
        tf.compat.v2.keras.mixed_precision.experimental.set_policy(
            'mixed_bfloat16')

    if train_config.load_all_detection_checkpoint_vars:
        raise ValueError('train_pb2.load_all_detection_checkpoint_vars '
                         'unsupported in TF2')

    config_util.update_fine_tune_checkpoint_type(train_config)
    fine_tune_checkpoint_type = train_config.fine_tune_checkpoint_type
    fine_tune_checkpoint_version = train_config.fine_tune_checkpoint_version

    # Write the as-run pipeline config to disk.
    if save_final_config:
        pipeline_config_final = create_pipeline_proto_from_configs(configs)
        config_util.save_pipeline_config(pipeline_config_final, model_dir)

    # Build the model, optimizer, and training input
    strategy = tf.compat.v2.distribute.get_strategy()
    with strategy.scope():
        detection_model = model_builder.build(model_config=model_config,
                                              is_training=True)

        def train_dataset_fn(input_context):
            """Callable to create train input."""
            # Create the inputs.
            train_input = inputs.train_input(
                train_config=train_config,
                train_input_config=train_input_config,
                model_config=model_config,
                model=detection_model,
                input_context=input_context)
            train_input = train_input.repeat()
            return train_input

        train_input = strategy.experimental_distribute_datasets_from_function(
            train_dataset_fn)

        global_step = tf.Variable(
            0,
            trainable=False,
            dtype=tf.compat.v2.dtypes.int64,
            name='global_step',
            aggregation=tf.compat.v2.VariableAggregation.ONLY_FIRST_REPLICA)
        optimizer, (learning_rate, ) = optimizer_builder.build(
            train_config.optimizer, global_step=global_step)

        if callable(learning_rate):
            learning_rate_fn = learning_rate
        else:
            learning_rate_fn = lambda: learning_rate

    ## Train the model
    # Get the appropriate filepath (temporary or not) based on whether the worker
    # is the chief.
    summary_writer_filepath = get_filepath(strategy,
                                           os.path.join(model_dir, 'train'))
    summary_writer = tf.compat.v2.summary.create_file_writer(
        summary_writer_filepath)

    if use_tpu:
        num_steps_per_iteration = 100
    else:
        # TODO(b/135933080) Explore setting to 100 when GPU performance issues
        # are fixed.
        num_steps_per_iteration = 1

    with summary_writer.as_default():
        with strategy.scope():
            with tf.compat.v2.summary.record_if(
                    lambda: global_step % num_steps_per_iteration == 0):
                # Load a fine-tuning checkpoint.
                if train_config.fine_tune_checkpoint:
                    load_fine_tune_checkpoint(
                        detection_model, train_config.fine_tune_checkpoint,
                        fine_tune_checkpoint_type,
                        fine_tune_checkpoint_version, train_input,
                        unpad_groundtruth_tensors)

                ckpt = tf.compat.v2.train.Checkpoint(step=global_step,
                                                     model=detection_model,
                                                     optimizer=optimizer)

                manager_dir = get_filepath(strategy, model_dir)
                if not strategy.extended.should_checkpoint:
                    checkpoint_max_to_keep = 1
                manager = tf.compat.v2.train.CheckpointManager(
                    ckpt, manager_dir, max_to_keep=checkpoint_max_to_keep)

                # We use the following instead of manager.latest_checkpoint because
                # manager_dir does not point to the model directory when we are running
                # in a worker.
                latest_checkpoint = tf.train.latest_checkpoint(model_dir)
                ckpt.restore(latest_checkpoint)

                def train_step_fn(features, labels):
                    """Single train step."""
                    loss = eager_train_step(
                        detection_model,
                        features,
                        labels,
                        unpad_groundtruth_tensors,
                        optimizer,
                        learning_rate=learning_rate_fn(),
                        add_regularization_loss=add_regularization_loss,
                        clip_gradients_value=clip_gradients_value,
                        global_step=global_step,
                        num_replicas=strategy.num_replicas_in_sync)
                    global_step.assign_add(1)
                    return loss

                def _sample_and_train(strategy, train_step_fn, data_iterator):
                    features, labels = data_iterator.next()
                    per_replica_losses = strategy.experimental_run_v2(
                        train_step_fn, args=(features, labels))
                    # TODO(anjalisridhar): explore if it is safe to remove the
                    ## num_replicas scaling of the loss and switch this to a ReduceOp.Mean
                    return strategy.reduce(tf.distribute.ReduceOp.SUM,
                                           per_replica_losses,
                                           axis=None)

                @tf.function
                def _dist_train_step(data_iterator):
                    """A distributed train step."""

                    if num_steps_per_iteration > 1:
                        for _ in tf.range(num_steps_per_iteration - 1):
                            _sample_and_train(strategy, train_step_fn,
                                              data_iterator)

                    return _sample_and_train(strategy, train_step_fn,
                                             data_iterator)

                train_input_iter = iter(train_input)

                if int(global_step.value()) == 0:
                    manager.save()

                checkpointed_step = int(global_step.value())
                logged_step = global_step.value()

                last_step_time = time.time()
                for _ in range(global_step.value(), train_steps,
                               num_steps_per_iteration):

                    loss = _dist_train_step(train_input_iter)

                    time_taken = time.time() - last_step_time
                    last_step_time = time.time()

                    tf.compat.v2.summary.scalar('steps_per_sec',
                                                num_steps_per_iteration * 1.0 /
                                                time_taken,
                                                step=global_step)

                    if global_step.value() - logged_step >= 100:
                        tf.logging.info(
                            'Step {} per-step time {:.3f}s loss={:.3f}'.format(
                                global_step.value(),
                                time_taken / num_steps_per_iteration, loss))
                        logged_step = global_step.value()

                    if ((int(global_step.value()) - checkpointed_step) >=
                            checkpoint_every_n):
                        manager.save()
                        checkpointed_step = int(global_step.value())

    # Remove the checkpoint directories of the non-chief workers that
    # MultiWorkerMirroredStrategy forces us to save during sync distributed
    # training.
    clean_temporary_directories(strategy, manager_dir)
    clean_temporary_directories(strategy, summary_writer_filepath)
    def _eval_input_fn(params=None):
        """Returns `features` and `labels` tensor dictionaries for evaluation.

    Args:
      params: Parameter dictionary passed from the estimator.

    Returns:
      features: Dictionary of feature tensors.
        features[fields.InputDataFields.image] is a [1, H, W, C] float32 tensor
          with preprocessed images.
        features[HASH_KEY] is a [1] int32 tensor representing unique
          identifiers for the images.
        features[fields.InputDataFields.true_image_shape] is a [1, 3]
          int32 tensor representing the true image shapes, as preprocessed
          images could be padded.
        features[fields.InputDataFields.original_image] is a [1, H', W', C]
          float32 tensor with the original image.
      labels: Dictionary of groundtruth tensors.
        labels[fields.InputDataFields.groundtruth_boxes] is a [1, num_boxes, 4]
          float32 tensor containing the corners of the groundtruth boxes.
        labels[fields.InputDataFields.groundtruth_classes] is a
          [num_boxes, num_classes] float32 one-hot tensor of classes.
        labels[fields.InputDataFields.groundtruth_area] is a [1, num_boxes]
          float32 tensor containing object areas.
        labels[fields.InputDataFields.groundtruth_is_crowd] is a [1, num_boxes]
          bool tensor indicating if the boxes enclose a crowd.
        labels[fields.InputDataFields.groundtruth_difficult] is a [1, num_boxes]
          int32 tensor indicating if the boxes represent difficult instances.
        -- Optional --
        labels[fields.InputDataFields.groundtruth_instance_masks] is a
          [1, num_boxes, H, W] float32 tensor containing only binary values,
          which represent instance masks for objects.

    Raises:
      TypeError: if the `eval_config`, `eval_input_config` or `model_config`
        are not of the correct type.
    """
        del params
        if not isinstance(eval_config, eval_pb2.EvalConfig):
            raise TypeError('For eval mode, the `eval_config` must be a '
                            'train_pb2.EvalConfig.')
        if not isinstance(eval_input_config, input_reader_pb2.InputReader):
            raise TypeError('The `eval_input_config` must be a '
                            'input_reader_pb2.InputReader.')
        if not isinstance(model_config, model_pb2.DetectionModel):
            raise TypeError('The `model_config` must be a '
                            'model_pb2.DetectionModel.')

        num_classes = config_util.get_number_of_classes(model_config)
        model = model_builder.build(model_config, is_training=False)
        image_resizer_config = config_util.get_image_resizer_config(
            model_config)
        image_resizer_fn = image_resizer_builder.build(image_resizer_config)

        transform_data_fn = functools.partial(
            transform_input_data,
            model_preprocess_fn=model.preprocess,
            image_resizer_fn=image_resizer_fn,
            num_classes=num_classes,
            data_augmentation_fn=None,
            retain_original_image=True)
        dataset = dataset_builder.build(
            eval_input_config, transform_input_data_fn=transform_data_fn)
        input_dict = dataset_util.make_initializable_iterator(
            dataset).get_next()

        hash_from_source_id = tf.string_to_hash_bucket_fast(
            input_dict[fields.InputDataFields.source_id], HASH_BINS)
        features = {
            fields.InputDataFields.image:
            input_dict[fields.InputDataFields.image],
            fields.InputDataFields.original_image:
            input_dict[fields.InputDataFields.original_image],
            HASH_KEY:
            tf.cast(hash_from_source_id, tf.int32),
            fields.InputDataFields.true_image_shape:
            input_dict[fields.InputDataFields.true_image_shape]
        }

        labels = {
            fields.InputDataFields.groundtruth_boxes:
            input_dict[fields.InputDataFields.groundtruth_boxes],
            fields.InputDataFields.groundtruth_classes:
            input_dict[fields.InputDataFields.groundtruth_classes],
            fields.InputDataFields.groundtruth_area:
            input_dict[fields.InputDataFields.groundtruth_area],
            fields.InputDataFields.groundtruth_is_crowd:
            input_dict[fields.InputDataFields.groundtruth_is_crowd],
            fields.InputDataFields.groundtruth_difficult:
            tf.cast(input_dict[fields.InputDataFields.groundtruth_difficult],
                    tf.int32)
        }
        if fields.InputDataFields.groundtruth_instance_masks in input_dict:
            labels[fields.InputDataFields.
                   groundtruth_instance_masks] = input_dict[
                       fields.InputDataFields.groundtruth_instance_masks]

        # Add a batch dimension to the tensors.
        features = {
            key: tf.expand_dims(features[key], axis=0)
            for key, feature in features.items()
        }
        labels = {
            key: tf.expand_dims(labels[key], axis=0)
            for key, label in labels.items()
        }

        return features, labels
Exemple #30
0
 def test_create_faster_rcnn_resnet101_with_mask_prediction_enabled(self):
     model_text_proto = """
   faster_rcnn {
     num_classes: 3
     image_resizer {
       keep_aspect_ratio_resizer {
         min_dimension: 600
         max_dimension: 1024
       }
     }
     feature_extractor {
       type: 'faster_rcnn_resnet101'
     }
     first_stage_anchor_generator {
       grid_anchor_generator {
         scales: [0.25, 0.5, 1.0, 2.0]
         aspect_ratios: [0.5, 1.0, 2.0]
         height_stride: 16
         width_stride: 16
       }
     }
     first_stage_box_predictor_conv_hyperparams {
       regularizer {
         l2_regularizer {
         }
       }
       initializer {
         truncated_normal_initializer {
         }
       }
     }
     initial_crop_size: 14
     maxpool_kernel_size: 2
     maxpool_stride: 2
     second_stage_box_predictor {
       mask_rcnn_box_predictor {
         fc_hyperparams {
           op: FC
           regularizer {
             l2_regularizer {
             }
           }
           initializer {
             truncated_normal_initializer {
             }
           }
         }
         conv_hyperparams {
           regularizer {
             l2_regularizer {
             }
           }
           initializer {
             truncated_normal_initializer {
             }
           }
         }
         predict_instance_masks: true
       }
     }
     second_stage_mask_prediction_loss_weight: 3.0
     second_stage_post_processing {
       batch_non_max_suppression {
         score_threshold: 0.01
         iou_threshold: 0.6
         max_detections_per_class: 100
         max_total_detections: 300
       }
       score_converter: SOFTMAX
     }
   }"""
     model_proto = model_pb2.DetectionModel()
     text_format.Merge(model_text_proto, model_proto)
     model = model_builder.build(model_proto, is_training=True)
     self.assertAlmostEqual(model._second_stage_mask_loss_weight, 3.0)
Exemple #31
0
  def _eval_input_fn(params=None):
    """Returns `features` and `labels` tensor dictionaries for evaluation.

    Args:
      params: Parameter dictionary passed from the estimator.

    Returns:
      features: Dictionary of feature tensors.
        features[fields.InputDataFields.image] is a [1, H, W, C] float32 tensor
          with preprocessed images.
        features[HASH_KEY] is a [1] int32 tensor representing unique
          identifiers for the images.
        features[fields.InputDataFields.true_image_shape] is a [1, 3]
          int32 tensor representing the true image shapes, as preprocessed
          images could be padded.
        features[fields.InputDataFields.original_image] is a [1, H', W', C]
          float32 tensor with the original image.
      labels: Dictionary of groundtruth tensors.
        labels[fields.InputDataFields.groundtruth_boxes] is a [1, num_boxes, 4]
          float32 tensor containing the corners of the groundtruth boxes.
        labels[fields.InputDataFields.groundtruth_classes] is a
          [num_boxes, num_classes] float32 one-hot tensor of classes.
        labels[fields.InputDataFields.groundtruth_area] is a [1, num_boxes]
          float32 tensor containing object areas.
        labels[fields.InputDataFields.groundtruth_is_crowd] is a [1, num_boxes]
          bool tensor indicating if the boxes enclose a crowd.
        labels[fields.InputDataFields.groundtruth_difficult] is a [1, num_boxes]
          int32 tensor indicating if the boxes represent difficult instances.
        -- Optional --
        labels[fields.InputDataFields.groundtruth_instance_masks] is a
          [1, num_boxes, H, W] float32 tensor containing only binary values,
          which represent instance masks for objects.

    Raises:
      TypeError: if the `eval_config`, `eval_input_config` or `model_config`
        are not of the correct type.
    """
    params = params or {}
    if not isinstance(eval_config, eval_pb2.EvalConfig):
      raise TypeError('For eval mode, the `eval_config` must be a '
                      'train_pb2.EvalConfig.')
    if not isinstance(eval_input_config, input_reader_pb2.InputReader):
      raise TypeError('The `eval_input_config` must be a '
                      'input_reader_pb2.InputReader.')
    if not isinstance(model_config, model_pb2.DetectionModel):
      raise TypeError('The `model_config` must be a '
                      'model_pb2.DetectionModel.')

    num_classes = config_util.get_number_of_classes(model_config)
    model = model_builder.build(model_config, is_training=False)
    image_resizer_config = config_util.get_image_resizer_config(model_config)
    image_resizer_fn = image_resizer_builder.build(image_resizer_config)

    transform_data_fn = functools.partial(
        transform_input_data, model_preprocess_fn=model.preprocess,
        image_resizer_fn=image_resizer_fn,
        num_classes=num_classes,
        data_augmentation_fn=None,
        retain_original_image=eval_config.retain_original_images)
    dataset = INPUT_BUILDER_UTIL_MAP['dataset_build'](
        eval_input_config,
        transform_input_data_fn=transform_data_fn,
        batch_size=params.get('batch_size', 1),
        num_classes=config_util.get_number_of_classes(model_config),
        spatial_image_shape=config_util.get_spatial_image_size(
            image_resizer_config))
    input_dict = dataset_util.make_initializable_iterator(dataset).get_next()

    return (_get_features_dict(input_dict), _get_labels_dict(input_dict))
Exemple #32
0
    def _eval_input_fn(params=None):
        """Returns `features` and `labels` tensor dictionaries for evaluation.

    Args:
      params: Parameter dictionary passed from the estimator.

    Returns:
      features: Dictionary of feature tensors.
        features[fields.InputDataFields.image] is a [1, H, W, C] float32 tensor
          with preprocessed images.
        features[HASH_KEY] is a [1] int32 tensor representing unique
          identifiers for the images.
        features[fields.InputDataFields.true_image_shape] is a [1, 3]
          int32 tensor representing the true image shapes, as preprocessed
          images could be padded.
        features[fields.InputDataFields.original_image] is a [1, H', W', C]
          float32 tensor with the original image.
      labels: Dictionary of groundtruth tensors.
        labels[fields.InputDataFields.groundtruth_boxes] is a [1, num_boxes, 4]
          float32 tensor containing the corners of the groundtruth boxes.
        labels[fields.InputDataFields.groundtruth_classes] is a
          [num_boxes, num_classes] float32 one-hot tensor of classes.
        labels[fields.InputDataFields.groundtruth_area] is a [1, num_boxes]
          float32 tensor containing object areas.
        labels[fields.InputDataFields.groundtruth_is_crowd] is a [1, num_boxes]
          bool tensor indicating if the boxes enclose a crowd.
        labels[fields.InputDataFields.groundtruth_difficult] is a [1, num_boxes]
          int32 tensor indicating if the boxes represent difficult instances.
        -- Optional --
        labels[fields.InputDataFields.groundtruth_instance_masks] is a
          [1, num_boxes, H, W] float32 tensor containing only binary values,
          which represent instance masks for objects.

    Raises:
      TypeError: if the `eval_config`, `eval_input_config` or `model_config`
        are not of the correct type.
    """
        params = params or {}
        if not isinstance(eval_config, eval_pb2.EvalConfig):
            raise TypeError('For eval mode, the `eval_config` must be a '
                            'train_pb2.EvalConfig.')
        if not isinstance(eval_input_config, input_reader_pb2.InputReader):
            raise TypeError('The `eval_input_config` must be a '
                            'input_reader_pb2.InputReader.')
        if not isinstance(model_config, model_pb2.DetectionModel):
            raise TypeError('The `model_config` must be a '
                            'model_pb2.DetectionModel.')

        num_classes = config_util.get_number_of_classes(model_config)
        model = model_builder.build(model_config, is_training=False)
        image_resizer_config = config_util.get_image_resizer_config(
            model_config)
        image_resizer_fn = image_resizer_builder.build(image_resizer_config)

        transform_data_fn = functools.partial(
            transform_input_data,
            model_preprocess_fn=model.preprocess,
            image_resizer_fn=image_resizer_fn,
            num_classes=num_classes,
            data_augmentation_fn=None,
            retain_original_image=eval_config.retain_original_images)
        dataset = INPUT_BUILDER_UTIL_MAP['dataset_build'](
            eval_input_config,
            transform_input_data_fn=transform_data_fn,
            batch_size=params.get('batch_size', 1),
            num_classes=config_util.get_number_of_classes(model_config),
            spatial_image_shape=config_util.get_spatial_image_size(
                image_resizer_config))
        input_dict = dataset_util.make_initializable_iterator(
            dataset).get_next()

        return (_get_features_dict(input_dict), _get_labels_dict(input_dict))
def export_tflite_graph(pipeline_config, trained_checkpoint_prefix, output_dir,
                        add_postprocessing_op, max_detections,
                        max_classes_per_detection):
  """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


  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'
      ]),
      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)
  else:
    # Return frozen without adding post-processing custom op
    transformed_graph_def = frozen_graph_def

  binary_graph = os.path.join(output_dir, 'tflite_graph.pb')
  with tf.gfile.GFile(binary_graph, 'wb') as f:
    f.write(transformed_graph_def.SerializeToString())
  txt_graph = os.path.join(output_dir, 'tflite_graph.pbtxt')
  with tf.gfile.GFile(txt_graph, 'w') as f:
    f.write(str(transformed_graph_def))
Exemple #34
0
def train_loop(hparams,
               pipeline_config_path,
               model_dir,
               config_override=None,
               train_steps=None,
               use_tpu=False,
               save_final_config=False,
               export_to_tpu=None,
               checkpoint_every_n=1000,
               **kwargs):
    """Trains a model using eager + functions.

  This method:
    1. Processes the pipeline configs
    2. (Optionally) saves the as-run config
    3. Builds the model & optimizer
    4. Gets the training input data
    5. Loads a fine-tuning detection or classification checkpoint if requested
    6. Loops over the train data, executing distributed training steps inside
       tf.functions.
    7. Checkpoints the model every `checkpoint_every_n` training steps.
    8. Logs the training metrics as TensorBoard summaries.

  Args:
    hparams: A `HParams`.
    pipeline_config_path: A path to a pipeline config file.
    model_dir:
      The directory to save checkpoints and summaries to.
    config_override: A pipeline_pb2.TrainEvalPipelineConfig text proto to
      override the config from `pipeline_config_path`.
    train_steps: Number of training steps. If None, the number of training steps
      is set from the `TrainConfig` proto.
    use_tpu: Boolean, whether training and evaluation should run on TPU.
    save_final_config: Whether to save final config (obtained after applying
      overrides) to `model_dir`.
    export_to_tpu: When use_tpu and export_to_tpu are true,
      `export_savedmodel()` exports a metagraph for serving on TPU besides the
      one on CPU. If export_to_tpu is not provided, we will look for it in
      hparams too.
    checkpoint_every_n:
      Checkpoint every n training steps.
    **kwargs: Additional keyword arguments for configuration override.
  """
    ## Parse the configs
    get_configs_from_pipeline_file = MODEL_BUILD_UTIL_MAP[
        'get_configs_from_pipeline_file']
    merge_external_params_with_configs = MODEL_BUILD_UTIL_MAP[
        'merge_external_params_with_configs']
    create_pipeline_proto_from_configs = MODEL_BUILD_UTIL_MAP[
        'create_pipeline_proto_from_configs']

    configs = get_configs_from_pipeline_file(pipeline_config_path,
                                             config_override=config_override)
    kwargs.update({
        'train_steps':
        train_steps,
        'use_bfloat16':
        configs['train_config'].use_bfloat16 and use_tpu
    })
    configs = merge_external_params_with_configs(configs,
                                                 hparams,
                                                 kwargs_dict=kwargs)
    model_config = configs['model']
    train_config = configs['train_config']
    train_input_config = configs['train_input_config']

    unpad_groundtruth_tensors = train_config.unpad_groundtruth_tensors
    use_bfloat16 = train_config.use_bfloat16
    add_regularization_loss = train_config.add_regularization_loss
    clip_gradients_value = None
    if train_config.gradient_clipping_by_norm > 0:
        clip_gradients_value = train_config.gradient_clipping_by_norm

    # update train_steps from config but only when non-zero value is provided
    if train_steps is None and train_config.num_steps != 0:
        train_steps = train_config.num_steps

    # Read export_to_tpu from hparams if not passed.
    if export_to_tpu is None:
        export_to_tpu = hparams.get('export_to_tpu', False)
    tf.logging.info('train_loop: use_tpu %s, export_to_tpu %s', use_tpu,
                    export_to_tpu)

    # Parse the checkpoint fine tuning configs
    if hparams.load_pretrained:
        fine_tune_checkpoint_path = train_config.fine_tune_checkpoint
    else:
        fine_tune_checkpoint_path = None
    load_all_detection_checkpoint_vars = (
        train_config.load_all_detection_checkpoint_vars)
    # TODO(kaftan) (or anyone else): move this piece of config munging to
    ## utils/config_util.py
    if not train_config.fine_tune_checkpoint_type:
        # train_config.from_detection_checkpoint field is deprecated. For
        # backward compatibility, set train_config.fine_tune_checkpoint_type
        # based on train_config.from_detection_checkpoint.
        if train_config.from_detection_checkpoint:
            train_config.fine_tune_checkpoint_type = 'detection'
        else:
            train_config.fine_tune_checkpoint_type = 'classification'
    fine_tune_checkpoint_type = train_config.fine_tune_checkpoint_type

    # Write the as-run pipeline config to disk.
    if save_final_config:
        pipeline_config_final = create_pipeline_proto_from_configs(configs)
        config_util.save_pipeline_config(pipeline_config_final, model_dir)

    # TODO(kaftan): Either make strategy a parameter of this method, or
    ## grab it w/  Distribution strategy's get_scope
    # Build the model, optimizer, and training input
    strategy = tf.compat.v2.distribute.MirroredStrategy()
    with strategy.scope():
        detection_model = model_builder.build(model_config=model_config,
                                              is_training=True)

        # Create the inputs.
        train_input = inputs.train_input(train_config=train_config,
                                         train_input_config=train_input_config,
                                         model_config=model_config,
                                         model=detection_model)

        train_input = strategy.experimental_distribute_dataset(
            train_input.repeat())

        global_step = tf.compat.v2.Variable(0,
                                            trainable=False,
                                            dtype=tf.compat.v2.dtypes.int64)
        optimizer, (learning_rate, ) = optimizer_builder.build(
            train_config.optimizer, global_step=global_step)

        if callable(learning_rate):
            learning_rate_fn = learning_rate
        else:
            learning_rate_fn = lambda: learning_rate

    ## Train the model
    summary_writer = tf.compat.v2.summary.create_file_writer(model_dir +
                                                             '/train')
    with summary_writer.as_default():
        with strategy.scope():
            # Load a fine-tuning checkpoint.
            if fine_tune_checkpoint_path:
                load_fine_tune_checkpoint(
                    detection_model, fine_tune_checkpoint_path,
                    fine_tune_checkpoint_type,
                    load_all_detection_checkpoint_vars, train_input,
                    unpad_groundtruth_tensors, use_tpu, use_bfloat16)

            ckpt = tf.compat.v2.train.Checkpoint(step=global_step,
                                                 model=detection_model)
            manager = tf.compat.v2.train.CheckpointManager(ckpt,
                                                           model_dir,
                                                           max_to_keep=7)

            ## Maybe re-enable checkpoint restoration depending on how it works:
            # ckpt.restore(manager.latest_checkpoint)

            def train_step_fn(features, labels):
                return eager_train_step(
                    detection_model,
                    features,
                    labels,
                    unpad_groundtruth_tensors,
                    optimizer,
                    learning_rate=learning_rate_fn(),
                    use_bfloat16=use_bfloat16,
                    add_regularization_loss=add_regularization_loss,
                    clip_gradients_value=clip_gradients_value,
                    use_tpu=use_tpu,
                    global_step=global_step,
                    num_replicas=strategy.num_replicas_in_sync)

            @tf.function
            def _dist_train_step(data_iterator):
                """A distributed train step."""
                features, labels = data_iterator.next()
                per_replica_losses = strategy.experimental_run_v2(
                    train_step_fn, args=(
                        features,
                        labels,
                    ))
                # TODO(anjalisridhar): explore if it is safe to remove the
                ## num_replicas scaling of the loss and switch this to a ReduceOp.Mean
                mean_loss = strategy.reduce(tf.distribute.ReduceOp.SUM,
                                            per_replica_losses,
                                            axis=None)
                return mean_loss

            train_input_iter = iter(train_input)
            for _ in range(train_steps):
                start_time = time.time()

                loss = _dist_train_step(train_input_iter)
                global_step.assign_add(1)
                end_time = time.time()
                tf.compat.v2.summary.scalar('steps_per_sec',
                                            1.0 / (end_time - start_time),
                                            step=global_step)
                # TODO(kaftan): Remove this print after it is no longer helpful for
                ## debugging.
                tf.print('Finished step', global_step, end_time, loss)
                if int(global_step.value().numpy()) % checkpoint_every_n == 0:
                    manager.save()