diff --git a/tensorflow/python/keras/tests/BUILD b/tensorflow/python/keras/tests/BUILD index 16d3d8494e2..da2b24dbdef 100644 --- a/tensorflow/python/keras/tests/BUILD +++ b/tensorflow/python/keras/tests/BUILD @@ -13,6 +13,22 @@ package( exports_files(["LICENSE"]) +tf_py_test( + name = "get_config_test", + srcs = ["get_config_test.py"], + python_version = "PY3", + shard_count = 4, + tags = [ + "no_pip", + ], + deps = [ + ":get_config_samples", + "//tensorflow/python:client_testlib", + "//tensorflow/python/keras", + "@absl_py//absl/testing:parameterized", + ], +) + tf_py_test( name = "add_loss_correctness_test", srcs = ["add_loss_correctness_test.py"], @@ -272,3 +288,10 @@ tf_py_test( "//third_party/py/numpy", ], ) + +py_library( + name = "get_config_samples", + srcs = ["get_config_samples.py"], + srcs_version = "PY2AND3", + deps = [], +) diff --git a/tensorflow/python/keras/tests/get_config_samples.py b/tensorflow/python/keras/tests/get_config_samples.py new file mode 100644 index 00000000000..ca622e82b7d --- /dev/null +++ b/tensorflow/python/keras/tests/get_config_samples.py @@ -0,0 +1,491 @@ +# Copyright 2020 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +# pylint: disable=protected-access +"""Sample `get_config` results for testing backwards compatibility.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +# inputs = tf.keras.Input(10) +# x = tf.keras.layers.Dense(10, activation='relu')(inputs) +# outputs = tf.keras.layers.Dense(1)(x) +# model = tf.keras.Model(inputs, outputs) +FUNCTIONAL_DNN = { + 'input_layers': [['input_1', 0, 0]], + 'layers': [{ + 'class_name': 'InputLayer', + 'config': { + 'batch_input_shape': (None, 10), + 'dtype': 'float32', + 'name': 'input_1', + 'ragged': False, + 'sparse': False + }, + 'inbound_nodes': [], + 'name': 'input_1' + }, { + 'class_name': 'Dense', + 'config': { + 'activation': 'relu', + 'activity_regularizer': None, + 'bias_constraint': None, + 'bias_initializer': { + 'class_name': 'Zeros', + 'config': {} + }, + 'bias_regularizer': None, + 'dtype': 'float32', + 'kernel_constraint': None, + 'kernel_initializer': { + 'class_name': 'GlorotUniform', + 'config': { + 'seed': None + } + }, + 'kernel_regularizer': None, + 'name': 'dense', + 'trainable': True, + 'units': 10, + 'use_bias': True + }, + 'inbound_nodes': [[['input_1', 0, 0, {}]]], + 'name': 'dense' + }, { + 'class_name': 'Dense', + 'config': { + 'activation': 'linear', + 'activity_regularizer': None, + 'bias_constraint': None, + 'bias_initializer': { + 'class_name': 'Zeros', + 'config': {} + }, + 'bias_regularizer': None, + 'dtype': 'float32', + 'kernel_constraint': None, + 'kernel_initializer': { + 'class_name': 'GlorotUniform', + 'config': { + 'seed': None + } + }, + 'kernel_regularizer': None, + 'name': 'dense_1', + 'trainable': True, + 'units': 1, + 'use_bias': True + }, + 'inbound_nodes': [[['dense', 0, 0, {}]]], + 'name': 'dense_1' + }], + 'name': 'model', + 'output_layers': [['dense_1', 0, 0]] +} + +# inputs = tf.keras.Input((256, 256, 3)) +# x = tf.keras.layers.Conv2D(filters=3, kernel_size=(3, 3))(inputs) +# x = tf.keras.layers.Flatten()(x) +# outputs = tf.keras.layers.Dense(1)(x) +# model = tf.keras.Model(inputs, outputs) +FUNCTIONAL_CNN = { + 'input_layers': [['input_2', 0, 0]], + 'layers': [{ + 'class_name': 'InputLayer', + 'config': { + 'batch_input_shape': (None, 256, 256, 3), + 'dtype': 'float32', + 'name': 'input_2', + 'ragged': False, + 'sparse': False + }, + 'inbound_nodes': [], + 'name': 'input_2' + }, { + 'class_name': 'Conv2D', + 'config': { + 'activation': 'linear', + 'activity_regularizer': None, + 'bias_constraint': None, + 'bias_initializer': { + 'class_name': 'Zeros', + 'config': {} + }, + 'bias_regularizer': None, + 'data_format': 'channels_last', + 'dilation_rate': (1, 1), + 'dtype': 'float32', + 'filters': 3, + 'kernel_constraint': None, + 'kernel_initializer': { + 'class_name': 'GlorotUniform', + 'config': { + 'seed': None + } + }, + 'kernel_regularizer': None, + 'kernel_size': (3, 3), + 'name': 'conv2d', + 'padding': 'valid', + 'strides': (1, 1), + 'trainable': True, + 'use_bias': True + }, + 'inbound_nodes': [[['input_2', 0, 0, {}]]], + 'name': 'conv2d' + }, { + 'class_name': 'Flatten', + 'config': { + 'data_format': 'channels_last', + 'dtype': 'float32', + 'name': 'flatten', + 'trainable': True + }, + 'inbound_nodes': [[['conv2d', 0, 0, {}]]], + 'name': 'flatten' + }, { + 'class_name': 'Dense', + 'config': { + 'activation': 'linear', + 'activity_regularizer': None, + 'bias_constraint': None, + 'bias_initializer': { + 'class_name': 'Zeros', + 'config': {} + }, + 'bias_regularizer': None, + 'dtype': 'float32', + 'kernel_constraint': None, + 'kernel_initializer': { + 'class_name': 'GlorotUniform', + 'config': { + 'seed': None + } + }, + 'kernel_regularizer': None, + 'name': 'dense_2', + 'trainable': True, + 'units': 1, + 'use_bias': True + }, + 'inbound_nodes': [[['flatten', 0, 0, {}]]], + 'name': 'dense_2' + }], + 'name': 'model_1', + 'output_layers': [['dense_2', 0, 0]] +} + +# inputs = tf.keras.Input((10, 3)) +# x = tf.keras.layers.LSTM(10)(inputs) +# outputs = tf.keras.layers.Dense(1)(x) +# model = tf.keras.Model(inputs, outputs) +FUNCTIONAL_LSTM = { + 'input_layers': [['input_5', 0, 0]], + 'layers': [{ + 'class_name': 'InputLayer', + 'config': { + 'batch_input_shape': (None, 10, 3), + 'dtype': 'float32', + 'name': 'input_5', + 'ragged': False, + 'sparse': False + }, + 'inbound_nodes': [], + 'name': 'input_5' + }, { + 'class_name': 'LSTM', + 'config': { + 'activation': 'tanh', + 'activity_regularizer': None, + 'bias_constraint': None, + 'bias_initializer': { + 'class_name': 'Zeros', + 'config': {} + }, + 'bias_regularizer': None, + 'dropout': 0.0, + 'dtype': 'float32', + 'go_backwards': False, + 'implementation': 2, + 'kernel_constraint': None, + 'kernel_initializer': { + 'class_name': 'GlorotUniform', + 'config': { + 'seed': None + } + }, + 'kernel_regularizer': None, + 'name': 'lstm_2', + 'recurrent_activation': 'sigmoid', + 'recurrent_constraint': None, + 'recurrent_dropout': 0.0, + 'recurrent_initializer': { + 'class_name': 'Orthogonal', + 'config': { + 'gain': 1.0, + 'seed': None + } + }, + 'recurrent_regularizer': None, + 'return_sequences': False, + 'return_state': False, + 'stateful': False, + 'time_major': False, + 'trainable': True, + 'unit_forget_bias': True, + 'units': 10, + 'unroll': False, + 'use_bias': True + }, + 'inbound_nodes': [[['input_5', 0, 0, {}]]], + 'name': 'lstm_2' + }, { + 'class_name': 'Dense', + 'config': { + 'activation': 'linear', + 'activity_regularizer': None, + 'bias_constraint': None, + 'bias_initializer': { + 'class_name': 'Zeros', + 'config': {} + }, + 'bias_regularizer': None, + 'dtype': 'float32', + 'kernel_constraint': None, + 'kernel_initializer': { + 'class_name': 'GlorotUniform', + 'config': { + 'seed': None + } + }, + 'kernel_regularizer': None, + 'name': 'dense_4', + 'trainable': True, + 'units': 1, + 'use_bias': True + }, + 'inbound_nodes': [[['lstm_2', 0, 0, {}]]], + 'name': 'dense_4' + }], + 'name': 'model_3', + 'output_layers': [['dense_4', 0, 0]] +} + +# model = tf.keras.Sequential() +# model.add(tf.keras.layers.Dense(10)) +# model.add(tf.keras.layers.Dense(1)) +SEQUENTIAL_DNN = { + 'layers': [{ + 'class_name': 'Dense', + 'config': { + 'activation': 'linear', + 'activity_regularizer': None, + 'bias_constraint': None, + 'bias_initializer': { + 'class_name': 'Zeros', + 'config': {} + }, + 'bias_regularizer': None, + 'dtype': 'float32', + 'kernel_constraint': None, + 'kernel_initializer': { + 'class_name': 'GlorotUniform', + 'config': { + 'seed': None + } + }, + 'kernel_regularizer': None, + 'name': 'dense_2', + 'trainable': True, + 'units': 10, + 'use_bias': True + } + }, { + 'class_name': 'Dense', + 'config': { + 'activation': 'linear', + 'activity_regularizer': None, + 'bias_constraint': None, + 'bias_initializer': { + 'class_name': 'Zeros', + 'config': {} + }, + 'bias_regularizer': None, + 'dtype': 'float32', + 'kernel_constraint': None, + 'kernel_initializer': { + 'class_name': 'GlorotUniform', + 'config': { + 'seed': None + } + }, + 'kernel_regularizer': None, + 'name': 'dense_3', + 'trainable': True, + 'units': 1, + 'use_bias': True + } + }], + 'name': 'sequential_1' +} + +# model = tf.keras.Sequential() +# model.add(tf.keras.layers.Conv2D(32, (3, 3))) +# model.add(tf.keras.layers.Flatten()) +# model.add(tf.keras.layers.Dense(1)) +SEQUENTIAL_CNN = { + 'layers': [{ + 'class_name': 'Conv2D', + 'config': { + 'activation': 'linear', + 'activity_regularizer': None, + 'bias_constraint': None, + 'bias_initializer': { + 'class_name': 'Zeros', + 'config': {} + }, + 'bias_regularizer': None, + 'data_format': 'channels_last', + 'dilation_rate': (1, 1), + 'dtype': 'float32', + 'filters': 32, + 'kernel_constraint': None, + 'kernel_initializer': { + 'class_name': 'GlorotUniform', + 'config': { + 'seed': None + } + }, + 'kernel_regularizer': None, + 'kernel_size': (3, 3), + 'name': 'conv2d_1', + 'padding': 'valid', + 'strides': (1, 1), + 'trainable': True, + 'use_bias': True + } + }, { + 'class_name': 'Flatten', + 'config': { + 'data_format': 'channels_last', + 'dtype': 'float32', + 'name': 'flatten_1', + 'trainable': True + } + }, { + 'class_name': 'Dense', + 'config': { + 'activation': 'linear', + 'activity_regularizer': None, + 'bias_constraint': None, + 'bias_initializer': { + 'class_name': 'Zeros', + 'config': {} + }, + 'bias_regularizer': None, + 'dtype': 'float32', + 'kernel_constraint': None, + 'kernel_initializer': { + 'class_name': 'GlorotUniform', + 'config': { + 'seed': None + } + }, + 'kernel_regularizer': None, + 'name': 'dense_6', + 'trainable': True, + 'units': 1, + 'use_bias': True + } + }], + 'name': 'sequential_4' +} + +# model = tf.keras.Sequential() +# model.add(tf.keras.layers.LSTM(10)) +# model.add(tf.keras.layers.Dense(1)) +SEQUENTIAL_LSTM = { + 'layers': [{ + 'class_name': 'LSTM', + 'config': { + 'activation': 'tanh', + 'activity_regularizer': None, + 'bias_constraint': None, + 'bias_initializer': { + 'class_name': 'Zeros', + 'config': {} + }, + 'bias_regularizer': None, + 'dropout': 0.0, + 'dtype': 'float32', + 'go_backwards': False, + 'implementation': 2, + 'kernel_constraint': None, + 'kernel_initializer': { + 'class_name': 'GlorotUniform', + 'config': { + 'seed': None + } + }, + 'kernel_regularizer': None, + 'name': 'lstm', + 'recurrent_activation': 'sigmoid', + 'recurrent_constraint': None, + 'recurrent_dropout': 0.0, + 'recurrent_initializer': { + 'class_name': 'Orthogonal', + 'config': { + 'gain': 1.0, + 'seed': None + } + }, + 'recurrent_regularizer': None, + 'return_sequences': False, + 'return_state': False, + 'stateful': False, + 'time_major': False, + 'trainable': True, + 'unit_forget_bias': True, + 'units': 10, + 'unroll': False, + 'use_bias': True + } + }, { + 'class_name': 'Dense', + 'config': { + 'activation': 'linear', + 'activity_regularizer': None, + 'bias_constraint': None, + 'bias_initializer': { + 'class_name': 'Zeros', + 'config': {} + }, + 'bias_regularizer': None, + 'dtype': 'float32', + 'kernel_constraint': None, + 'kernel_initializer': { + 'class_name': 'GlorotUniform', + 'config': { + 'seed': None + } + }, + 'kernel_regularizer': None, + 'name': 'dense_4', + 'trainable': True, + 'units': 1, + 'use_bias': True + } + }], + 'name': 'sequential_2' +} diff --git a/tensorflow/python/keras/tests/get_config_test.py b/tensorflow/python/keras/tests/get_config_test.py new file mode 100644 index 00000000000..3274447f9ed --- /dev/null +++ b/tensorflow/python/keras/tests/get_config_test.py @@ -0,0 +1,58 @@ +# Copyright 2020 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#,============================================================================ +"""Tests for `get_config` backwards compatibility.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.keras import keras_parameterized +from tensorflow.python.keras.engine import sequential +from tensorflow.python.keras.engine import training +from tensorflow.python.keras.tests import get_config_samples +from tensorflow.python.platform import test + + +@keras_parameterized.run_all_keras_modes +class TestGetConfigBackwardsCompatible(keras_parameterized.TestCase): + + def test_functional_dnn(self): + model = training.Model.from_config(get_config_samples.FUNCTIONAL_DNN) + self.assertLen(model.layers, 3) + + def test_functional_cnn(self): + model = training.Model.from_config(get_config_samples.FUNCTIONAL_CNN) + self.assertLen(model.layers, 4) + + def test_functional_lstm(self): + model = training.Model.from_config(get_config_samples.FUNCTIONAL_LSTM) + self.assertLen(model.layers, 3) + + def test_sequential_dnn(self): + model = sequential.Sequential.from_config(get_config_samples.SEQUENTIAL_DNN) + self.assertLen(model.layers, 2) + + def test_sequential_cnn(self): + model = sequential.Sequential.from_config(get_config_samples.SEQUENTIAL_CNN) + self.assertLen(model.layers, 3) + + def test_sequential_lstm(self): + model = sequential.Sequential.from_config( + get_config_samples.SEQUENTIAL_LSTM) + self.assertLen(model.layers, 2) + + +if __name__ == '__main__': + test.main()