1# Copyright 2016 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 GRU layer."""
16
17from __future__ import absolute_import
18from __future__ import division
19from __future__ import print_function
20
21from absl.testing import parameterized
22import numpy as np
23
24from tensorflow.python import keras
25from tensorflow.python.eager import context
26from tensorflow.python.framework import test_util as tf_test_util
27from tensorflow.python.keras import keras_parameterized
28from tensorflow.python.keras import testing_utils
29from tensorflow.python.platform import test
30
31
32@keras_parameterized.run_all_keras_modes
33class GRULayerTest(keras_parameterized.TestCase):
34
35  def test_return_sequences_GRU(self):
36    num_samples = 2
37    timesteps = 3
38    embedding_dim = 4
39    units = 2
40    testing_utils.layer_test(
41        keras.layers.GRU,
42        kwargs={'units': units,
43                'return_sequences': True},
44        input_shape=(num_samples, timesteps, embedding_dim))
45
46  def test_dynamic_behavior_GRU(self):
47    num_samples = 2
48    timesteps = 3
49    embedding_dim = 4
50    units = 2
51    layer = keras.layers.GRU(units, input_shape=(None, embedding_dim))
52    model = keras.models.Sequential()
53    model.add(layer)
54    model.compile(
55        'rmsprop', 'mse', run_eagerly=testing_utils.should_run_eagerly())
56    x = np.random.random((num_samples, timesteps, embedding_dim))
57    y = np.random.random((num_samples, units))
58    model.train_on_batch(x, y)
59
60  def test_dropout_GRU(self):
61    num_samples = 2
62    timesteps = 3
63    embedding_dim = 4
64    units = 2
65    testing_utils.layer_test(
66        keras.layers.GRU,
67        kwargs={'units': units,
68                'dropout': 0.1,
69                'recurrent_dropout': 0.1},
70        input_shape=(num_samples, timesteps, embedding_dim))
71
72  @parameterized.parameters([0, 1, 2])
73  def test_implementation_mode_GRU(self, implementation_mode):
74    num_samples = 2
75    timesteps = 3
76    embedding_dim = 4
77    units = 2
78    testing_utils.layer_test(
79        keras.layers.GRU,
80        kwargs={'units': units,
81                'implementation': implementation_mode},
82        input_shape=(num_samples, timesteps, embedding_dim))
83
84  def test_reset_after_GRU(self):
85    num_samples = 2
86    timesteps = 3
87    embedding_dim = 4
88    units = 2
89
90    (x_train, y_train), _ = testing_utils.get_test_data(
91        train_samples=num_samples,
92        test_samples=0,
93        input_shape=(timesteps, embedding_dim),
94        num_classes=units)
95    y_train = keras.utils.to_categorical(y_train, units)
96
97    inputs = keras.layers.Input(shape=[timesteps, embedding_dim])
98    gru_layer = keras.layers.GRU(units,
99                                 reset_after=True)
100    output = gru_layer(inputs)
101    gru_model = keras.models.Model(inputs, output)
102    gru_model.compile(
103        'rmsprop', 'mse', run_eagerly=testing_utils.should_run_eagerly())
104    gru_model.fit(x_train, y_train)
105    gru_model.predict(x_train)
106
107  def test_with_masking_layer_GRU(self):
108    layer_class = keras.layers.GRU
109    inputs = np.random.random((2, 3, 4))
110    targets = np.abs(np.random.random((2, 3, 5)))
111    targets /= targets.sum(axis=-1, keepdims=True)
112    model = keras.models.Sequential()
113    model.add(keras.layers.Masking(input_shape=(3, 4)))
114    model.add(layer_class(units=5, return_sequences=True, unroll=False))
115    model.compile(
116        loss='categorical_crossentropy',
117        optimizer='rmsprop',
118        run_eagerly=testing_utils.should_run_eagerly())
119    model.fit(inputs, targets, epochs=1, batch_size=2, verbose=1)
120
121  def test_statefulness_GRU(self):
122    num_samples = 2
123    timesteps = 3
124    embedding_dim = 4
125    units = 2
126    layer_class = keras.layers.GRU
127
128    model = keras.models.Sequential()
129    model.add(
130        keras.layers.Embedding(
131            4,
132            embedding_dim,
133            mask_zero=True,
134            input_length=timesteps,
135            batch_input_shape=(num_samples, timesteps)))
136    layer = layer_class(
137        units, return_sequences=False, stateful=True, weights=None)
138    model.add(layer)
139    model.compile(optimizer='sgd', loss='mse',
140                  run_eagerly=testing_utils.should_run_eagerly())
141    out1 = model.predict(np.ones((num_samples, timesteps)))
142    self.assertEqual(out1.shape, (num_samples, units))
143
144    # train once so that the states change
145    model.train_on_batch(
146        np.ones((num_samples, timesteps)), np.ones((num_samples, units)))
147    out2 = model.predict(np.ones((num_samples, timesteps)))
148
149    # if the state is not reset, output should be different
150    self.assertNotEqual(out1.max(), out2.max())
151
152    # check that output changes after states are reset
153    # (even though the model itself didn't change)
154    layer.reset_states()
155    out3 = model.predict(np.ones((num_samples, timesteps)))
156    self.assertNotEqual(out2.max(), out3.max())
157
158    # check that container-level reset_states() works
159    model.reset_states()
160    out4 = model.predict(np.ones((num_samples, timesteps)))
161    np.testing.assert_allclose(out3, out4, atol=1e-5)
162
163    # check that the call to `predict` updated the states
164    out5 = model.predict(np.ones((num_samples, timesteps)))
165    self.assertNotEqual(out4.max(), out5.max())
166
167    # Check masking
168    layer.reset_states()
169
170    left_padded_input = np.ones((num_samples, timesteps))
171    left_padded_input[0, :1] = 0
172    left_padded_input[1, :2] = 0
173    out6 = model.predict(left_padded_input)
174
175    layer.reset_states()
176
177    right_padded_input = np.ones((num_samples, timesteps))
178    right_padded_input[0, -1:] = 0
179    right_padded_input[1, -2:] = 0
180    out7 = model.predict(right_padded_input)
181
182    np.testing.assert_allclose(out7, out6, atol=1e-5)
183
184
185@tf_test_util.run_all_in_graph_and_eager_modes
186class GRULayerGenericTest(test.TestCase):
187
188  def test_constraints_GRU(self):
189    embedding_dim = 4
190    layer_class = keras.layers.GRU
191    k_constraint = keras.constraints.max_norm(0.01)
192    r_constraint = keras.constraints.max_norm(0.01)
193    b_constraint = keras.constraints.max_norm(0.01)
194    layer = layer_class(
195        5,
196        return_sequences=False,
197        weights=None,
198        input_shape=(None, embedding_dim),
199        kernel_constraint=k_constraint,
200        recurrent_constraint=r_constraint,
201        bias_constraint=b_constraint)
202    layer.build((None, None, embedding_dim))
203    self.assertEqual(layer.cell.kernel.constraint, k_constraint)
204    self.assertEqual(layer.cell.recurrent_kernel.constraint, r_constraint)
205    self.assertEqual(layer.cell.bias.constraint, b_constraint)
206
207  def test_from_config_GRU(self):
208    layer_class = keras.layers.GRU
209    for stateful in (False, True):
210      l1 = layer_class(units=1, stateful=stateful)
211      l2 = layer_class.from_config(l1.get_config())
212      assert l1.get_config() == l2.get_config()
213
214  def test_regularizers_GRU(self):
215    embedding_dim = 4
216    layer_class = keras.layers.GRU
217    layer = layer_class(
218        5,
219        return_sequences=False,
220        weights=None,
221        input_shape=(None, embedding_dim),
222        kernel_regularizer=keras.regularizers.l1(0.01),
223        recurrent_regularizer=keras.regularizers.l1(0.01),
224        bias_regularizer='l2',
225        activity_regularizer='l1')
226    layer.build((None, None, 2))
227    self.assertEqual(len(layer.losses), 3)
228
229    x = keras.backend.variable(np.ones((2, 3, 2)))
230    layer(x)
231    if context.executing_eagerly():
232      self.assertEqual(len(layer.losses), 4)
233    else:
234      self.assertEqual(len(layer.get_losses_for(x)), 1)
235
236
237if __name__ == '__main__':
238  test.main()
239