1# Copyright 2018 The TensorFlow Authors. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# ============================================================================== 15"""Tests for numerical correctness.""" 16 17from absl.testing import parameterized 18import numpy as np 19 20from tensorflow.python import keras 21from tensorflow.python.keras import keras_parameterized 22from tensorflow.python.keras import testing_utils 23from tensorflow.python.platform import test 24 25 26class MultiInputSubclassed(keras.Model): 27 """Subclassed Model that adds its inputs and then adds a bias.""" 28 29 def __init__(self): 30 super(MultiInputSubclassed, self).__init__() 31 self.add = keras.layers.Add() 32 self.bias = testing_utils.Bias() 33 34 def call(self, inputs): 35 added = self.add(inputs) 36 return self.bias(added) 37 38 39def multi_input_functional(): 40 """Functional Model that adds its inputs and then adds a bias.""" 41 input_1 = keras.Input(shape=(1,)) 42 input_2 = keras.Input(shape=(1,)) 43 input_3 = keras.Input(shape=(1,)) 44 added = keras.layers.Add()([input_1, input_2, input_3]) 45 output = testing_utils.Bias()(added) 46 return keras.Model([input_1, input_2, input_3], output) 47 48 49@keras_parameterized.run_with_all_model_types 50@keras_parameterized.run_all_keras_modes 51class SimpleBiasTest(keras_parameterized.TestCase): 52 53 def _get_simple_bias_model(self): 54 model = testing_utils.get_model_from_layers([testing_utils.Bias()], 55 input_shape=(1,)) 56 model.compile( 57 keras.optimizer_v2.gradient_descent.SGD(0.1), 58 'mae', 59 run_eagerly=testing_utils.should_run_eagerly()) 60 return model 61 62 def test_simple_bias_fit(self): 63 x = np.array([[0.], [1.], [2.]]) 64 y = np.array([[0.5], [2.], [3.5]]) 65 model = self._get_simple_bias_model() 66 67 history = model.fit(x, y, batch_size=3, epochs=5) 68 self.assertAllClose(history.history['loss'], [1., 0.9, 0.8, 0.7, 0.6]) 69 70 def test_simple_bias_evaluate(self): 71 x = np.array([[0.], [1.], [2.]]) 72 y = np.array([[1.], [3.], [5.]]) 73 model = self._get_simple_bias_model() 74 75 loss = model.evaluate(x, y, batch_size=1) 76 self.assertAlmostEqual(loss, 2.) 77 78 def test_simple_bias_predict(self): 79 x = np.array([[0.], [1.], [2.]]) 80 model = self._get_simple_bias_model() 81 82 pred = model.predict(x, batch_size=1) 83 self.assertAllClose(x, pred) 84 85 86@keras_parameterized.run_all_keras_modes 87class MultipleInputTest(keras_parameterized.TestCase): 88 89 def _get_multiple_input_model(self, subclassed=True): 90 if subclassed: 91 model = MultiInputSubclassed() 92 else: 93 model = multi_input_functional() 94 model.compile( 95 keras.optimizer_v2.gradient_descent.SGD(0.1), 96 'mae', 97 run_eagerly=testing_utils.should_run_eagerly()) 98 return model 99 100 @parameterized.named_parameters(('subclassed', True), ('functional', False)) 101 def test_multiple_input_fit(self, subclassed): 102 x = [ 103 np.array([[1.], [2.], [3.]]), 104 np.array([[4.], [5.], [6.]]), 105 np.array([[7.], [8.], [9.]]) 106 ] 107 y = np.array([[12.5], [16.], [19.5]]) 108 109 model = self._get_multiple_input_model(subclassed) 110 history = model.fit(x, y, batch_size=3, epochs=5) 111 self.assertAllClose(history.history['loss'], [1., 0.9, 0.8, 0.7, 0.6]) 112 113 @parameterized.named_parameters(('subclassed', True), ('functional', False)) 114 def test_multiple_input_evaluate(self, subclassed): 115 x = [ 116 np.array([[1.], [2.], [3.]]), 117 np.array([[4.], [5.], [6.]]), 118 np.array([[7.], [8.], [9.]]) 119 ] 120 y = np.array([[13.], [17.], [21.]]) 121 122 model = self._get_multiple_input_model(subclassed) 123 loss = model.evaluate(x, y, batch_size=3) 124 self.assertAlmostEqual(loss, 2.) 125 126 @parameterized.named_parameters(('subclassed', True), ('functional', False)) 127 def test_multiple_input_predict(self, subclassed): 128 x = [ 129 np.array([[1.], [2.], [3.]]), 130 np.array([[4.], [5.], [6.]]), 131 np.array([[7.], [8.], [9.]]) 132 ] 133 134 model = self._get_multiple_input_model(subclassed) 135 pred = model.predict(x, batch_size=1) 136 self.assertAllClose(pred, [[12.], [15.], [18.]]) 137 138 139if __name__ == '__main__': 140 test.main() 141