mirror of
https://github.com/zebrajr/tensorflow.git
synced 2026-01-15 12:15:41 +00:00
Add unit test for model_to_estimator where inpu_fn
returns features and labels as a list instead of dict. PiperOrigin-RevId: 212685344
This commit is contained in:
committed by
TensorFlower Gardener
parent
28e945e590
commit
3fb474713b
@@ -34,6 +34,7 @@ from tensorflow.python.framework import dtypes
|
||||
from tensorflow.python.framework import test_util
|
||||
from tensorflow.python.keras import testing_utils
|
||||
from tensorflow.python.keras.engine import distributed_training_utils
|
||||
from tensorflow.python.ops.parsing_ops import gen_parsing_ops
|
||||
from tensorflow.python.platform import gfile
|
||||
from tensorflow.python.platform import test
|
||||
from tensorflow.python.summary.writer import writer_cache
|
||||
@@ -66,6 +67,32 @@ def simple_functional_model():
|
||||
return model
|
||||
|
||||
|
||||
def multi_inputs_multi_outputs_model():
|
||||
input_a = keras.layers.Input(shape=(16,), name='input_a')
|
||||
input_b = keras.layers.Input(shape=(16,), name='input_b')
|
||||
input_m = keras.layers.Input(shape=(8,), dtype='string', name='input_m')
|
||||
dense = keras.layers.Dense(8, name='dense_1')
|
||||
|
||||
interm_a = dense(input_a)
|
||||
# Read m
|
||||
interm_m = keras.layers.Lambda(gen_parsing_ops.string_to_number)(input_m)
|
||||
interm_s = keras.layers.Lambda(lambda k: k[0] * k[1])([interm_m, interm_a])
|
||||
interm_b = dense(input_b)
|
||||
merged = keras.layers.concatenate([interm_s, interm_b], name='merge')
|
||||
output_c = keras.layers.Dense(3, activation='softmax', name='dense_2')(merged)
|
||||
output_d = keras.layers.Dense(2, activation='softmax', name='dense_3')(merged)
|
||||
model = keras.models.Model(
|
||||
inputs=[input_a, input_b, input_m], outputs=[output_c, output_d])
|
||||
model.compile(
|
||||
loss='categorical_crossentropy',
|
||||
optimizer=gradient_descent.GradientDescentOptimizer(0.001),
|
||||
metrics={
|
||||
'dense_2': 'categorical_accuracy',
|
||||
'dense_3': 'categorical_accuracy'
|
||||
})
|
||||
return model
|
||||
|
||||
|
||||
def get_ds_train_input_fn():
|
||||
np.random.seed(_RANDOM_SEED)
|
||||
(x_train, y_train), _ = testing_utils.get_test_data(
|
||||
@@ -94,6 +121,49 @@ def get_ds_test_input_fn():
|
||||
return dataset
|
||||
|
||||
|
||||
def get_multi_inputs_multi_outputs_data():
|
||||
(a_train, c_train), (a_test, c_test) = testing_utils.get_test_data(
|
||||
train_samples=_TRAIN_SIZE,
|
||||
test_samples=50,
|
||||
input_shape=(16,),
|
||||
num_classes=3,
|
||||
random_seed=_RANDOM_SEED)
|
||||
(b_train, d_train), (b_test, d_test) = testing_utils.get_test_data(
|
||||
train_samples=_TRAIN_SIZE,
|
||||
test_samples=50,
|
||||
input_shape=(16,),
|
||||
num_classes=2,
|
||||
random_seed=_RANDOM_SEED)
|
||||
(m_train, _), (m_test, _) = testing_utils.get_test_data(
|
||||
train_samples=_TRAIN_SIZE,
|
||||
test_samples=50,
|
||||
input_shape=(8,),
|
||||
num_classes=2,
|
||||
random_seed=_RANDOM_SEED)
|
||||
|
||||
c_train = keras.utils.to_categorical(c_train)
|
||||
c_test = keras.utils.to_categorical(c_test)
|
||||
d_train = keras.utils.to_categorical(d_train)
|
||||
d_test = keras.utils.to_categorical(d_test)
|
||||
|
||||
train_data = {
|
||||
'input_a': a_train,
|
||||
'input_b': b_train,
|
||||
'input_m': m_train,
|
||||
'output_c': c_train,
|
||||
'output_d': d_train
|
||||
}
|
||||
test_data = {
|
||||
'input_a': a_test,
|
||||
'input_b': b_test,
|
||||
'input_m': m_test,
|
||||
'output_c': c_test,
|
||||
'output_d': d_test
|
||||
}
|
||||
|
||||
return (train_data, test_data)
|
||||
|
||||
|
||||
def batch_wrapper(dataset, batch_size, distribution):
|
||||
# TPUs currently require fully defined input shapes, drop_remainder ensures
|
||||
# the input will have fully defined shapes.
|
||||
@@ -121,6 +191,8 @@ class TestEstimatorDistributionStrategy(test_util.TensorFlowTestCase):
|
||||
gfile.MakeDirs(self._base_dir)
|
||||
self._config = run_config_lib.RunConfig(
|
||||
tf_random_seed=_RANDOM_SEED, model_dir=self._base_dir)
|
||||
self._dist = mirrored_strategy.MirroredStrategy(
|
||||
devices=['/device:GPU:0', '/device:GPU:1'])
|
||||
|
||||
def tearDown(self):
|
||||
writer_cache.FileWriterCache.clear()
|
||||
@@ -174,6 +246,53 @@ class TestEstimatorDistributionStrategy(test_util.TensorFlowTestCase):
|
||||
writer_cache.FileWriterCache.clear()
|
||||
gfile.DeleteRecursively(self._config.model_dir)
|
||||
|
||||
def test_multi_inputs_multi_outputs_with_input_fn_as_dict(self):
|
||||
train_data, test_data = get_multi_inputs_multi_outputs_data()
|
||||
|
||||
def train_input_fn():
|
||||
input_dict = {
|
||||
'input_a': train_data['input_a'],
|
||||
'input_b': train_data['input_b'],
|
||||
'input_m': train_data['input_m'].astype(np.str)
|
||||
}
|
||||
output_dict = {
|
||||
'dense_2': train_data['output_c'],
|
||||
'dense_3': train_data['output_d']
|
||||
}
|
||||
return dataset_ops.Dataset.from_tensor_slices((input_dict,
|
||||
output_dict)).batch(16)
|
||||
|
||||
def eval_input_fn():
|
||||
input_dict = {
|
||||
'input_a': test_data['input_a'],
|
||||
'input_b': test_data['input_b'],
|
||||
'input_m': test_data['input_m'].astype(np.str)
|
||||
}
|
||||
output_dict = {
|
||||
'dense_2': test_data['output_c'],
|
||||
'dense_3': test_data['output_d']
|
||||
}
|
||||
return dataset_ops.Dataset.from_tensor_slices((input_dict,
|
||||
output_dict)).batch(16)
|
||||
|
||||
self.do_test_multi_inputs_multi_outputs_with_input_fn(
|
||||
train_input_fn, eval_input_fn)
|
||||
|
||||
def do_test_multi_inputs_multi_outputs_with_input_fn(self, train_input_fn,
|
||||
eval_input_fn):
|
||||
config = run_config_lib.RunConfig(
|
||||
tf_random_seed=_RANDOM_SEED,
|
||||
model_dir=self._base_dir,
|
||||
train_distribute=self._dist)
|
||||
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_keras_optimizer_with_distribution_strategy(self):
|
||||
dist = mirrored_strategy.MirroredStrategy(
|
||||
devices=['/device:GPU:0', '/device:GPU:1'])
|
||||
|
||||
@@ -102,6 +102,49 @@ def gen_input_fn(x, y=None, batch_size=128, num_epochs=1, shuffle=False):
|
||||
return input_fn
|
||||
|
||||
|
||||
def get_multi_inputs_multi_outputs_data():
|
||||
(a_train, c_train), (a_test, c_test) = testing_utils.get_test_data(
|
||||
train_samples=_TRAIN_SIZE,
|
||||
test_samples=50,
|
||||
input_shape=(16,),
|
||||
num_classes=3,
|
||||
random_seed=_RANDOM_SEED)
|
||||
(b_train, d_train), (b_test, d_test) = testing_utils.get_test_data(
|
||||
train_samples=_TRAIN_SIZE,
|
||||
test_samples=50,
|
||||
input_shape=(16,),
|
||||
num_classes=2,
|
||||
random_seed=_RANDOM_SEED)
|
||||
(m_train, _), (m_test, _) = testing_utils.get_test_data(
|
||||
train_samples=_TRAIN_SIZE,
|
||||
test_samples=50,
|
||||
input_shape=(8,),
|
||||
num_classes=2,
|
||||
random_seed=_RANDOM_SEED)
|
||||
|
||||
c_train = keras.utils.to_categorical(c_train)
|
||||
c_test = keras.utils.to_categorical(c_test)
|
||||
d_train = keras.utils.to_categorical(d_train)
|
||||
d_test = keras.utils.to_categorical(d_test)
|
||||
|
||||
train_data = {
|
||||
'input_a': a_train,
|
||||
'input_b': b_train,
|
||||
'input_m': m_train,
|
||||
'output_c': c_train,
|
||||
'output_d': d_train
|
||||
}
|
||||
test_data = {
|
||||
'input_a': a_test,
|
||||
'input_b': b_test,
|
||||
'input_m': m_test,
|
||||
'output_c': c_test,
|
||||
'output_d': d_test
|
||||
}
|
||||
|
||||
return (train_data, test_data)
|
||||
|
||||
|
||||
def get_resource_for_simple_model(model_type='sequential',
|
||||
is_evaluate=False,):
|
||||
if model_type == 'sequential':
|
||||
@@ -159,20 +202,21 @@ def randomize_io_type(array, name):
|
||||
|
||||
|
||||
def multi_inputs_multi_outputs_model():
|
||||
a = keras.layers.Input(shape=(16,), name='input_a')
|
||||
b = keras.layers.Input(shape=(16,), name='input_b')
|
||||
m = keras.layers.Input(shape=(8,), dtype='string', name='input_m')
|
||||
input_a = keras.layers.Input(shape=(16,), name='input_a')
|
||||
input_b = keras.layers.Input(shape=(16,), name='input_b')
|
||||
input_m = keras.layers.Input(shape=(8,), dtype='string', name='input_m')
|
||||
dense = keras.layers.Dense(8, name='dense_1')
|
||||
|
||||
a_2 = dense(a)
|
||||
interm_a = dense(input_a)
|
||||
# Read m
|
||||
m_2 = keras.layers.Lambda(gen_parsing_ops.string_to_number)(m)
|
||||
s_2 = keras.layers.Lambda(lambda k: k[0] * k[1])([m_2, a_2])
|
||||
b_2 = dense(b)
|
||||
merged = keras.layers.concatenate([s_2, b_2], name='merge')
|
||||
c = keras.layers.Dense(3, activation='softmax', name='dense_2')(merged)
|
||||
d = keras.layers.Dense(2, activation='softmax', name='dense_3')(merged)
|
||||
model = keras.models.Model(inputs=[a, b, m], outputs=[c, d])
|
||||
interm_m = keras.layers.Lambda(gen_parsing_ops.string_to_number)(input_m)
|
||||
interm_s = keras.layers.Lambda(lambda k: k[0] * k[1])([interm_m, interm_a])
|
||||
interm_b = dense(input_b)
|
||||
merged = keras.layers.concatenate([interm_s, interm_b], name='merge')
|
||||
output_c = keras.layers.Dense(3, activation='softmax', name='dense_2')(merged)
|
||||
output_d = keras.layers.Dense(2, activation='softmax', name='dense_3')(merged)
|
||||
model = keras.models.Model(
|
||||
inputs=[input_a, input_b, input_m], outputs=[output_c, output_d])
|
||||
model.compile(
|
||||
loss='categorical_crossentropy',
|
||||
optimizer='rmsprop',
|
||||
@@ -414,51 +458,85 @@ class TestKerasEstimator(test_util.TensorFlowTestCase):
|
||||
]
|
||||
self.assertAllEqual(est_pred, keras_pred)
|
||||
|
||||
def test_multi_inputs_multi_outputs(self):
|
||||
np.random.seed(_RANDOM_SEED)
|
||||
(a_train, c_train), (a_test, c_test) = testing_utils.get_test_data(
|
||||
train_samples=_TRAIN_SIZE,
|
||||
test_samples=50,
|
||||
input_shape=(16,),
|
||||
num_classes=3)
|
||||
np.random.seed(_RANDOM_SEED)
|
||||
(b_train, d_train), (b_test, d_test) = testing_utils.get_test_data(
|
||||
train_samples=_TRAIN_SIZE,
|
||||
test_samples=50,
|
||||
input_shape=(16,),
|
||||
num_classes=2)
|
||||
np.random.seed(_RANDOM_SEED)
|
||||
(input_m_train, _), (input_m_test, _) = testing_utils.get_test_data(
|
||||
train_samples=_TRAIN_SIZE,
|
||||
test_samples=50,
|
||||
input_shape=(8,),
|
||||
num_classes=2)
|
||||
|
||||
c_train = keras.utils.to_categorical(c_train)
|
||||
c_test = keras.utils.to_categorical(c_test)
|
||||
d_train = keras.utils.to_categorical(d_train)
|
||||
d_test = keras.utils.to_categorical(d_test)
|
||||
def test_multi_inputs_multi_outputs_with_input_fn_as_dict(self):
|
||||
train_data, test_data = get_multi_inputs_multi_outputs_data()
|
||||
|
||||
def train_input_fn():
|
||||
input_dict = {'input_a': a_train, 'input_b': b_train,
|
||||
'input_m': input_m_train.astype(np.str)}
|
||||
output_dict = {'dense_2': c_train, 'dense_3': d_train}
|
||||
input_dict = {
|
||||
'input_a': train_data['input_a'],
|
||||
'input_b': train_data['input_b'],
|
||||
'input_m': train_data['input_m'].astype(np.str)
|
||||
}
|
||||
output_dict = {
|
||||
'dense_2': train_data['output_c'],
|
||||
'dense_3': train_data['output_d']
|
||||
}
|
||||
return input_dict, output_dict
|
||||
|
||||
def eval_input_fn():
|
||||
input_dict = {'input_a': a_test, 'input_b': b_test,
|
||||
'input_m': input_m_test.astype(np.str)}
|
||||
output_dict = {'dense_2': c_test, 'dense_3': d_test}
|
||||
input_dict = {
|
||||
'input_a': test_data['input_a'],
|
||||
'input_b': test_data['input_b'],
|
||||
'input_m': test_data['input_m'].astype(np.str)
|
||||
}
|
||||
output_dict = {
|
||||
'dense_2': test_data['output_c'],
|
||||
'dense_3': test_data['output_d']
|
||||
}
|
||||
return input_dict, output_dict
|
||||
|
||||
def pred_input_fn():
|
||||
input_dict = {
|
||||
'input_a': test_data['input_a'],
|
||||
'input_b': test_data['input_b'],
|
||||
'input_m': test_data['input_m'].astype(np.str)
|
||||
}
|
||||
return input_dict
|
||||
|
||||
self.do_test_multi_inputs_multi_outputs_with_input_fn(
|
||||
train_input_fn, eval_input_fn, pred_input_fn)
|
||||
|
||||
def test_multi_inputs_multi_outputs_with_input_fn_as_list(self):
|
||||
train_data, test_data = get_multi_inputs_multi_outputs_data()
|
||||
|
||||
def train_input_fn():
|
||||
input_list = [
|
||||
train_data['input_a'], train_data['input_b'],
|
||||
train_data['input_m'].astype(np.str)
|
||||
]
|
||||
output_list = [train_data['output_c'], train_data['output_d']]
|
||||
return input_list, output_list
|
||||
|
||||
def eval_input_fn():
|
||||
input_list = [
|
||||
test_data['input_a'], test_data['input_b'],
|
||||
test_data['input_m'].astype(np.str)
|
||||
]
|
||||
output_list = [test_data['output_c'], test_data['output_d']]
|
||||
return input_list, output_list
|
||||
|
||||
def pred_input_fn():
|
||||
input_list = [
|
||||
test_data['input_a'], test_data['input_b'],
|
||||
test_data['input_m'].astype(np.str)
|
||||
]
|
||||
return input_list
|
||||
|
||||
self.do_test_multi_inputs_multi_outputs_with_input_fn(
|
||||
train_input_fn, eval_input_fn, pred_input_fn)
|
||||
|
||||
def do_test_multi_inputs_multi_outputs_with_input_fn(
|
||||
self, train_input_fn, eval_input_fn, pred_input_fn):
|
||||
with self.cached_session():
|
||||
model = multi_inputs_multi_outputs_model()
|
||||
est_keras = keras_lib.model_to_estimator(
|
||||
keras_model=model, config=self._config)
|
||||
before_eval_results = est_keras.evaluate(input_fn=eval_input_fn, steps=1)
|
||||
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)
|
||||
after_eval_results = est_keras.evaluate(input_fn=eval_input_fn, steps=1)
|
||||
self.assertLess(after_eval_results['loss'], before_eval_results['loss'])
|
||||
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_init_from_file(self):
|
||||
if h5py is None:
|
||||
|
||||
@@ -29,7 +29,8 @@ from tensorflow.python.util import tf_inspect
|
||||
def get_test_data(train_samples,
|
||||
test_samples,
|
||||
input_shape,
|
||||
num_classes):
|
||||
num_classes,
|
||||
random_seed=None):
|
||||
"""Generates test data to train a model on.
|
||||
|
||||
Arguments:
|
||||
@@ -37,10 +38,13 @@ def get_test_data(train_samples,
|
||||
test_samples: Integer, how many test samples to generate.
|
||||
input_shape: Tuple of integers, shape of the inputs.
|
||||
num_classes: Integer, number of classes for the data and targets.
|
||||
random_seed: Integer, random seed used by numpy to generate data.
|
||||
|
||||
Returns:
|
||||
A tuple of Numpy arrays: `(x_train, y_train), (x_test, y_test)`.
|
||||
"""
|
||||
if random_seed is not None:
|
||||
np.random.seed(random_seed)
|
||||
num_sample = train_samples + test_samples
|
||||
templates = 2 * num_classes * np.random.random((num_classes,) + input_shape)
|
||||
y = np.random.randint(0, num_classes, size=(num_sample,))
|
||||
|
||||
Reference in New Issue
Block a user