def test_custom_objects(self): def custom_relu(x): return tf.keras.backend.relu(x, max_value=6) keras_model = simple_functional_model(activation=custom_relu) keras_model.compile(loss='categorical_crossentropy', optimizer='adam') custom_objects = {'custom_relu': custom_relu} (x_train, y_train), _ = get_test_data( train_samples=_TRAIN_SIZE, test_samples=50, input_shape=(10,), num_classes=2) y_train = tf.keras.utils.to_categorical(y_train, 2) input_name = keras_model.input_names[0] output_name = keras_model.output_names[0] train_input_fn = gen_input_fn( x=randomize_io_type(x_train, input_name), y=randomize_io_type(y_train, output_name), shuffle=False, num_epochs=None, batch_size=16) with self.assertRaisesRegex(ValueError, 'custom_relu'): est = keras_lib.model_to_estimator( keras_model=keras_model, model_dir=tempfile.mkdtemp(dir=self._base_dir)) est.train(input_fn=train_input_fn, steps=1) est = keras_lib.model_to_estimator( keras_model=keras_model, model_dir=tempfile.mkdtemp(dir=self._base_dir), custom_objects=custom_objects) est.train(input_fn=train_input_fn, steps=1)
def test_invalid_metric_names_map(self): keras_model, (_, _), (_, _), _, eval_input_fn = get_resource_for_simple_model( model_type='functional', is_evaluate=True) keras_model.compile( loss='categorical_crossentropy', optimizer='adam', metrics=['binary_accuracy']) keras_est = keras_lib.model_to_estimator( keras_model=keras_model, config=self._config, metric_names_map={'binary_acc': ''}) with self.assertRaisesRegexp(ValueError, r'Invalid `metric_names_map`.*do not exist'): keras_est.evaluate(input_fn=eval_input_fn) keras_est = keras_lib.model_to_estimator( keras_model=keras_model, config=self._config, metric_names_map={ 'binary_accuracy': 'acc', 'abcde': '' }) with self.assertRaisesRegexp( ValueError, r'Invalid `metric_names_map`.*unexpected keys'): keras_est.evaluate(input_fn=eval_input_fn)
def test_with_empty_config(self): keras_model, _, _, _, _ = get_resource_for_simple_model( model_type='sequential', is_evaluate=True) keras_model.compile( loss='categorical_crossentropy', optimizer='rmsprop', metrics=['mse', keras.metrics.CategoricalAccuracy()]) est_keras = keras_lib.model_to_estimator( keras_model=keras_model, model_dir=self._base_dir, config=run_config_lib.RunConfig()) self.assertEqual(run_config_lib.get_default_session_config(), est_keras._session_config) self.assertEqual(est_keras._session_config, est_keras._config.session_config) self.assertEqual(self._base_dir, est_keras._config.model_dir) self.assertEqual(self._base_dir, est_keras._model_dir) est_keras = keras_lib.model_to_estimator( keras_model=keras_model, model_dir=self._base_dir, config=None) self.assertEqual(run_config_lib.get_default_session_config(), est_keras._session_config) self.assertEqual(est_keras._session_config, est_keras._config.session_config) self.assertEqual(self._base_dir, est_keras._config.model_dir) self.assertEqual(self._base_dir, est_keras._model_dir)
def test_sample_weights(self): # Create simple pass-through model input_layer = keras.layers.Input(shape=1, name='input_layer') keras_model = keras.Model(inputs=input_layer, outputs=input_layer) keras_model.compile(loss='mean_absolute_error', optimizer='adam') features = [[0.], [0], [1], [1]] sample_weights = [0, .4, 1, 1] targets = [[0], [1], [0], [1]] expected_loss = keras_model.test_on_batch( array_ops.constant(features), array_ops.constant(targets), array_ops.constant(sample_weights)) def input_fn(): dataset = dataset_ops.Dataset.from_tensors(({ 'features': features, 'sample_weights': sample_weights }, targets)) return dataset est_keras = keras_lib.model_to_estimator( keras_model=keras_model, model_dir=tempfile.mkdtemp(dir=self._base_dir)) eval_results = est_keras.evaluate(input_fn, steps=1) self.assertAllClose(expected_loss, eval_results['loss']) # Test multiple with outputs and sample weights. keras_model = keras.Model(inputs=input_layer, outputs=[input_layer, input_layer]) keras_model.compile(loss='mean_absolute_error', optimizer='adam') expected_loss = keras_model.test_on_batch( array_ops.constant(features), [array_ops.constant(targets), array_ops.constant(targets)], [ array_ops.constant(sample_weights), array_ops.constant(sample_weights) ])[0] def input_fn_multiple_targets(): dataset = dataset_ops.Dataset.from_tensors( (features, sample_weights, targets)) dataset = dataset.map(lambda x, y, z: ({ 'features': x, 'sample_weights': (y, y) }, (z, z))) return dataset est_keras = keras_lib.model_to_estimator( keras_model=keras_model, model_dir=tempfile.mkdtemp(dir=self._base_dir)) eval_results = est_keras.evaluate(input_fn_multiple_targets, steps=1) self.assertAllClose(expected_loss, eval_results['loss'])
def test_with_conflicting_model_dir_and_config(self): keras_model, _, _, _, _ = get_resource_for_simple_model( model_type='sequential', is_evaluate=True) keras_model.compile( loss='categorical_crossentropy', optimizer='rmsprop', metrics=['mse', keras.metrics.CategoricalAccuracy()]) with self.assertRaisesRegexp( ValueError, '`model_dir` are set both in ' 'constructor and `RunConfig`'): keras_lib.model_to_estimator( keras_model=keras_model, model_dir=self._base_dir, config=run_config_lib.RunConfig(model_dir=_TMP_DIR))
def test_train_with_dense_features(self): feature_dict = { 'sex': np.int64([1, 1, 1, 1, 0]), 'cp': np.int64([0, 3, 3, 2, 1]), 'slope': np.int64([3, 2, 0, 3, 1]), } label = np.int64([0, 1, 0, 0, 0]) train_input_fn = numpy_io.numpy_input_fn(x=feature_dict, y=label, num_epochs=1, shuffle=False) feature_columns = list() input_features = dict() for feature_name, data_array in feature_dict.items(): feature_columns.append( feature_column.indicator_column( feature_column.categorical_column_with_identity( key=feature_name, num_buckets=np.size(np.unique(data_array))))) input_features[feature_name] = keras.layers.Input( name=feature_name, shape=(np.size(np.unique(data_array)), ), dtype=dtypes.int64) x = feature_column.DenseFeatures(feature_columns)(input_features) x = keras.layers.Dense(16, activation='relu')(x) logits = keras.layers.Dense(1, activation='linear')(x) model = keras.Model(inputs=input_features, outputs=logits) model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy']) estimator_model = keras_lib.model_to_estimator(keras_model=model) estimator_model.train(input_fn=train_input_fn, steps=5)
def test_train_with_tf_optimizer(self): for model_type in ['sequential', 'functional']: keras_model, (_, _), ( _, _ ), train_input_fn, eval_input_fn = get_resource_for_simple_model( model_type=model_type, is_evaluate=True) keras_model.compile( loss='categorical_crossentropy', optimizer=rmsprop.RMSPropOptimizer(1e-3), metrics=['mse', keras.metrics.CategoricalAccuracy()]) with self.cached_session(): est_keras = keras_lib.model_to_estimator( keras_model=keras_model, config=self._config) before_eval_results = est_keras.evaluate( input_fn=eval_input_fn, steps=1) est_keras.train(input_fn=train_input_fn, steps=_TRAIN_SIZE / 16) after_eval_results = est_keras.evaluate(input_fn=eval_input_fn, steps=1) self.assertLess(after_eval_results['loss'], before_eval_results['loss']) writer_cache.FileWriterCache.clear() gfile.DeleteRecursively(self._config.model_dir)
def test_warm_start_from_keras_ckpt(self): keras_model, (x_train, y_train), ( _, _), train_input_fn, eval_input_fn = get_resource_for_simple_model( model_type='functional', is_evaluate=True) keras_model.compile(optimizer=rmsprop.RMSPropOptimizer(1e-3), loss='categorical_crossentropy', metrics=['accuracy']) keras_model.fit(x_train, y_train, epochs=1) warm_start_path = os.path.join(self._config.model_dir, 'keras', 'warm_start.ckpt') keras_model.save_weights(warm_start_path) est_keras = keras_lib.model_to_estimator(keras_model=keras_model, config=self._config, checkpoint_format='saver') self.assertEqual( warm_start_path, est_keras._warm_start_settings.ckpt_to_initialize_from) before_eval_results = est_keras.evaluate(input_fn=eval_input_fn, steps=1) est_keras.train(input_fn=train_input_fn, steps=_TRAIN_SIZE / 16) after_eval_results = est_keras.evaluate(input_fn=eval_input_fn, steps=1) self.assertLess(after_eval_results['loss'], before_eval_results['loss'])
def test_gpu_config(self): with tf.Graph().as_default(): keras_model, (_, _), (_, _), _, _ = get_resource_for_simple_model() keras_model.compile( loss='categorical_crossentropy', optimizer='rmsprop', metrics=['mse', keras.metrics.CategoricalAccuracy()]) gpu_options = config_pb2.GPUOptions(per_process_gpu_memory_fraction=0.3) sess_config = config_pb2.ConfigProto(gpu_options=gpu_options) self._config._session_config = sess_config keras_lib.model_to_estimator(keras_model=keras_model, config=self._config) self.assertEqual( keras.backend.get_session( )._config.gpu_options.per_process_gpu_memory_fraction, gpu_options.per_process_gpu_memory_fraction)
def test_invalid_ionames_error(self): (x_train, y_train), (_, _) = testing_utils.get_test_data( train_samples=_TRAIN_SIZE, test_samples=100, input_shape=(10,), num_classes=2) y_train = np_utils.to_categorical(y_train) def invald_input_name_input_fn(): input_dict = {'invalid_input_name': x_train} return input_dict, y_train def invald_output_name_input_fn(): input_dict = {'input_layer': x_train} output_dict = {'invalid_output_name': y_train} return input_dict, output_dict model = simple_functional_model() model.compile( loss='categorical_crossentropy', optimizer='adam', metrics=['acc']) est_keras = keras_lib.model_to_estimator( keras_model=model, config=self._config) regexp_pattern = r'{} keys:(\s|.)*{}(\s|.)*Missed keys:(\s|.)*{}' with self.assertRaisesRegexp( keras_lib.FormattedKeyError, regexp_pattern.format('features', 'invalid_input_name', 'input_layer')): est_keras.train(input_fn=invald_input_name_input_fn, steps=100) with self.assertRaisesRegexp( keras_lib.FormattedKeyError, regexp_pattern.format('labels', 'invalid_output_name', 'dense_1')): est_keras.train(input_fn=invald_output_name_input_fn, steps=100)
def test_init_from_file(self): if h5py is None: return # Skip test if models cannot be saved. keras_model, (x_train, y_train), ( x_test, _), _, pred_input_fn = get_resource_for_simple_model( model_type='functional', is_evaluate=False) with self.cached_session(): keras_model.compile( loss='categorical_crossentropy', optimizer='rmsprop', metrics=['categorical_accuracy']) keras_model.fit(x_train, y_train, epochs=1) keras_pred = [np.argmax(y) for y in keras_model.predict(x_test)] fname = os.path.join(self._base_dir, 'keras_model.h5') keras.models.save_model(keras_model, fname) with self.cached_session(): keras_est = keras_lib.model_to_estimator( keras_model_path=fname, config=self._config) est_pred = [ np.argmax(y[keras_model.output_names[0]]) for y in keras_est.predict(input_fn=pred_input_fn) ] self.assertAllEqual(est_pred, keras_pred)
def test_invalid_ionames_error(self): (x_train, y_train), (_, _) = testing_utils.get_test_data( train_samples=_TRAIN_SIZE, test_samples=100, input_shape=(10,), num_classes=2) y_train = keras.utils.to_categorical(y_train) def invald_input_name_input_fn(): input_dict = {'invalid_input_name': x_train} return input_dict, y_train def invald_output_name_input_fn(): input_dict = {'input_1': x_train} output_dict = {'invalid_output_name': y_train} return input_dict, output_dict model = simple_functional_model() model.compile( loss='categorical_crossentropy', optimizer='adam', metrics=['acc']) est_keras = keras_lib.model_to_estimator( keras_model=model, config=self._config) with self.assertRaisesRegexp(KeyError, 'Difference: .*invalid_input_name'): est_keras.train(input_fn=invald_input_name_input_fn, steps=100) with self.assertRaisesRegexp(KeyError, 'Difference: .*invalid_output_name'): est_keras.train(input_fn=invald_output_name_input_fn, steps=100)
def test_train_keras_estimator( self, model_type, checkpoint_format=None, fit_before_export=False, optimizer='rmsprop', hook=None): hooks = [hook()] if hook else None tf_optimizer = False if optimizer == 'tf_rmsprop': tf_optimizer = True optimizer = rmsprop.RMSPropOptimizer(1e-3) keras_model, (x_train, y_train), (_, _), train_input_fn, eval_input_fn = ( get_resource_for_simple_model(model_type=model_type, is_evaluate=True)) keras_model.compile( optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy']) if fit_before_export: keras_model.fit(x_train, y_train, epochs=1) est_keras = keras_lib.model_to_estimator( keras_model=keras_model, config=self._config, checkpoint_format=checkpoint_format) est_keras.train(input_fn=train_input_fn, steps=_TRAIN_SIZE / 16, hooks=hooks) before_eval_results = est_keras.evaluate(input_fn=eval_input_fn, steps=1) est_keras.train(input_fn=train_input_fn, steps=_TRAIN_SIZE / 16, hooks=hooks) after_eval_results = est_keras.evaluate(input_fn=eval_input_fn, steps=1) self.assertLess(after_eval_results['loss'], before_eval_results['loss']) if checkpoint_format == 'object' and tf_optimizer: latest_checkpoint = checkpoint_management.latest_checkpoint( est_keras.model_dir) keras_model.load_weights(latest_checkpoint)
def test_train_sequential_with_distribution_strategy( self, distribution, cloning): keras_model = simple_sequential_model() keras_model.compile( loss='categorical_crossentropy', metrics=[keras.metrics.CategoricalAccuracy()], optimizer=rmsprop_keras.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']) writer_cache.FileWriterCache.clear() gfile.DeleteRecursively(self._config.model_dir)
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 = keras.layers.Input(name='symbol', shape=3, dtype=tf.dtypes.string) # build linear part with feature layer. linear_feature_layer = dense_features.DenseFeatures([ind_column]) linear_model = linear.LinearModel(units=1, name='Linear', kernel_initializer='zeros') combined_linear = keras.Sequential( [linear_feature_layer, linear_model]) # build dnn part with feature layer. dnn_feature_layer = dense_features.DenseFeatures([ind_column]) dense_layer = keras.layers.Dense(units=1, name='DNNDense', kernel_initializer='zeros') combined_dnn = keras.Sequential([dnn_feature_layer, dense_layer]) # build and compile wide deep. wide_deep_model = wide_deep.WideDeepModel(combined_linear, combined_dnn) wide_deep_model._set_inputs({'symbol': keras_input}) sgd_opt = gradient_descent.SGD(0.1) adam_opt = adam.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)
def test_train_with_subclassed_model_with_existing_state(self): keras_model, (_, _), ( _, _), train_input_fn, eval_input_fn = get_resource_for_simple_model( model_type='subclass', is_evaluate=True) keras_model.compile( loss='categorical_crossentropy', optimizer=rmsprop.RMSPropOptimizer(1e-3), metrics=['mse', keras.metrics.CategoricalAccuracy()]) with self.cached_session(): # Create state keras_model.train_on_batch(np.random.random((10, ) + _INPUT_SIZE), np.random.random((10, _NUM_CLASS))) original_preds = keras_model.predict(np.ones((10, ) + _INPUT_SIZE)) est_keras = keras_lib.model_to_estimator(keras_model=keras_model, config=self._config) est_keras.train(input_fn=train_input_fn, steps=_TRAIN_SIZE / 16) before_eval_results = est_keras.evaluate(input_fn=eval_input_fn, steps=1) est_keras.train(input_fn=train_input_fn, steps=_TRAIN_SIZE / 16) after_eval_results = est_keras.evaluate(input_fn=eval_input_fn, steps=1) self.assertLess(after_eval_results['loss'], before_eval_results['loss'])
def test_pretrained_weights(self): keras_model, (_, _), (_, _), _, _ = get_resource_for_simple_model() keras_model.compile( loss='categorical_crossentropy', optimizer=rmsprop.RMSPropOptimizer(1e-3), metrics=['mse', keras.metrics.CategoricalAccuracy()]) keras_model.train_on_batch( np.random.random((10,) + _INPUT_SIZE), np.random.random((10, _NUM_CLASS))) weights = keras_model.get_weights() keras_model, (_, _), (_, _), _, _ = get_resource_for_simple_model() keras_model.set_weights(weights) keras_model.compile( loss='categorical_crossentropy', optimizer=SGD(lr=0.0001, momentum=0.9), metrics=['mse', keras.metrics.CategoricalAccuracy()]) keras_lib.model_to_estimator(keras_model=keras_model, config=self._config)
def test_model_to_estimator_with_rnn(self, layer): # See https://github.com/tensorflow/tensorflow/issues/27750 for details. timestep = 10 rnn_cell_size = 8 layers = [ keras.layers.Reshape([timestep, 1], input_shape=[timestep,]), layer(rnn_cell_size, return_sequences=True), layer(rnn_cell_size), keras.layers.Dense(1) ] model = keras.Sequential(layers) model.compile(loss='mse', optimizer='sgd') keras_lib.model_to_estimator( keras_model=model, checkpoint_format='checkpoint', model_dir=tempfile.mkdtemp(dir=self._base_dir))
def model_to_estimator( keras_model=None, keras_model_path=None, custom_objects=None, model_dir=None, config=None): """Constructs an `Estimator` instance from given keras model. For usage example, please see: [Creating estimators from Keras Models](https://tensorflow.org/guide/estimators#model_to_estimator). Args: keras_model: A compiled Keras model object. This argument is mutually exclusive with `keras_model_path`. 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`. custom_objects: Dictionary for custom objects. model_dir: Directory to save `Estimator` model parameters, graph, summary files for TensorBoard, etc. config: `RunConfig` to config `Estimator`. 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. """ try: from tensorflow_estimator.python.estimator import keras as 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.') keras_lib.model_to_estimator( keras_model=keras_model, keras_model_path=keras_model_path, custom_objects=custom_objects, model_dir=model_dir, config=config)
def train_loop(model_name, model_fn, input_fn, loss_fn): # Early exit, do not import tensorflow as early here. if FLAGS.task is None: raise UsageError('flag --task must be defined in distributed mode.') if FLAGS.taskindex is None: raise UsageError( 'flag --taskindex must be defined in distributed mode.') # We are good to go here import tensorflow as tf from tensorflow_estimator.python.estimator import keras as keras_est with open(FLAGS.configfile) as f: configs = yaml.load(f.read(), Loader=yaml.SafeLoader) # type: dict tf_config = { 'cluster': configs['cluster'], 'task': { 'type': FLAGS.task, 'index': FLAGS.taskindex } } os.environ['TF_CONFIG'] = json.dumps(tf_config) hooks = [] if FLAGS.step_counter_freq: hooks.append( tf.estimator.StepCounterHook( every_n_steps=FLAGS.step_counter_freq)) # Prepare distributed strategy strategy = tf.distribute.experimental.MultiWorkerMirroredStrategy() config = tf.estimator.RunConfig( tf_random_seed=FLAGS.tf_random_seed, train_distribute=strategy, eval_distribute=strategy, model_dir=FLAGS.model_dir, save_checkpoints_steps=FLAGS.save_checkpoints_freq) model = model_fn() model.compile(loss=loss_fn, optimizer=tf.compat.v1.train.AdamOptimizer( FLAGS.learning_rate)) classifier = keras_est.model_to_estimator(keras_model=model, config=config) train_spec = tf.estimator.TrainSpec(input_fn=input_fn, hooks=hooks) eval_spec = tf.estimator.EvalSpec(input_fn=input_fn) try: tf.estimator.train_and_evaluate(classifier, train_spec=train_spec, eval_spec=eval_spec) except KeyboardInterrupt: return
def model_to_estimator( keras_model=None, keras_model_path=None, custom_objects=None, model_dir=None, config=None, checkpoint_format='saver'): """Constructs an `Estimator` instance from given keras model. For usage example, please see: [Creating estimators from Keras Models](https://tensorflow.org/guide/estimators#model_to_estimator). Args: keras_model: A compiled Keras model object. This argument is mutually exclusive with `keras_model_path`. 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`. custom_objects: Dictionary for custom objects. model_dir: Directory to save `Estimator` model parameters, graph, summary files for TensorBoard, etc. config: `RunConfig` to config `Estimator`. 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. 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 as 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.') 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)
def do_test_multi_inputs_multi_outputs_with_input_fn( self, train_input_fn, eval_input_fn, pred_input_fn): model = multi_inputs_multi_outputs_model() est_keras = keras_lib.model_to_estimator( keras_model=model, config=self._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']) est_keras.predict(input_fn=pred_input_fn)
def test_with_empty_config_and_empty_model_dir(self): keras_model, _, _, _, _ = get_resource_for_simple_model( model_type='sequential', is_evaluate=True) keras_model.compile( loss='categorical_crossentropy', optimizer='rmsprop', metrics=['mse', keras.metrics.CategoricalAccuracy()]) with test.mock.patch.object(tempfile, 'mkdtemp', return_value=_TMP_DIR): est_keras = keras_lib.model_to_estimator( keras_model=keras_model, config=run_config_lib.RunConfig()) self.assertEqual(est_keras._model_dir, _TMP_DIR)
def test_tf_config(self): keras_model, (_, _), (_, _), _, _ = get_resource_for_simple_model() keras_model.compile( loss='categorical_crossentropy', optimizer='rmsprop', metrics=['mse', keras.metrics.CategoricalAccuracy()]) tf_config = json.dumps({ 'cluster': { run_config_lib.TaskType.PS: ['localhost:1234'], run_config_lib.TaskType.WORKER: ['localhost:1236'], run_config_lib.TaskType.MASTER: ['localhost:1238'] }, 'task': { 'type': run_config_lib.TaskType.MASTER, 'index': 0 } }) with test.mock.patch.dict('os.environ', {'TF_CONFIG': tf_config}): keras_lib.model_to_estimator( keras_model=keras_model, model_dir=tempfile.mkdtemp(dir=self._base_dir))
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_with_subclassed_model(self): keras_model, (_, _), ( _, _), train_input_fn, eval_input_fn = get_resource_for_simple_model( model_type='subclass', is_evaluate=True) keras_model.compile( loss='categorical_crossentropy', optimizer=rmsprop.RMSPropOptimizer(1e-3), metrics=['mse', keras.metrics.CategoricalAccuracy()]) est_keras = keras_lib.model_to_estimator( keras_model=keras_model, config=self._config) est_keras.train(input_fn=train_input_fn, steps=_TRAIN_SIZE / 16) before_eval_results = est_keras.evaluate(input_fn=eval_input_fn, steps=1) est_keras.train(input_fn=train_input_fn, steps=_TRAIN_SIZE / 16) after_eval_results = est_keras.evaluate(input_fn=eval_input_fn, steps=1) self.assertLess(after_eval_results['loss'], before_eval_results['loss'])
def test_export_keras_estimator(self, checkpoint_format): keras_model, (x_train, y_train), ( _, _), train_input_fn, _ = get_resource_for_simple_model( model_type='sequential', is_evaluate=False) keras_model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) keras_model.fit(x_train, y_train, epochs=1) bias_value = keras.backend.get_value(keras_model.layers[0].bias) est_keras = keras_lib.model_to_estimator( keras_model=keras_model, model_dir=tempfile.mkdtemp(dir=self._base_dir), checkpoint_format=checkpoint_format) def serving_input_receiver_fn(): feature_spec = { 'dense_input': parsing_ops.FixedLenFeature([1], dtype=dtypes.float32) } return export_lib.build_parsing_serving_input_receiver_fn( feature_spec) # Try immediately exporting, testing that (1) exported values are the same, # and (2) estimator can be exported without saving a checkpoint into the # model directory. saved_model_dir = est_keras.export_saved_model( tempfile.mkdtemp(dir=self._base_dir), serving_input_receiver_fn()) variables_path = saved_model_utils.get_variables_path(saved_model_dir) variable_name = 'dense/bias' if checkpoint_format == 'checkpoint': names_to_keys = saver_lib.object_graph_key_mapping(variables_path) variable_name = names_to_keys[variable_name] self.assertAllClose( bias_value, training.load_variable(variables_path, variable_name)) # Export the estimator after training a bit. est_keras.train(input_fn=train_input_fn, steps=_TRAIN_SIZE / 16) saved_model_dir = est_keras.export_saved_model( tempfile.mkdtemp(dir=self._base_dir), serving_input_receiver_fn()) variables_path = saved_model_utils.get_variables_path(saved_model_dir) self.assertNotAllClose( bias_value, training.load_variable(variables_path, variable_name))
def test_train_premade_linear_model(self): (x_train, y_train ), _, train_inp_fn, eval_inp_fn = get_resource_for_simple_model() linear_model = linear.LinearModel(units=1) opt = gradient_descent.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 model_to_estimator( keras_model=None, keras_model_path=None, custom_objects=None, model_dir=None, config=None): """Constructs an `Estimator` instance from given keras model. For usage example, please see: [Creating estimators from Keras Models](https://tensorflow.org/guide/estimators#model_to_estimator). Args: keras_model: A compiled Keras model object. This argument is mutually exclusive with `keras_model_path`. 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`. custom_objects: Dictionary for custom objects. model_dir: Directory to save `Estimator` model parameters, graph, summary files for TensorBoard, etc. config: `RunConfig` to config `Estimator`. 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. """ try: from tensorflow_estimator.python.estimator import keras as 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.') return keras_lib.model_to_estimator( keras_model=keras_model, keras_model_path=keras_model_path, custom_objects=custom_objects, model_dir=model_dir, config=config)
def test_keras_model_init_error(self): with self.assertRaisesRegexp(ValueError, 'Either'): keras_lib.model_to_estimator() keras_model = simple_sequential_model() with self.assertRaisesRegexp(ValueError, 'not both'): keras_lib.model_to_estimator( keras_model=keras_model, keras_model_path=tempfile.mkdtemp(dir=self._base_dir)) keras_model = simple_sequential_model() with self.assertRaisesRegexp(ValueError, 'compiled'): keras_lib.model_to_estimator(keras_model=keras_model)
def test_predict(self): # Check that predict on a pretrained model yield the same result. keras_model, (x_train, y_train), ( x_test, _), _, pred_input_fn = get_resource_for_simple_model( model_type='sequential', is_evaluate=False) keras_model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) keras_model.fit(x_train, y_train, epochs=1) keras_pred = [np.argmax(y) for y in keras_model.predict(x_test)] keras_est = keras_lib.model_to_estimator(keras_model=keras_model, config=self._config) est_pred = [ np.argmax(y[keras_model.output_names[0]]) for y in keras_est.predict(input_fn=pred_input_fn) ] self.assertAllEqual(est_pred, keras_pred)