Beispiel #1
0
    def test_train_sequential_with_distribution_strategy(
            self, distribution, cloning):
        keras_model = simple_sequential_model()
        keras_model.compile(
            loss='categorical_crossentropy',
            metrics=[tf.keras.metrics.CategoricalAccuracy()],
            optimizer=tf.keras.optimizers.RMSprop(learning_rate=0.01),
            cloning=cloning)
        config = run_config_lib.RunConfig(tf_random_seed=_RANDOM_SEED,
                                          model_dir=self._base_dir,
                                          train_distribute=distribution)
        with self.cached_session():
            est_keras = keras_lib.model_to_estimator(keras_model=keras_model,
                                                     config=config)
            before_eval_results = est_keras.evaluate(
                input_fn=get_ds_test_input_fn, steps=1)
            est_keras.train(input_fn=get_ds_train_input_fn,
                            steps=_TRAIN_SIZE / 16)
            after_eval_results = est_keras.evaluate(
                input_fn=get_ds_test_input_fn, steps=1)
            self.assertLess(after_eval_results['loss'],
                            before_eval_results['loss'])

        tf.compat.v1.summary.FileWriterCache.clear()
        tf.compat.v1.gfile.DeleteRecursively(self._config.model_dir)
Beispiel #2
0
 def do_test_multi_inputs_multi_outputs_with_input_fn(
         self, distribution, train_input_fn, eval_input_fn):
     config = run_config_lib.RunConfig(tf_random_seed=_RANDOM_SEED,
                                       model_dir=self._base_dir,
                                       train_distribute=distribution)
     with self.cached_session():
         model = multi_inputs_multi_outputs_model()
         est_keras = keras_lib.model_to_estimator(keras_model=model,
                                                  config=config)
         baseline_eval_results = est_keras.evaluate(input_fn=eval_input_fn,
                                                    steps=1)
         est_keras.train(input_fn=train_input_fn, steps=_TRAIN_SIZE / 16)
         eval_results = est_keras.evaluate(input_fn=eval_input_fn, steps=1)
         self.assertLess(eval_results['loss'],
                         baseline_eval_results['loss'])
    def test_train_premade_linear_model(self):
        (x_train, y_train
         ), _, train_inp_fn, eval_inp_fn = get_resource_for_simple_model()

        linear_model = tf.keras.experimental.LinearModel(units=1)
        opt = tf.keras.optimizers.SGD(0.1)
        linear_model.compile(opt, 'mse', ['mse'])
        linear_model.fit(x_train, y_train, epochs=10)

        est = keras_lib.model_to_estimator(keras_model=linear_model,
                                           config=self._config,
                                           checkpoint_format='saver')
        before_eval_results = est.evaluate(input_fn=eval_inp_fn, steps=1)
        est.train(input_fn=train_inp_fn, steps=500)
        after_eval_results = est.evaluate(input_fn=eval_inp_fn, steps=1)
        self.assertLess(after_eval_results['loss'],
                        before_eval_results['loss'])
        self.assertLess(after_eval_results['loss'], 0.1)
    def test_train_premade_linear_model_with_dense_features(self):
        vocab_list = ['alpha', 'beta', 'gamma']
        vocab_val = [0.4, 0.6, 0.9]
        data = np.random.choice(vocab_list, size=256)
        y = np.zeros_like(data, dtype=np.float32)
        for vocab, val in zip(vocab_list, vocab_val):
            indices = np.where(data == vocab)
            y[indices] = val + np.random.uniform(
                low=-0.01, high=0.01, size=indices[0].shape)
        cat_column = tf.feature_column.categorical_column_with_vocabulary_list(
            key='symbol', vocabulary_list=vocab_list)
        ind_column = tf.feature_column.indicator_column(cat_column)
        keras_input = tf.keras.layers.Input(name='symbol',
                                            shape=3,
                                            dtype=tf.dtypes.string)
        feature_layer = tf.compat.v1.keras.layers.DenseFeatures([ind_column])
        h = feature_layer({'symbol': keras_input})
        linear_model = tf.keras.experimental.LinearModel(units=1)
        h = linear_model(h)

        model = tf.keras.models.Model(inputs=keras_input, outputs=h)
        opt = tf.keras.optimizers.SGD(0.1)
        model.compile(opt, 'mse', ['mse'])
        train_input_fn = numpy_io.numpy_input_fn(x={'symbol': data},
                                                 y=y,
                                                 num_epochs=20,
                                                 shuffle=False)
        eval_input_fn = numpy_io.numpy_input_fn(x={'symbol': data},
                                                y=y,
                                                num_epochs=20,
                                                shuffle=False)
        est = keras_lib.model_to_estimator(keras_model=model,
                                           config=self._config,
                                           checkpoint_format='saver')
        before_eval_results = est.evaluate(input_fn=eval_input_fn, steps=1)
        est.train(input_fn=train_input_fn, steps=30)
        after_eval_results = est.evaluate(input_fn=eval_input_fn, steps=1)
        self.assertLess(after_eval_results['loss'],
                        before_eval_results['loss'])
        self.assertLess(after_eval_results['loss'], 0.05)
Beispiel #5
0
def model_to_estimator(keras_model=None,
                       keras_model_path=None,
                       custom_objects=None,
                       model_dir=None,
                       config=None,
                       checkpoint_format='saver',
                       metric_names_map=None,
                       export_outputs=None):
    """Constructs an `Estimator` instance from given keras model.

  If you use infrastructure or other tooling that relies on Estimators, you can
  still build a Keras model and use model_to_estimator to convert the Keras
  model to an Estimator for use with downstream systems.

  For usage example, please see:
  [Creating estimators from Keras Models](
    https://www.tensorflow.org/guide/estimators#creating_estimators_from_keras_models).

  Sample Weights:
  Estimators returned by `model_to_estimator` are configured so that they can
  handle sample weights (similar to `keras_model.fit(x, y, sample_weights)`).

  To pass sample weights when training or evaluating the Estimator, the first
  item returned by the input function should be a dictionary with keys
  `features` and `sample_weights`. Example below:

  ```python
  keras_model = tf.keras.Model(...)
  keras_model.compile(...)

  estimator = tf.keras.estimator.model_to_estimator(keras_model)

  def input_fn():
    return dataset_ops.Dataset.from_tensors(
        ({'features': features, 'sample_weights': sample_weights},
         targets))

  estimator.train(input_fn, steps=1)
  ```

  Example with customized export signature:
  ```python
  inputs = {'a': tf.keras.Input(..., name='a'),
            'b': tf.keras.Input(..., name='b')}
  outputs = {'c': tf.keras.layers.Dense(..., name='c')(inputs['a']),
             'd': tf.keras.layers.Dense(..., name='d')(inputs['b'])}
  keras_model = tf.keras.Model(inputs, outputs)
  keras_model.compile(...)
  export_outputs = {'c': tf.estimator.export.RegressionOutput,
                    'd': tf.estimator.export.ClassificationOutput}

  estimator = tf.keras.estimator.model_to_estimator(
      keras_model, export_outputs=export_outputs)

  def input_fn():
    return dataset_ops.Dataset.from_tensors(
        ({'features': features, 'sample_weights': sample_weights},
         targets))

  estimator.train(input_fn, steps=1)
  ```

  Args:
    keras_model: A compiled Keras model object. This argument is mutually
      exclusive with `keras_model_path`. Estimator's `model_fn` uses the
      structure of the model to clone the model. Defaults to `None`.
    keras_model_path: Path to a compiled Keras model saved on disk, in HDF5
      format, which can be generated with the `save()` method of a Keras model.
      This argument is mutually exclusive with `keras_model`.
      Defaults to `None`.
    custom_objects: Dictionary for cloning customized objects. This is
      used with classes that is not part of this pip package. For example, if
      user maintains a `relu6` class that inherits from `tf.keras.layers.Layer`,
      then pass `custom_objects={'relu6': relu6}`. Defaults to `None`.
    model_dir: Directory to save `Estimator` model parameters, graph, summary
      files for TensorBoard, etc. If unset a directory will be created with
      `tempfile.mkdtemp`
    config: `RunConfig` to config `Estimator`. Allows setting up things in
      `model_fn` based on configuration such as `num_ps_replicas`, or
      `model_dir`. Defaults to `None`. If both `config.model_dir` and the
      `model_dir` argument (above) are specified the `model_dir` **argument**
      takes precedence.
    checkpoint_format: Sets the format of the checkpoint saved by the estimator
      when training. May be `saver` or `checkpoint`, depending on whether to
      save checkpoints from `tf.train.Saver` or `tf.train.Checkpoint`. This
      argument currently defaults to `saver`. When 2.0 is released, the default
      will be `checkpoint`. Estimators use name-based `tf.train.Saver`
      checkpoints, while Keras models use object-based checkpoints from
      `tf.train.Checkpoint`. Currently, saving object-based checkpoints from
      `model_to_estimator` is only supported by Functional and Sequential
      models. Defaults to 'saver'.
    metric_names_map: Optional dictionary mapping Keras model output metric
      names to custom names. This can be used to override the default Keras
      model output metrics names in a multi IO model use case and provide custom
      names for the `eval_metric_ops` in Estimator.
      The Keras model metric names can be obtained using `model.metrics_names`
      excluding any loss metrics such as total loss and output losses.
      For example, if your Keras model has two outputs `out_1` and `out_2`,
      with `mse` loss and `acc` metric, then `model.metrics_names` will be
      `['loss', 'out_1_loss', 'out_2_loss', 'out_1_acc', 'out_2_acc']`.
      The model metric names excluding the loss metrics will be
      `['out_1_acc', 'out_2_acc']`.
    export_outputs: Optional dictionary. This can be used to override the
      default Keras model output exports in a multi IO model use case and
      provide custom names for the `export_outputs` in
      `tf.estimator.EstimatorSpec`. Default is None, which is equivalent to
      {'serving_default': `tf.estimator.export.PredictOutput`}. If not None,
      the keys must match the keys of `model.output_names`.
      A dict `{name: output}` where:
        * name: An arbitrary name for this output.
        * output: an `ExportOutput` class such as `ClassificationOutput`,
          `RegressionOutput`, or `PredictOutput`. Single-headed models only need
          to specify one entry in this dictionary. Multi-headed models should
          specify one entry for each head, one of which must be named using
          `tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY`
          If no entry is provided, a default `PredictOutput` mapping to
          `predictions` will be created.

  Returns:
    An Estimator from given keras model.

  Raises:
    ValueError: If neither keras_model nor keras_model_path was given.
    ValueError: If both keras_model and keras_model_path was given.
    ValueError: If the keras_model_path is a GCS URI.
    ValueError: If keras_model has not been compiled.
    ValueError: If an invalid checkpoint_format was given.
  """

    try:
        from tensorflow_estimator.python.estimator import keras_lib  # pylint: disable=g-import-not-at-top
    except ImportError:
        raise NotImplementedError(
            'tf.keras.estimator.model_to_estimator function not available in your '
            'installation.')
    _model_to_estimator_usage_gauge.get_cell('v1').set(True)
    return keras_lib.model_to_estimator(  # pylint:disable=unexpected-keyword-arg
        keras_model=keras_model,
        keras_model_path=keras_model_path,
        custom_objects=custom_objects,
        model_dir=model_dir,
        config=config,
        checkpoint_format=checkpoint_format,
        use_v2_estimator=False,
        metric_names_map=metric_names_map,
        export_outputs=export_outputs)
    def test_train_premade_widedeep_model_with_feature_layers(self):
        vocab_list = ['alpha', 'beta', 'gamma']
        vocab_val = [0.4, 0.6, 0.9]
        data = np.random.choice(vocab_list, size=256)
        y = np.zeros_like(data, dtype=np.float32)
        for vocab, val in zip(vocab_list, vocab_val):
            indices = np.where(data == vocab)
            y[indices] = val + np.random.uniform(
                low=-0.01, high=0.01, size=indices[0].shape)
        cat_column = tf.feature_column.categorical_column_with_vocabulary_list(
            key='symbol', vocabulary_list=vocab_list)
        ind_column = tf.feature_column.indicator_column(cat_column)
        # TODO(tanzheny): use emb column for dense part once b/139667019 is fixed.
        # emb_column = feature_column.embedding_column(cat_column, dimension=5)
        keras_input = tf.keras.layers.Input(name='symbol',
                                            shape=3,
                                            dtype=tf.dtypes.string)

        # build linear part with feature layer.
        linear_feature_layer = tf.compat.v1.keras.layers.DenseFeatures(
            [ind_column])
        linear_model = tf.keras.experimental.LinearModel(
            units=1, name='Linear', kernel_initializer='zeros')
        combined_linear = tf.keras.models.Sequential(
            [linear_feature_layer, linear_model])

        # build dnn part with feature layer.
        dnn_feature_layer = tf.compat.v1.keras.layers.DenseFeatures(
            [ind_column])
        dense_layer = tf.keras.layers.Dense(units=1,
                                            name='DNNDense',
                                            kernel_initializer='zeros')
        combined_dnn = tf.keras.models.Sequential(
            [dnn_feature_layer, dense_layer])

        # build and compile wide deep.
        wide_deep_model = tf.keras.experimental.WideDeepModel(
            combined_linear, combined_dnn)
        wide_deep_model._set_inputs({'symbol': keras_input})
        sgd_opt = tf.keras.optimizers.SGD(0.1)
        adam_opt = tf.keras.optimizers.Adam(0.1)
        wide_deep_model.compile([sgd_opt, adam_opt], 'mse', ['mse'])

        # build estimator.
        train_input_fn = numpy_io.numpy_input_fn(x={'symbol': data},
                                                 y=y,
                                                 num_epochs=20,
                                                 shuffle=False)
        eval_input_fn = numpy_io.numpy_input_fn(x={'symbol': data},
                                                y=y,
                                                num_epochs=20,
                                                shuffle=False)
        est = keras_lib.model_to_estimator(keras_model=wide_deep_model,
                                           config=self._config,
                                           checkpoint_format='saver')

        before_eval_results = est.evaluate(input_fn=eval_input_fn, steps=1)
        est.train(input_fn=train_input_fn, steps=20)
        after_eval_results = est.evaluate(input_fn=eval_input_fn, steps=1)
        self.assertLess(after_eval_results['loss'],
                        before_eval_results['loss'])
        self.assertLess(after_eval_results['loss'], 0.1)