def _assert_model_fn_for_train_eval(self, configs, mode, class_agnostic=False): model_config = configs['model'] train_config = configs['train_config'] with tf.Graph().as_default(): if mode == 'train': features, labels = _make_initializable_iterator( inputs.create_train_input_fn(configs['train_config'], configs['train_input_config'], configs['model'])()).get_next() model_mode = tf.estimator.ModeKeys.TRAIN batch_size = train_config.batch_size elif mode == 'eval': features, labels = _make_initializable_iterator( inputs.create_eval_input_fn(configs['eval_config'], configs['eval_input_config'], configs['model'])()).get_next() model_mode = tf.estimator.ModeKeys.EVAL batch_size = 1 elif mode == 'eval_on_train': features, labels = _make_initializable_iterator( inputs.create_eval_input_fn(configs['eval_config'], configs['train_input_config'], configs['model'])()).get_next() model_mode = tf.estimator.ModeKeys.EVAL batch_size = 1 detection_model_fn = functools.partial( model_builder.build, model_config=model_config, is_training=True) hparams = model_hparams.create_hparams( hparams_overrides='load_pretrained=false') model_fn = model_lib.create_model_fn(detection_model_fn, configs, hparams) estimator_spec = model_fn(features, labels, model_mode) self.assertIsNotNone(estimator_spec.loss) self.assertIsNotNone(estimator_spec.predictions) if mode == 'eval' or mode == 'eval_on_train': if class_agnostic: self.assertNotIn('detection_classes', estimator_spec.predictions) else: detection_classes = estimator_spec.predictions['detection_classes'] self.assertEqual(batch_size, detection_classes.shape.as_list()[0]) self.assertEqual(tf.float32, detection_classes.dtype) detection_boxes = estimator_spec.predictions['detection_boxes'] detection_scores = estimator_spec.predictions['detection_scores'] num_detections = estimator_spec.predictions['num_detections'] self.assertEqual(batch_size, detection_boxes.shape.as_list()[0]) self.assertEqual(tf.float32, detection_boxes.dtype) self.assertEqual(batch_size, detection_scores.shape.as_list()[0]) self.assertEqual(tf.float32, detection_scores.dtype) self.assertEqual(tf.float32, num_detections.dtype) if mode == 'eval': self.assertIn('Detections_Left_Groundtruth_Right/0', estimator_spec.eval_metric_ops) if model_mode == tf.estimator.ModeKeys.TRAIN: self.assertIsNotNone(estimator_spec.train_op) return estimator_spec
def _assert_model_fn_for_train_eval(self, configs, mode, class_agnostic=False): model_config = configs['model'] train_config = configs['train_config'] with tf.Graph().as_default(): if mode == 'train_bkp': features, labels = inputs.create_train_input_fn( configs['train_config'], configs['train_input_config'], configs['model'])() model_mode = tf.estimator.ModeKeys.TRAIN batch_size = train_config.batch_size elif mode == 'eval_bkp': features, labels = inputs.create_eval_input_fn( configs['eval_config'], configs['eval_input_config'], configs['model'])() model_mode = tf.estimator.ModeKeys.EVAL batch_size = 1 elif mode == 'eval_on_train': features, labels = inputs.create_eval_input_fn( configs['eval_config'], configs['train_input_config'], configs['model'])() model_mode = tf.estimator.ModeKeys.EVAL batch_size = 1 detection_model_fn = functools.partial(model_builder.build, model_config=model_config, is_training=True) hparams = model_hparams.create_hparams( hparams_overrides='load_pretrained=false') model_fn = model_lib.create_model_fn(detection_model_fn, configs, hparams) estimator_spec = model_fn(features, labels, model_mode) self.assertIsNotNone(estimator_spec.loss) self.assertIsNotNone(estimator_spec.predictions) if class_agnostic: self.assertNotIn('detection_classes', estimator_spec.predictions) else: detection_classes = estimator_spec.predictions[ 'detection_classes'] self.assertEqual(batch_size, detection_classes.shape.as_list()[0]) self.assertEqual(tf.float32, detection_classes.dtype) detection_boxes = estimator_spec.predictions['detection_boxes'] detection_scores = estimator_spec.predictions['detection_scores'] num_detections = estimator_spec.predictions['num_detections'] self.assertEqual(batch_size, detection_boxes.shape.as_list()[0]) self.assertEqual(tf.float32, detection_boxes.dtype) self.assertEqual(batch_size, detection_scores.shape.as_list()[0]) self.assertEqual(tf.float32, detection_scores.dtype) self.assertEqual(tf.float32, num_detections.dtype) if model_mode == tf.estimator.ModeKeys.TRAIN: self.assertIsNotNone(estimator_spec.train_op) return estimator_spec
def _assert_model_fn_for_predict(self, configs): model_config = configs['model'] with tf.Graph().as_default(): features, _ = _make_initializable_iterator( inputs.create_eval_input_fn(configs['eval_config'], configs['eval_input_config'], configs['model'])()).get_next() detection_model_fn = functools.partial(model_builder.build, model_config=model_config, is_training=False) hparams = model_hparams.create_hparams( hparams_overrides='load_pretrained=false') model_fn = model_lib.create_model_fn(detection_model_fn, configs, hparams) estimator_spec = model_fn(features, None, tf.estimator.ModeKeys.PREDICT) self.assertIsNone(estimator_spec.loss) self.assertIsNone(estimator_spec.train_op) self.assertIsNotNone(estimator_spec.predictions) self.assertIsNotNone(estimator_spec.export_outputs) self.assertIn( tf.saved_model.signature_constants.PREDICT_METHOD_NAME, estimator_spec.export_outputs)
def test_ssd_inceptionV2_eval_input(self, eval_batch_size=1): """Tests the eval input function for SSDInceptionV2.""" configs = _get_configs_for_model('ssd_inception_v2_pets') model_config = configs['model'] model_config.ssd.num_classes = 37 eval_config = configs['eval_config'] eval_config.batch_size = eval_batch_size eval_input_fn = inputs.create_eval_input_fn( eval_config, configs['eval_input_configs'][0], model_config) features, labels = _make_initializable_iterator( eval_input_fn()).get_next() self.assertAllEqual( [eval_batch_size, 300, 300, 3], features[fields.InputDataFields.image].shape.as_list()) self.assertEqual(tf.float32, features[fields.InputDataFields.image].dtype) self.assertAllEqual( [eval_batch_size, 300, 300, 3], features[fields.InputDataFields.original_image].shape.as_list()) self.assertEqual(tf.uint8, features[fields.InputDataFields.original_image].dtype) self.assertAllEqual([eval_batch_size], features[inputs.HASH_KEY].shape.as_list()) self.assertEqual(tf.int32, features[inputs.HASH_KEY].dtype) self.assertAllEqual( [eval_batch_size, 100, 4], labels[fields.InputDataFields.groundtruth_boxes].shape.as_list()) self.assertEqual( tf.float32, labels[fields.InputDataFields.groundtruth_boxes].dtype) self.assertAllEqual( [eval_batch_size, 100, model_config.ssd.num_classes], labels[fields.InputDataFields.groundtruth_classes].shape.as_list()) self.assertEqual( tf.float32, labels[fields.InputDataFields.groundtruth_classes].dtype) self.assertAllEqual( [eval_batch_size, 100, model_config.ssd.num_classes], labels[fields.InputDataFields. groundtruth_confidences].shape.as_list()) self.assertEqual( tf.float32, labels[fields.InputDataFields.groundtruth_confidences].dtype) self.assertAllEqual( [eval_batch_size, 100], labels[fields.InputDataFields.groundtruth_area].shape.as_list()) self.assertEqual(tf.float32, labels[fields.InputDataFields.groundtruth_area].dtype) self.assertAllEqual([ eval_batch_size, 100 ], labels[fields.InputDataFields.groundtruth_is_crowd].shape.as_list()) self.assertEqual( tf.bool, labels[fields.InputDataFields.groundtruth_is_crowd].dtype) self.assertAllEqual([eval_batch_size, 100], labels[ fields.InputDataFields.groundtruth_difficult].shape.as_list()) self.assertEqual( tf.int32, labels[fields.InputDataFields.groundtruth_difficult].dtype)
def test_error_with_bad_eval_model_config(self): """Tests that a TypeError is raised with improper eval model config.""" configs = _get_configs_for_model('ssd_inception_v2_pets') configs['model'].ssd.num_classes = 37 eval_input_fn = inputs.create_eval_input_fn( eval_config=configs['eval_config'], eval_input_config=configs['eval_input_config'], model_config=configs['eval_config']) # Expecting `DetectionModel`. with self.assertRaises(TypeError): eval_input_fn()
def test_faster_rcnn_resnet50_eval_input(self): """Tests the eval input function for FasterRcnnResnet50.""" configs = _get_configs_for_model('faster_rcnn_resnet50_pets') model_config = configs['model'] model_config.faster_rcnn.num_classes = 37 eval_input_fn = inputs.create_eval_input_fn( configs['eval_config'], configs['eval_input_configs'][0], model_config) features, labels = _make_initializable_iterator( eval_input_fn()).get_next() self.assertAllEqual( [1, None, None, 3], features[fields.InputDataFields.image].shape.as_list()) self.assertEqual(tf.float32, features[fields.InputDataFields.image].dtype) self.assertAllEqual( [1, None, None, 3], features[fields.InputDataFields.original_image].shape.as_list()) self.assertEqual(tf.uint8, features[fields.InputDataFields.original_image].dtype) self.assertAllEqual([1], features[inputs.HASH_KEY].shape.as_list()) self.assertEqual(tf.int32, features[inputs.HASH_KEY].dtype) self.assertAllEqual( [1, 100, 4], labels[fields.InputDataFields.groundtruth_boxes].shape.as_list()) self.assertEqual( tf.float32, labels[fields.InputDataFields.groundtruth_boxes].dtype) self.assertAllEqual( [1, 100, model_config.faster_rcnn.num_classes], labels[fields.InputDataFields.groundtruth_classes].shape.as_list()) self.assertEqual( tf.float32, labels[fields.InputDataFields.groundtruth_classes].dtype) self.assertAllEqual([1, 100, model_config.faster_rcnn.num_classes], labels[fields.InputDataFields. groundtruth_confidences].shape.as_list()) self.assertEqual( tf.float32, labels[fields.InputDataFields.groundtruth_confidences].dtype) self.assertAllEqual( [1, 100], labels[fields.InputDataFields.groundtruth_area].shape.as_list()) self.assertEqual(tf.float32, labels[fields.InputDataFields.groundtruth_area].dtype) self.assertAllEqual([ 1, 100 ], labels[fields.InputDataFields.groundtruth_is_crowd].shape.as_list()) self.assertEqual( tf.bool, labels[fields.InputDataFields.groundtruth_is_crowd].dtype) self.assertAllEqual([1, 100], labels[ fields.InputDataFields.groundtruth_difficult].shape.as_list()) self.assertEqual( tf.int32, labels[fields.InputDataFields.groundtruth_difficult].dtype)
def test_ssd_inceptionV2_eval_input(self, eval_batch_size=1): """Tests the eval input function for SSDInceptionV2.""" configs = _get_configs_for_model('ssd_inception_v2_pets') model_config = configs['model'] model_config.ssd.num_classes = 37 eval_config = configs['eval_config'] eval_config.batch_size = eval_batch_size eval_input_fn = inputs.create_eval_input_fn( eval_config, configs['eval_input_configs'][0], model_config) features, labels = _make_initializable_iterator(eval_input_fn()).get_next() self.assertAllEqual([eval_batch_size, 300, 300, 3], features[fields.InputDataFields.image].shape.as_list()) self.assertEqual(tf.float32, features[fields.InputDataFields.image].dtype) self.assertAllEqual( [eval_batch_size, 300, 300, 3], features[fields.InputDataFields.original_image].shape.as_list()) self.assertEqual(tf.uint8, features[fields.InputDataFields.original_image].dtype) self.assertAllEqual([eval_batch_size], features[inputs.HASH_KEY].shape.as_list()) self.assertEqual(tf.int32, features[inputs.HASH_KEY].dtype) self.assertAllEqual( [eval_batch_size, 100, 4], labels[fields.InputDataFields.groundtruth_boxes].shape.as_list()) self.assertEqual(tf.float32, labels[fields.InputDataFields.groundtruth_boxes].dtype) self.assertAllEqual( [eval_batch_size, 100, model_config.ssd.num_classes], labels[fields.InputDataFields.groundtruth_classes].shape.as_list()) self.assertEqual(tf.float32, labels[fields.InputDataFields.groundtruth_classes].dtype) self.assertAllEqual( [eval_batch_size, 100], labels[ fields.InputDataFields.groundtruth_weights].shape.as_list()) self.assertEqual( tf.float32, labels[fields.InputDataFields.groundtruth_weights].dtype) self.assertAllEqual( [eval_batch_size, 100], labels[fields.InputDataFields.groundtruth_area].shape.as_list()) self.assertEqual(tf.float32, labels[fields.InputDataFields.groundtruth_area].dtype) self.assertAllEqual( [eval_batch_size, 100], labels[fields.InputDataFields.groundtruth_is_crowd].shape.as_list()) self.assertEqual( tf.bool, labels[fields.InputDataFields.groundtruth_is_crowd].dtype) self.assertAllEqual( [eval_batch_size, 100], labels[fields.InputDataFields.groundtruth_difficult].shape.as_list()) self.assertEqual( tf.int32, labels[fields.InputDataFields.groundtruth_difficult].dtype)
def test_ssd_inceptionV2_eval_input(self): """Tests the eval input function for SSDInceptionV2.""" configs = _get_configs_for_model('ssd_inception_v2_pets') model_config = configs['model'] model_config.ssd.num_classes = 37 eval_input_fn = inputs.create_eval_input_fn( configs['eval_config'], configs['eval_input_config'], model_config) features, labels = eval_input_fn() self.assertAllEqual( [1, 300, 300, 3], features[fields.InputDataFields.image].shape.as_list()) self.assertEqual(tf.float32, features[fields.InputDataFields.image].dtype) self.assertAllEqual( [1, None, None, 3], features[fields.InputDataFields.original_image].shape.as_list()) self.assertEqual(tf.uint8, features[fields.InputDataFields.original_image].dtype) self.assertAllEqual([1], features[inputs.HASH_KEY].shape.as_list()) self.assertEqual(tf.int32, features[inputs.HASH_KEY].dtype) self.assertAllEqual( [1, None, 4], labels[fields.InputDataFields.groundtruth_boxes].shape.as_list()) self.assertEqual( tf.float32, labels[fields.InputDataFields.groundtruth_boxes].dtype) self.assertAllEqual( [1, None, model_config.ssd.num_classes], labels[fields.InputDataFields.groundtruth_classes].shape.as_list()) self.assertEqual( tf.float32, labels[fields.InputDataFields.groundtruth_classes].dtype) self.assertAllEqual( [1, None], labels[fields.InputDataFields.groundtruth_area].shape.as_list()) self.assertEqual(tf.float32, labels[fields.InputDataFields.groundtruth_area].dtype) self.assertAllEqual([ 1, None ], labels[fields.InputDataFields.groundtruth_is_crowd].shape.as_list()) self.assertEqual( tf.bool, labels[fields.InputDataFields.groundtruth_is_crowd].dtype) self.assertAllEqual([1, None], labels[ fields.InputDataFields.groundtruth_difficult].shape.as_list()) self.assertEqual( tf.int32, labels[fields.InputDataFields.groundtruth_difficult].dtype)
def _assert_outputs_for_train_eval(self, configs, mode, class_agnostic=False): model_config = configs['model'] train_config = configs['train_config'] with tf.Graph().as_default(): if mode == tf.estimator.ModeKeys.TRAIN: features, labels = inputs.create_train_input_fn( configs['train_config'], configs['train_input_config'], configs['model'])() batch_size = train_config.batch_size else: features, labels = inputs.create_eval_input_fn( configs['eval_config'], configs['eval_input_config'], configs['model'])() batch_size = 1 detection_model_fn = functools.partial( model_builder.build, model_config=model_config, is_training=True) hparams = model_hparams.create_hparams( hparams_overrides='load_pretrained=false') model_fn = model.create_model_fn(detection_model_fn, configs, hparams) estimator_spec = model_fn(features, labels, mode) self.assertIsNotNone(estimator_spec.loss) self.assertIsNotNone(estimator_spec.predictions) if class_agnostic: self.assertNotIn('detection_classes', estimator_spec.predictions) else: detection_classes = estimator_spec.predictions['detection_classes'] self.assertEqual(batch_size, detection_classes.shape.as_list()[0]) self.assertEqual(tf.float32, detection_classes.dtype) detection_boxes = estimator_spec.predictions['detection_boxes'] detection_scores = estimator_spec.predictions['detection_scores'] num_detections = estimator_spec.predictions['num_detections'] self.assertEqual(batch_size, detection_boxes.shape.as_list()[0]) self.assertEqual(tf.float32, detection_boxes.dtype) self.assertEqual(batch_size, detection_scores.shape.as_list()[0]) self.assertEqual(tf.float32, detection_scores.dtype) self.assertEqual(tf.float32, num_detections.dtype) if mode == tf.estimator.ModeKeys.TRAIN: self.assertIsNotNone(estimator_spec.train_op) return estimator_spec
def test_faster_rcnn_resnet50_eval_input(self): """Tests the eval input function for FasterRcnnResnet50.""" configs = _get_configs_for_model('faster_rcnn_resnet50_pets') model_config = configs['model'] model_config.faster_rcnn.num_classes = 37 eval_input_fn = inputs.create_eval_input_fn( configs['eval_config'], configs['eval_input_config'], model_config) features, labels = eval_input_fn() self.assertAllEqual([1, None, None, 3], features[fields.InputDataFields.image].shape.as_list()) self.assertEqual(tf.float32, features[fields.InputDataFields.image].dtype) self.assertAllEqual( [1, None, None, 3], features[fields.InputDataFields.original_image].shape.as_list()) self.assertEqual(tf.uint8, features[fields.InputDataFields.original_image].dtype) self.assertAllEqual([1], features[inputs.HASH_KEY].shape.as_list()) self.assertEqual(tf.int32, features[inputs.HASH_KEY].dtype) self.assertAllEqual( [1, None, 4], labels[fields.InputDataFields.groundtruth_boxes].shape.as_list()) self.assertEqual(tf.float32, labels[fields.InputDataFields.groundtruth_boxes].dtype) self.assertAllEqual( [1, None, model_config.faster_rcnn.num_classes], labels[fields.InputDataFields.groundtruth_classes].shape.as_list()) self.assertEqual(tf.float32, labels[fields.InputDataFields.groundtruth_classes].dtype) self.assertAllEqual( [1, None], labels[fields.InputDataFields.groundtruth_area].shape.as_list()) self.assertEqual(tf.float32, labels[fields.InputDataFields.groundtruth_area].dtype) self.assertAllEqual( [1, None], labels[fields.InputDataFields.groundtruth_is_crowd].shape.as_list()) self.assertEqual( tf.bool, labels[fields.InputDataFields.groundtruth_is_crowd].dtype) self.assertAllEqual( [1, None], labels[fields.InputDataFields.groundtruth_difficult].shape.as_list()) self.assertEqual( tf.int32, labels[fields.InputDataFields.groundtruth_difficult].dtype)
def _assert_model_fn_for_predict(self, configs): model_config = configs['model'] with tf.Graph().as_default(): features, _ = _make_initializable_iterator( inputs.create_eval_input_fn(configs['eval_config'], configs['eval_input_config'], configs['model'])()).get_next() detection_model_fn = functools.partial( model_builder.build, model_config=model_config, is_training=False) hparams = model_hparams.create_hparams( hparams_overrides='load_pretrained=false') model_fn = model_lib.create_model_fn(detection_model_fn, configs, hparams) estimator_spec = model_fn(features, None, tf.estimator.ModeKeys.PREDICT) self.assertIsNone(estimator_spec.loss) self.assertIsNone(estimator_spec.train_op) self.assertIsNotNone(estimator_spec.predictions) self.assertIsNotNone(estimator_spec.export_outputs) self.assertIn(tf.saved_model.signature_constants.PREDICT_METHOD_NAME, estimator_spec.export_outputs)
def populate_experiment(run_config, hparams, pipeline_config_path, train_steps=None, eval_steps=None, model_fn_creator=create_model_fn, **kwargs): """Populates an `Experiment` object. Args: run_config: A `RunConfig`. hparams: A `HParams`. pipeline_config_path: A path to a pipeline config file. train_steps: Number of training steps. If None, the number of training steps is set from the `TrainConfig` proto. eval_steps: Number of evaluation steps per evaluation cycle. If None, the number of evaluation steps is set from the `EvalConfig` proto. model_fn_creator: A function that creates a `model_fn` for `Estimator`. Follows the signature: * Args: * `detection_model_fn`: Function that returns `DetectionModel` instance. * `configs`: Dictionary of pipeline config objects. * `hparams`: `HParams` object. * Returns: `model_fn` for `Estimator`. **kwargs: Additional keyword arguments for configuration override. Returns: An `Experiment` that defines all aspects of training, evaluation, and export. """ configs = config_util.get_configs_from_pipeline_file(pipeline_config_path) configs = config_util.merge_external_params_with_configs( configs, hparams, train_steps=train_steps, eval_steps=eval_steps, **kwargs) model_config = configs['model'] train_config = configs['train_config'] train_input_config = configs['train_input_config'] eval_config = configs['eval_config'] eval_input_config = configs['eval_input_config'] if train_steps is None: train_steps = train_config.num_steps if train_config.num_steps else None if eval_steps is None: eval_steps = eval_config.num_examples if eval_config.num_examples else None detection_model_fn = functools.partial( model_builder.build, model_config=model_config) # Create the input functions for TRAIN/EVAL. train_input_fn = inputs.create_train_input_fn( train_config=train_config, train_input_config=train_input_config, model_config=model_config) eval_input_fn = inputs.create_eval_input_fn( eval_config=eval_config, eval_input_config=eval_input_config, model_config=model_config) export_strategies = [ tf.contrib.learn.utils.saved_model_export_utils.make_export_strategy( serving_input_fn=inputs.create_predict_input_fn( model_config=model_config)) ] estimator = tf.estimator.Estimator( model_fn=model_fn_creator(detection_model_fn, configs, hparams), config=run_config) if run_config.is_chief: # Store the final pipeline config for traceability. pipeline_config_final = config_util.create_pipeline_proto_from_configs( configs) pipeline_config_final_path = os.path.join(estimator.model_dir, 'pipeline.config') config_text = text_format.MessageToString(pipeline_config_final) with tf.gfile.Open(pipeline_config_final_path, 'wb') as f: tf.logging.info('Writing as-run pipeline config file to %s', pipeline_config_final_path) f.write(config_text) return tf.contrib.learn.Experiment( estimator=estimator, train_input_fn=train_input_fn, eval_input_fn=eval_input_fn, train_steps=train_steps, eval_steps=eval_steps, export_strategies=export_strategies, eval_delay_secs=120,)
def create_estimator(run_config, hparams, pipeline_config_path, train_steps=None, eval_steps=None, train_batch_size=None, model_fn_creator=model.create_model_fn, use_tpu=False, num_shards=1, params=None, **kwargs): """Creates an `Estimator` object. Args: run_config: A `RunConfig`. hparams: A `HParams`. pipeline_config_path: A path to a pipeline config file. train_steps: Number of training steps. If None, the number of training steps is set from the `TrainConfig` proto. eval_steps: Number of evaluation steps per evaluation cycle. If None, the number of evaluation steps is set from the `EvalConfig` proto. train_batch_size: Training batch size. If none, use batch size from `TrainConfig` proto. model_fn_creator: A function that creates a `model_fn` for `Estimator`. Follows the signature: * Args: * `detection_model_fn`: Function that returns `DetectionModel` instance. * `configs`: Dictionary of pipeline config objects. * `hparams`: `HParams` object. * Returns: `model_fn` for `Estimator`. use_tpu: Boolean, whether training and evaluation should run on TPU. num_shards: Number of shards (TPU cores). params: Parameter dictionary passed from the estimator. **kwargs: Additional keyword arguments for configuration override. Returns: Estimator: A estimator object used for training and evaluation train_input_fn: Input function for the training loop eval_validation_input_fn: Input function to run for evaluation on validation data. eval_training_input_fn: Input function to run for evaluation on training data. train_steps: Number of training steps either from arg `train_steps` or `TrainConfig` proto eval_steps: Number of evaluation steps either from arg `eval_steps` or `EvalConfig` proto """ configs = config_util.get_configs_from_pipeline_file(pipeline_config_path) configs = config_util.merge_external_params_with_configs( configs, hparams, train_steps=train_steps, eval_steps=eval_steps, batch_size=train_batch_size, **kwargs) model_config = configs['model'] train_config = configs['train_config'] train_input_config = configs['train_input_config'] eval_config = configs['eval_config'] eval_input_config = configs['eval_input_config'] if FLAGS.eval_training_data: eval_input_config = configs['train_input_config'] if params is None: params = {} if train_steps is None and train_config.num_steps: train_steps = train_config.num_steps if eval_steps is None and eval_config.num_examples: eval_steps = eval_config.num_examples detection_model_fn = functools.partial( model_builder.build, model_config=model_config) # Create the input functions for TRAIN/EVAL. train_input_fn = inputs.create_train_input_fn( train_config=train_config, train_input_config=train_input_config, model_config=model_config) eval_validation_input_fn = inputs.create_eval_input_fn( eval_config=eval_config, eval_input_config=eval_input_config, model_config=model_config) eval_training_input_fn = inputs.create_eval_input_fn( eval_config=eval_config, eval_input_config=train_input_config, model_config=model_config) estimator = tpu_estimator.TPUEstimator( model_fn=model_fn_creator(detection_model_fn, configs, hparams, use_tpu), train_batch_size=train_config.batch_size, # For each core, only batch size 1 is supported for eval. eval_batch_size=num_shards * 1 if use_tpu else 1, use_tpu=use_tpu, config=run_config, params=params) return (estimator, train_input_fn, eval_validation_input_fn, eval_training_input_fn, train_steps, eval_steps)
def update_odapi_model(tasks, estimator, data_dir, reverse_class_mapping_dict, odapi_configs, steps_per_epoch, export_dir, run_eval, eval_steps, temp_files_num): """Update the object detection api model with annotations from prodigy Arguments: tasks (iterable): prodigy's tasks estimator (tf.estimator.Estimator): detection model as tf estimator data_dir (str): directory to store temp train TF-Records reverse_class_mapping_dict (dict): key as class name and value as int odapi_configs (dict): Object detection api pipeline.config object steps_per_epoch (int): Number of training steps. export_dir (str): directory to export temp SavedModels for TF serving run_eval (bool): Whether to run evaluation eval_steps (int): Number of steps for evaluations temp_files_num (int): Number of recent files/folders to keep in export and data directories Returns: None if run_eval is False else evaluation loss (float) """ train_data_name = "{}_train.record".format(int(time())) num_examples = _write_tf_record( tasks=tasks, output_file=os.path.join(data_dir, train_data_name), reverse_class_mapping_dict=reverse_class_mapping_dict ) if num_examples == 0: log("No training data found! Skipping model update") return None train_input_config = odapi_configs["train_input_config"] # delete existing input paths old_input_paths = train_input_config.tf_record_input_reader.input_path for i in range(len(old_input_paths)): del train_input_config.tf_record_input_reader.input_path[i] train_input_config.tf_record_input_reader.input_path.append( os.path.join(data_dir, train_data_name )) train_input_fn = create_train_input_fn( train_config=odapi_configs["train_config"], model_config=odapi_configs["model"], train_input_config=train_input_config) train_steps = steps_per_epoch if train_steps in (0, -1): train_steps = num_examples log("Training for {} steps".format(train_steps)) estimator.train(input_fn=train_input_fn, steps=train_steps) _export_saved_model(export_dir, estimator, odapi_configs) # Keep only recent temp_files_num in temp dirs _remove_garbage(folder=export_dir, max_num_to_keep=temp_files_num, garbage_type="folder", filter_string=None) _remove_garbage(folder=data_dir, max_num_to_keep=temp_files_num, garbage_type="file", filter_string=".record") if run_eval: log("Running evaluation for {} steps".format(eval_steps)) eval_input_config = odapi_configs["eval_input_config"] eval_input_config.shuffle = False eval_input_config.num_readers = 1 eval_input_config.num_parallel_batches = 1 eval_input_config.num_prefetch_batches = -1 # autotune eval_input_config.queue_capacity = 2 eval_input_config.min_after_dequeue = 1 eval_input_config.read_block_length = 10 eval_input_config.prefetch_size = 2 eval_input_config.num_parallel_map_calls = 2 eval_input_function = create_eval_input_fn( eval_config=odapi_configs["eval_config"], eval_input_config=eval_input_config, model_config=odapi_configs["model"]) eval_dict = estimator.evaluate(input_fn=eval_input_function, steps=eval_steps) return eval_dict["loss"] else: return None
def populate_experiment(run_config, hparams, pipeline_config_path, train_steps=None, eval_steps=None, model_fn_creator=create_model_fn, **kwargs): configs = config_util.get_configs_from_pipeline_file(pipeline_config_path) configs = config_util.merge_external_params_with_configs( configs, hparams, train_steps=train_steps, eval_steps=eval_steps, **kwargs) model_config = configs['model'] train_config = configs['train_config'] train_input_config = configs['train_input_config'] eval_config = configs['eval_config'] eval_input_config = configs['eval_input_config'] if train_steps is None: train_steps = train_config.num_steps if train_config.num_steps else None if eval_steps is None: eval_steps = eval_config.num_examples if eval_config.num_examples else None detection_model_fn = functools.partial( model_builder.build, model_config=model_config) train_input_fn = inputs.create_train_input_fn( train_config=train_config, train_input_config=train_input_config, model_config=model_config) eval_input_fn = inputs.create_eval_input_fn( eval_config=eval_config, eval_input_config=eval_input_config, model_config=model_config) export_strategies = [ tf.contrib.learn.utils.saved_model_export_utils.make_export_strategy( serving_input_fn=inputs.create_predict_input_fn( model_config=model_config)) ] estimator = tf.estimator.Estimator( model_fn=model_fn_creator(detection_model_fn, configs, hparams), config=run_config) if run_config.is_chief: pipeline_config_final = config_util.create_pipeline_proto_from_configs( configs) pipeline_config_final_path = os.path.join(estimator.model_dir, 'pipeline.config') config_text = text_format.MessageToString(pipeline_config_final) with tf.gfile.Open(pipeline_config_final_path, 'wb') as f: tf.logging.info('Writing as-run pipeline config file to %s', pipeline_config_final_path) f.write(config_text) return tf.contrib.learn.Experiment( estimator=estimator, train_input_fn=train_input_fn, eval_input_fn=eval_input_fn, train_steps=train_steps, eval_steps=eval_steps, export_strategies=export_strategies, eval_delay_secs=120,)
def create_estimator(run_config, hparams, pipeline_config_path, train_steps=None, eval_steps=None, train_batch_size=None, model_fn_creator=model.create_model_fn, use_tpu=False, num_shards=1, params=None, **kwargs): """Creates an `Estimator` object. Args: run_config: A `RunConfig`. hparams: A `HParams`. pipeline_config_path: A path to a pipeline config file. train_steps: Number of training steps. If None, the number of training steps is set from the `TrainConfig` proto. eval_steps: Number of evaluation steps per evaluation cycle. If None, the number of evaluation steps is set from the `EvalConfig` proto. train_batch_size: Training batch size. If none, use batch size from `TrainConfig` proto. model_fn_creator: A function that creates a `model_fn` for `Estimator`. Follows the signature: * Args: * `detection_model_fn`: Function that returns `DetectionModel` instance. * `configs`: Dictionary of pipeline config objects. * `hparams`: `HParams` object. * Returns: `model_fn` for `Estimator`. use_tpu: Boolean, whether training and evaluation should run on TPU. num_shards: Number of shards (TPU cores). params: Parameter dictionary passed from the estimator. **kwargs: Additional keyword arguments for configuration override. Returns: Estimator: A estimator object used for training and evaluation train_input_fn: Input function for the training loop eval_input_fn: Input function for the evaluation run train_steps: Number of training steps either from arg `train_steps` or `TrainConfig` proto eval_steps: Number of evaluation steps either from arg `eval_steps` or `EvalConfig` proto """ configs = config_util.get_configs_from_pipeline_file(pipeline_config_path) configs = config_util.merge_external_params_with_configs( configs, hparams, train_steps=train_steps, eval_steps=eval_steps, batch_size=train_batch_size, **kwargs) model_config = configs['model'] train_config = configs['train_config'] train_input_config = configs['train_input_config'] eval_config = configs['eval_config'] eval_input_config = configs['eval_input_config'] if params is None: params = {} if train_steps is None: train_steps = train_config.num_steps if train_config.num_steps else None if eval_steps is None: eval_steps = eval_config.num_examples if eval_config.num_examples else None detection_model_fn = functools.partial( model_builder.build, model_config=model_config) # Create the input functions for TRAIN/EVAL. train_input_fn = inputs.create_train_input_fn( train_config=train_config, train_input_config=train_input_config, model_config=model_config) eval_input_fn = inputs.create_eval_input_fn( eval_config=eval_config, eval_input_config=eval_input_config, model_config=model_config) estimator = tpu_estimator.TPUEstimator( model_fn=model_fn_creator(detection_model_fn, configs, hparams, use_tpu), train_batch_size=train_config.batch_size, # For each core, only batch size 1 is supported for eval. eval_batch_size=num_shards * 1 if use_tpu else 1, use_tpu=use_tpu, config=run_config, params=params) return estimator, train_input_fn, eval_input_fn, train_steps, eval_steps