def test_setter_update(self): """Test the prototyped setter method.""" input_data = keras.Input(shape=(1, )) layer = AddingPreprocessingLayer() output = layer(input_data) model = keras.Model(input_data, output) model._run_eagerly = testing_utils.should_run_eagerly() layer.set_total(15) self.assertAllEqual([[16], [17], [18]], model.predict([1., 2., 3.]))
def test_add_entropy_loss_on_functional_model(self): inputs = Input(shape=(1,)) targets = Input(shape=(1,)) outputs = testing_utils.Bias()(inputs) model = Model([inputs, targets], outputs) model.add_loss(losses.binary_crossentropy(targets, outputs)) model.compile('sgd', run_eagerly=testing_utils.should_run_eagerly()) with tf.compat.v1.test.mock.patch.object(logging, 'warning') as mock_log: model.fit([self.x, self.y], batch_size=3, epochs=5) self.assertNotIn('Gradients do not exist for variables', str(mock_log.call_args))
def test_sequential_nesting(self): model = testing_utils.get_small_sequential_mlp(4, 3) inner_model = testing_utils.get_small_sequential_mlp(4, 5) model.add(inner_model) model.compile(loss='mse', optimizer='rmsprop', run_eagerly=testing_utils.should_run_eagerly()) x = np.random.random((2, 6)) y = np.random.random((2, 5)) model.fit(x, y, epochs=1)
def _get_compiled_multi_io_model(self): model = get_multi_io_model() model.compile( optimizer='rmsprop', loss='mse', metrics=[metrics.MeanSquaredError(name='mean_squared_error')], weighted_metrics=[ metrics.MeanSquaredError(name='mean_squared_error_2') ], run_eagerly=testing_utils.should_run_eagerly()) return model
def test_wide_deep_model_with_single_input(self): linear_model = linear.LinearModel(units=1) dnn_model = sequential.Sequential([core.Dense(units=1, input_dim=3)]) wide_deep_model = wide_deep.WideDeepModel(linear_model, dnn_model) inputs = np.random.uniform(low=-5., high=5., size=(64, 3)) output = .3 * inputs[:, 0] wide_deep_model.compile(optimizer=['sgd', 'adam'], loss='mse', metrics=[], run_eagerly=testing_utils.should_run_eagerly()) wide_deep_model.fit(inputs, output, epochs=5)
def test_zero_regularization(self): # Verifies that training with zero regularization works. x, y = np.ones((10, 10)), np.ones((10, 3)) model = testing_utils.get_model_from_layers([ keras.layers.Dense(3, kernel_regularizer=keras.regularizers.l2(0)) ], input_shape=(10, )) model.compile('sgd', 'mse', run_eagerly=testing_utils.should_run_eagerly()) model.fit(x, y, batch_size=5, epochs=1)
def test_clone_and_build_sequential_without_inputs_defined(self): model = models.Sequential(_get_layers(input_shape=None)) model.compile(testing_utils.get_v2_optimizer('rmsprop'), 'mse', metrics=['acc', metrics.categorical_accuracy], run_eagerly=testing_utils.should_run_eagerly()) self._clone_and_build_test_helper(model, 'sequential') inp = np.random.random((10, 4)) out = np.random.random((10, 4)) model.train_on_batch(inp, out) self._clone_and_build_test_helper(model, 'sequential')
def test_with_masking_layer_GRU(self): layer_class = keras.layers.GRU inputs = np.random.random((2, 3, 4)) targets = np.abs(np.random.random((2, 3, 5))) targets /= targets.sum(axis=-1, keepdims=True) model = keras.models.Sequential() model.add(keras.layers.Masking(input_shape=(3, 4))) model.add(layer_class(units=5, return_sequences=True, unroll=False)) model.compile(loss='categorical_crossentropy', optimizer='rmsprop', run_eagerly=testing_utils.should_run_eagerly()) model.fit(inputs, targets, epochs=1, batch_size=2, verbose=1)
def test_build_before_fit(self): # Fix for b/112433577 model = testing_utils.get_small_sequential_mlp(4, 5) model.compile(loss='mse', optimizer='rmsprop', run_eagerly=testing_utils.should_run_eagerly()) model.build((None, 6)) x = np.random.random((2, 6)) y = np.random.random((2, 5)) model.fit(x, y, epochs=1)
def test_GRU_runtime_with_mask(self): # Masking will affect which backend is selected based on whether the mask # is strictly right padded. layer = rnn.GRU(self.rnn_state_size, return_runtime=True) inputs = keras.layers.Input( shape=[self.timestep, self.input_shape], dtype=tf.float32) masked_inputs = keras.layers.Masking()(inputs) outputs, runtime = layer(masked_inputs) # Expand the runtime so that it is a 1D tensor instead of scalar. # TF model does not work with scalar model output, specially during # aggregation. runtime = keras.layers.Lambda( lambda x: tf.compat.v1.expand_dims(x, axis=-1))(runtime) model = keras.models.Model(inputs=inputs, outputs=[outputs, runtime]) (x_train, y_train), _ = testing_utils.get_test_data( train_samples=self.batch, test_samples=0, input_shape=(self.timestep, self.input_shape), num_classes=self.output_shape) y_train = np_utils.to_categorical(y_train, self.output_shape) model.compile( optimizer='sgd', loss=['categorical_crossentropy', None], run_eagerly=testing_utils.should_run_eagerly()) model.fit(x_train, y_train) # Verify unpadded data. _, runtime_value = model.predict(x_train) if tf.test.is_gpu_available(): self.assertEqual(runtime_value[0], rnn._RUNTIME_GPU) else: self.assertEqual(runtime_value[0], rnn._RUNTIME_CPU) # Update x/y to be right padded by setting the last timestep to 0 x_train[:, -1, :] = 0 y_train[:, -1] = 0 _, runtime_value = model.predict(x_train) if tf.test.is_gpu_available(): self.assertEqual(runtime_value[0], rnn._RUNTIME_GPU) else: self.assertEqual(runtime_value[0], rnn._RUNTIME_CPU) # Further update x/y to be mix padded (masks in the middle), and verify # only cpu kernel can be selected. x_train[:, -3, :] = 0 y_train[:, -3] = 0 _, runtime_value = model.predict(x_train) self.assertEqual(runtime_value[0], rnn._RUNTIME_CPU)
def test_generator_input_to_fit_eval_predict(self): val_data = np.ones([10, 10], np.float32), np.ones([10, 1], np.float32) def ones_generator(): while True: yield np.ones([10, 10], np.float32), np.ones([10, 1], np.float32) model = testing_utils.get_small_mlp(num_hidden=10, num_classes=1, input_dim=10) model.compile(rmsprop.RMSprop(0.001), 'binary_crossentropy', run_eagerly=testing_utils.should_run_eagerly()) model.fit(ones_generator(), steps_per_epoch=2, validation_data=val_data, epochs=2) model.evaluate(ones_generator(), steps=2) model.predict(ones_generator(), steps=2) # Test with a changing batch size model = testing_utils.get_small_mlp(num_hidden=3, num_classes=4, input_dim=2) model.compile(loss='mse', optimizer=rmsprop.RMSprop(1e-3), metrics=['mae', metrics_module.CategoricalAccuracy()]) model.fit_generator(custom_generator_changing_batch_size(), steps_per_epoch=5, epochs=1, verbose=1, max_queue_size=10, use_multiprocessing=False) model.fit_generator( custom_generator_changing_batch_size(), steps_per_epoch=5, epochs=1, verbose=1, max_queue_size=10, use_multiprocessing=False, validation_data=custom_generator_changing_batch_size(), validation_steps=10) model.fit(custom_generator_changing_batch_size(), steps_per_epoch=5, validation_data=custom_generator_changing_batch_size(), validation_steps=10, epochs=2) model.evaluate(custom_generator_changing_batch_size(), steps=5) model.predict(custom_generator_changing_batch_size(), steps=5)
def test_embedding_with_sharded_variable(self): layer = keras.layers.Embedding(input_dim=5, output_dim=2) v = [ tf.Variable([[1., 2.], [3., 4.]]), tf.Variable([[5., 6.], [7., 8.]]), tf.Variable([[9., 10.]]) ] model = keras.models.Sequential([layer]) layer.embeddings = sharded_variable.ShardedVariable(v) model.run_eagerly = testing_utils.should_run_eagerly() outputs = model.predict(np.array([[0, 2, 4]], dtype='int32')) self.assertAllClose(outputs, [[[1., 2.], [5., 6.], [9., 10.]]])
def test_trace_multi_io_model_outputs(self): input_dim = 5 num_classes = 3 num_classes_b = 4 input_a = keras.layers.Input(shape=(input_dim,), name='input_a') input_b = keras.layers.Input(shape=(input_dim,), name='input_b') dense = keras.layers.Dense(num_classes, name='dense') dense2 = keras.layers.Dense(num_classes_b, name='dense2') dropout = keras.layers.Dropout(0.5, name='dropout') branch_a = [input_a, dense] branch_b = [input_b, dense, dense2, dropout] model = testing_utils.get_multi_io_model(branch_a, branch_b) input_a_ts = tf.constant( np.random.random((10, input_dim)).astype(np.float32)) input_b_ts = tf.constant( np.random.random((10, input_dim)).astype(np.float32)) if testing_utils.get_model_type() == 'subclass': with self.assertRaisesRegex(ValueError, '.*input shape is not availabl*'): saving_utils.trace_model_call(model) model.compile( optimizer='sgd', loss='mse', run_eagerly=testing_utils.should_run_eagerly()) model.fit(x=[np.random.random((8, input_dim)).astype(np.float32), np.random.random((8, input_dim)).astype(np.float32)], y=[np.random.random((8, num_classes)).astype(np.float32), np.random.random((8, num_classes_b)).astype(np.float32)], epochs=2) fn = saving_utils.trace_model_call(model) # tf.function requires that the input structures match when calling a # ConcreteFunction. For some reason V1 models defines the inputs as a list, # while V2 models sets the inputs as a tuple. if (not tf.executing_eagerly() and testing_utils.get_model_type() != 'functional'): signature_outputs = fn([input_a_ts, input_b_ts]) else: signature_outputs = fn((input_a_ts, input_b_ts)) outputs = model([input_a_ts, input_b_ts]) if model.output_names: expected_outputs = { model.output_names[0]: outputs[0], model.output_names[1]: outputs[1] } else: expected_outputs = {'output_1': outputs[0], 'output_2': outputs[1]} self._assert_all_close(expected_outputs, signature_outputs)
def test_dataset_fit_correctness(self): class SumLayer(keras.layers.Layer): def build(self, _): self.w = self.add_weight('w', ()) def call(self, inputs): return keras.backend.sum(inputs, axis=1, keepdims=True) + self.w * 0 model = keras.Sequential([SumLayer(input_shape=(2, ))]) model.compile('rmsprop', loss='mae', run_eagerly=testing_utils.should_run_eagerly()) inputs = np.zeros((40, 2), dtype=np.float32) inputs[10:20, :] = 2 inputs[20:30, :] = 1 inputs[30:, :] = 4 targets = np.zeros((40, 1), dtype=np.float32) # Test correctness with `steps_per_epoch`. train_dataset = tf.data.Dataset.from_tensor_slices( (inputs, targets)).batch(10) val_dataset = tf.data.Dataset.from_tensor_slices( (inputs, targets)).batch(10) history = model.fit(train_dataset, epochs=2, steps_per_epoch=2, verbose=1, validation_data=val_dataset, validation_steps=2) self.assertAllClose(history.history['loss'], [inputs[:20].sum() / 20, inputs[20:].sum() / 20]) # The validation dataset will be reset at the end of each validation run. self.assertAllClose(history.history['val_loss'], [inputs[:20].sum() / 20, inputs[:20].sum() / 20]) # Test correctness with dataset reset. train_dataset = tf.data.Dataset.from_tensor_slices( (inputs, targets)).batch(10) val_dataset = tf.data.Dataset.from_tensor_slices( (inputs, targets)).batch(10) history = model.fit(train_dataset, epochs=2, verbose=1, validation_data=val_dataset) self.assertAllClose( history.history['loss'], [inputs.sum() / 40, inputs.sum() / 40]) self.assertAllClose( history.history['val_loss'], [inputs.sum() / 40, inputs.sum() / 40])
def test_clone_and_build_non_compiled_model(self): inp = np.random.random((10, 4)) out = np.random.random((10, 4)) model = _get_model() with self.assertRaisesRegex(ValueError, 'has not been compiled'): models.clone_and_build_model(model, compile_clone=True) is_subclassed = (testing_utils.get_model_type() == 'subclass') # With placeholder creation new_model = models.clone_and_build_model( model, compile_clone=False, in_place_reset=is_subclassed) with self.assertRaisesRegex(RuntimeError, 'must compile'): new_model.evaluate(inp, out) with self.assertRaisesRegex(RuntimeError, 'must compile'): new_model.train_on_batch(inp, out) new_model.compile( testing_utils.get_v2_optimizer('rmsprop'), 'mse', run_eagerly=testing_utils.should_run_eagerly()) new_model.train_on_batch(inp, out) # Create new tensors for inputs. input_a = keras.Input(shape=(4,)) new_model = models.clone_and_build_model( model, input_tensors=input_a, compile_clone=False, in_place_reset=is_subclassed) with self.assertRaisesRegex(RuntimeError, 'must compile'): new_model.evaluate(inp, out) with self.assertRaisesRegex(RuntimeError, 'must compile'): new_model.train_on_batch(inp, out) new_model.compile( testing_utils.get_v2_optimizer('rmsprop'), 'mse', run_eagerly=testing_utils.should_run_eagerly()) new_model.train_on_batch(inp, out)
def test_masking_with_stacking_LSTM(self, unroll): inputs = np.random.random((2, 3, 4)) targets = np.abs(np.random.random((2, 3, 5))) targets /= targets.sum(axis=-1, keepdims=True) model = keras.models.Sequential() model.add(keras.layers.Masking(input_shape=(3, 4))) lstm_cells = [keras.layers.LSTMCell(10), keras.layers.LSTMCell(5)] model.add( keras.layers.RNN(lstm_cells, return_sequences=True, unroll=unroll)) model.compile(loss='categorical_crossentropy', optimizer='rmsprop', run_eagerly=testing_utils.should_run_eagerly()) model.fit(inputs, targets, epochs=1, batch_size=2, verbose=1)
def test_loss_on_model_fit(self): inputs = Input(shape=(1,)) targets = Input(shape=(1,)) outputs = testing_utils.Bias()(inputs) model = Model([inputs, targets], outputs) model.add_loss(MAE()(targets, outputs)) model.add_loss(tf.reduce_mean(mae(targets, outputs))) model.compile( optimizer_v2.gradient_descent.SGD(0.05), run_eagerly=testing_utils.should_run_eagerly()) history = model.fit([self.x, self.y], batch_size=3, epochs=5) self.assertAllClose(history.history['loss'], [2., 1.8, 1.6, 1.4, 1.2], 1e-3)
def test_merge_minimum(self): i1 = keras.layers.Input(shape=(4, 5)) i2 = keras.layers.Input(shape=(4, 5)) o = keras.layers.minimum([i1, i2]) self.assertListEqual(o.shape.as_list(), [None, 4, 5]) model = keras.models.Model([i1, i2], o) model.run_eagerly = testing_utils.should_run_eagerly() x1 = np.random.random((2, 4, 5)) x2 = np.random.random((2, 4, 5)) out = model.predict([x1, x2]) self.assertEqual(out.shape, (2, 4, 5)) self.assertAllClose(out, np.minimum(x1, x2), atol=1e-4)
def test_ragged_tensor_rebatched_outputs(self): # Create a model that accepts an input, converts it to Ragged, and # converts the ragged tensor back to a dense tensor. layers = [ToRagged(padding=0)] model = testing_utils.get_model_from_layers(layers, input_shape=(None,)) model._run_eagerly = testing_utils.should_run_eagerly() # Define some input data with additional padding. input_data = np.array([[1, 0, 0], [2, 3, 0], [4, 0, 0], [5, 6, 0]]) output = model.predict(input_data, batch_size=2) expected_values = [[1], [2, 3], [4], [5, 6]] self.assertAllEqual(expected_values, output)
def test_post_build_adapt_update_numpy(self): """Test that preproc layers can adapt() after build() is called.""" input_dataset = np.array([1, 2, 3, 4, 5]) input_data = keras.Input(shape=(1, )) layer = get_layer() output = layer(input_data) model = keras.Model(input_data, output) model._run_eagerly = testing_utils.should_run_eagerly() layer.adapt(input_dataset) self.assertAllEqual([[16], [17], [18]], model.predict([1., 2., 3.]))
def test_model_backend_float64_use_cases(self): # Test case for GitHub issue 19318 floatx = keras.backend.floatx() keras.backend.set_floatx('float64') x = keras.Input((5, )) y = keras.layers.Dense(1)(x) model = keras.models.Model(x, y) model.compile(testing_utils.get_v2_optimizer('rmsprop'), 'mse', run_eagerly=testing_utils.should_run_eagerly()) keras.backend.set_floatx(floatx)
def test_build_behavior(self): # Test graph network creation after __call__ model = get_model() model(np.random.random((2, 6))) self.assertLen(model.weights, 4) self.assertTrue(model._is_graph_network) self.assertLen(model.inputs, 1) self.assertLen(model.outputs, 1) self.assertEqual(model.inputs[0].shape.as_list(), [2, 6]) self.assertEqual(model.outputs[0].shape.as_list(), [2, 2]) # Test effect of new __call__ with a different shape model(np.random.random((3, 6))) self.assertLen(model.inputs, 1) self.assertLen(model.outputs, 1) self.assertEqual(model.inputs[0].shape.as_list(), [None, 6]) self.assertEqual(model.outputs[0].shape.as_list(), [None, 2]) model(np.random.random((4, 6))) self.assertLen(model.inputs, 1) self.assertLen(model.outputs, 1) self.assertEqual(model.inputs[0].shape.as_list(), [None, 6]) self.assertEqual(model.outputs[0].shape.as_list(), [None, 2]) # Test graph network creation after build model = get_model() model.build((None, 6)) self.assertLen(model.weights, 4) self.assertTrue(model._is_graph_network) self.assertLen(model.inputs, 1) self.assertLen(model.outputs, 1) self.assertEqual(model.inputs[0].shape.as_list(), [None, 6]) self.assertEqual(model.outputs[0].shape.as_list(), [None, 2]) # Test graph network creation after compile/fit model = get_model() model.compile( loss='mse', optimizer='rmsprop', metrics=[keras.metrics.CategoricalAccuracy()], run_eagerly=testing_utils.should_run_eagerly()) model.fit(np.zeros((2, 6)), np.zeros((2, 2))) self.assertLen(model.weights, 4) self.assertTrue(model._is_graph_network) self.assertLen(model.inputs, 1) self.assertLen(model.outputs, 1) # Inconsistency here: with eager `fit`, the model is built with shape # (2, 6), but with graph function `fit`, it is built with shape `(None, 6)`. # This is likely due to our assumption "the batch size should be dynamic" # at the level of `Model`. TODO(fchollet): investigate and resolve. self.assertEqual(model.inputs[0].shape.as_list()[-1], 6) self.assertEqual(model.outputs[0].shape.as_list()[-1], 2)
def test_loss_layer(self): class LossLayer(keras.layers.Layer): def call(self, inputs): self.add_loss(tf.reduce_sum(inputs)) return inputs # Test loss layer alone model = keras.Sequential([LossLayer()]) model.compile('rmsprop', run_eagerly=testing_utils.should_run_eagerly()) loss = model.train_on_batch(np.ones((2, 2))) self.assertAllClose(loss, 4.) model(np.random.random((4, 2))) # Triggers a rebuild loss = model.train_on_batch(np.ones((1, 2))) self.assertAllClose(loss, 2.) # Test loss layer combined with another layer model = keras.Sequential( [keras.layers.Dense(1, kernel_initializer='ones'), LossLayer()]) model.compile('rmsprop', run_eagerly=testing_utils.should_run_eagerly()) loss = model.train_on_batch(np.ones((2, 2))) self.assertAllClose(loss, 4.) model(np.random.random((4, 2))) # Triggers a rebuild loss = model.train_on_batch(np.ones((1, 2))) self.assertLess(loss, 2.) # Test loss layer combined with external loss model = keras.Sequential( [keras.layers.Dense(1, kernel_initializer='ones'), LossLayer()]) model.compile('rmsprop', 'mse', run_eagerly=testing_utils.should_run_eagerly()) loss = model.train_on_batch(np.ones((2, 2)), np.ones((2, 2))) model(np.random.random((4, 2))) # Triggers a rebuild loss = model.train_on_batch(np.ones((1, 2)), np.ones((1, 2)))
def test_loss_with_sample_weight_on_model_fit(self): inputs = Input(shape=(1,)) targets = Input(shape=(1,)) sw = Input(shape=(1,)) outputs = testing_utils.Bias()(inputs) model = Model([inputs, targets, sw], outputs) model.add_loss(MAE()(targets, outputs, sw)) model.add_loss(3 * tf.reduce_mean(sw * mae(targets, outputs))) model.compile( optimizer_v2.gradient_descent.SGD(0.025), run_eagerly=testing_utils.should_run_eagerly()) history = model.fit([self.x, self.y, self.w], batch_size=3, epochs=5) self.assertAllClose(history.history['loss'], [4., 3.6, 3.2, 2.8, 2.4], 1e-3)
def test_post_build_adapt_update_dataset(self): """Test that preproc layers can adapt() after build() is called.""" input_dataset = tf.data.Dataset.from_tensor_slices( np.array([[1], [2], [3], [4], [5], [0]])) input_data = keras.Input(shape=(1, )) layer = get_layer() output = layer(input_data) model = keras.Model(input_data, output) model._run_eagerly = testing_utils.should_run_eagerly() layer.adapt(input_dataset) self.assertAllEqual([[16], [17], [18]], model.predict([1., 2., 3.]))
def test_post_build_injected_update(self): """Test external update injection after build() is called.""" input_dataset = np.array([1, 2, 3, 4, 5]) input_data = keras.Input(shape=(1, )) layer = get_layer() output = layer(input_data) model = keras.Model(input_data, output) model._run_eagerly = testing_utils.should_run_eagerly() combiner = layer._combiner updates = combiner.extract(combiner.compute(input_dataset)) layer._set_state_variables(updates) self.assertAllEqual([[16], [17], [18]], model.predict([1., 2., 3.]))
def test_wide_deep_model(self): linear_model = linear.LinearModel(units=1) dnn_model = sequential.Sequential([core.Dense(units=1, input_dim=3)]) wide_deep_model = wide_deep.WideDeepModel(linear_model, dnn_model) linear_inp = np.random.uniform(low=-5, high=5, size=(64, 2)) dnn_inp = np.random.uniform(low=-5, high=5, size=(64, 3)) inputs = [linear_inp, dnn_inp] output = .3 * linear_inp[:, 0] + .2 * dnn_inp[:, 1] wide_deep_model.compile(optimizer=['sgd', 'adam'], loss='mse', metrics=[], run_eagerly=testing_utils.should_run_eagerly()) wide_deep_model.fit(inputs, output, epochs=5) self.assertTrue(wide_deep_model.built)
def test_dataset_with_sparse_labels(self): model = testing_utils.get_small_mlp(1, 4, input_dim=3) optimizer = 'rmsprop' model.compile(optimizer, loss='sparse_categorical_crossentropy', run_eagerly=testing_utils.should_run_eagerly()) inputs = np.zeros((10, 3), dtype=np.float32) targets = np.random.randint(0, 4, size=10, dtype=np.int32) dataset = tf.data.Dataset.from_tensor_slices((inputs, targets)) dataset = dataset.repeat(100) dataset = dataset.batch(10) model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=1)
def test_activity_regularizer_batch_independent(self): inputs = layers.Input(shape=(10,)) x = layers.Dense(10, activation='relu', activity_regularizer='l2')(inputs) outputs = layers.Dense(1, activation='sigmoid')(x) model = Model(inputs, outputs) optimizer = RMSPropOptimizer(learning_rate=0.001) model.compile( optimizer, run_eagerly=testing_utils.should_run_eagerly()) loss_small_batch = model.test_on_batch(np.ones((10, 10), 'float32')) loss_big_batch = model.test_on_batch(np.ones((20, 10), 'float32')) self.assertAlmostEqual(loss_small_batch, loss_big_batch, places=4)
def test_loss_callable_on_model_fit(self): model = testing_utils.get_model_from_layers([testing_utils.Bias()], input_shape=(1,)) def callable_loss(): return tf.reduce_sum(model.weights) model.add_loss(callable_loss) model.compile( optimizer_v2.gradient_descent.SGD(0.1), run_eagerly=testing_utils.should_run_eagerly()) history = model.fit(self.x, batch_size=3, epochs=5) self.assertAllClose(history.history['loss'], [0., -.1, -.2, -.3, -.4], 1e-3)