• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 training routines."""
16
17import collections
18import io
19import sys
20
21from absl.testing import parameterized
22import numpy as np
23
24from tensorflow.python.data.ops import dataset_ops
25from tensorflow.python.eager import context
26from tensorflow.python.eager import def_function
27from tensorflow.python.framework import ops
28from tensorflow.python.framework import tensor_shape
29from tensorflow.python.framework import test_util as tf_test_util
30from tensorflow.python.keras import backend
31from tensorflow.python.keras import combinations
32from tensorflow.python.keras import keras_parameterized
33from tensorflow.python.keras import layers as layers_module
34from tensorflow.python.keras import losses
35from tensorflow.python.keras import metrics as metrics_module
36from tensorflow.python.keras import optimizer_v2
37from tensorflow.python.keras import testing_utils
38from tensorflow.python.keras.callbacks import Callback
39from tensorflow.python.keras.engine import input_layer
40from tensorflow.python.keras.engine import sequential
41from tensorflow.python.keras.engine import training as training_module
42from tensorflow.python.keras.engine import training_utils_v1
43from tensorflow.python.keras.utils import data_utils
44from tensorflow.python.keras.utils import np_utils
45from tensorflow.python.ops import array_ops
46from tensorflow.python.ops import init_ops
47from tensorflow.python.ops import math_ops
48from tensorflow.python.ops import nn_ops
49from tensorflow.python.ops import sparse_ops
50from tensorflow.python.ops import state_ops
51from tensorflow.python.ops import template
52from tensorflow.python.ops import variable_scope
53from tensorflow.python.ops import variables as variables_module
54from tensorflow.python.platform import test
55from tensorflow.python.platform import tf_logging as logging
56from tensorflow.python.training.rmsprop import RMSPropOptimizer
57
58try:
59  import scipy.sparse as scipy_sparse  # pylint: disable=g-import-not-at-top
60except ImportError:
61  scipy_sparse = None
62
63
64class TrainingTest(keras_parameterized.TestCase):
65
66  @keras_parameterized.run_all_keras_modes
67  @keras_parameterized.run_with_all_model_types
68  def test_model_instrumentation(self):
69    layers = [
70        layers_module.Dense(10, dtype=np.float64),
71        layers_module.Dense(10, dtype=np.float64)
72    ]
73    model = testing_utils.get_model_from_layers(layers, input_shape=(1,))
74
75    self.assertTrue(model._instrumented_keras_api)
76    self.assertTrue(model._instrumented_keras_model_class)
77    self.assertFalse(model._instrumented_keras_layer_class)
78
79  @keras_parameterized.run_with_all_model_types
80  @keras_parameterized.run_all_keras_modes
81  def test_fit_training_arg(self):
82
83    class ReturnTraining(layers_module.Layer):
84
85      def call(self, inputs, training):
86        if training:
87          return inputs + array_ops.constant([100], 'float32')
88        else:
89          return inputs + array_ops.constant([0], 'float32')
90
91    model = sequential.Sequential([ReturnTraining()])
92    model.compile(
93        'sgd',
94        'mse',
95        run_eagerly=testing_utils.should_run_eagerly())
96    hist = model.fit(x=np.array([0.]), y=np.array([0.]))
97    self.assertAllClose(hist.history['loss'][0], 10000)
98
99  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
100  def test_fit_on_empty(self):
101    model = sequential.Sequential([layers_module.Dense(1)])
102    model.compile('sgd', 'mse', run_eagerly=testing_utils.should_run_eagerly())
103    with self.assertRaisesRegex(ValueError,
104                                'Expect x to be a non-empty array or dataset.'):
105      model.fit(x=np.array([]), y=np.array([]))
106
107  @keras_parameterized.run_all_keras_modes
108  def test_run_eagerly_setting(self):
109    model = sequential.Sequential([layers_module.Dense(1)])
110    run_eagerly = testing_utils.should_run_eagerly()
111    model.compile('sgd', 'mse', run_eagerly=run_eagerly)
112    self.assertEqual(model.run_eagerly, run_eagerly)
113
114  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
115  @parameterized.named_parameters(
116      ('train_on_batch', 'train_on_batch'),
117      ('test_on_batch', 'test_on_batch'),
118      ('predict_on_batch', 'predict_on_batch'),
119      ('fit', 'fit'),
120      ('evaluate', 'evaluate'),
121      ('predict', 'predict'),
122  )
123  def test_disallow_methods_inside_tf_function(self, method_name):
124    model = sequential.Sequential([layers_module.Dense(1)])
125    run_eagerly = testing_utils.should_run_eagerly()
126    model.compile('sgd', 'mse', run_eagerly=run_eagerly)
127
128    @def_function.function
129    def my_fn():
130      getattr(model, method_name)(1)
131
132    error_msg = 'inside a `tf.function`'
133    with self.assertRaisesRegex(RuntimeError, error_msg):
134      my_fn()
135
136  @keras_parameterized.run_all_keras_modes
137  def test_fit_and_validate_learning_phase(self):
138
139    class ReturnTraining(layers_module.Layer):
140
141      def call(self, inputs):
142        return backend.in_train_phase(lambda: array_ops.ones_like(inputs),
143                                      lambda: array_ops.zeros_like(inputs))
144
145    model = sequential.Sequential([ReturnTraining(input_shape=(2,))])
146    model.compile(
147        'sgd',
148        loss='mae',
149        run_eagerly=testing_utils.should_run_eagerly())
150
151    inputs = np.ones((40, 2), dtype=np.float32)
152    targets = np.ones((40, 1), dtype=np.float32)
153
154    # Test correctness with `steps_per_epoch`.
155    train_dataset = dataset_ops.Dataset.from_tensor_slices(
156        (inputs, targets)).batch(10)
157    val_dataset = dataset_ops.Dataset.from_tensor_slices(
158        (inputs, targets)).batch(10)
159    history = model.fit(
160        train_dataset, epochs=2, verbose=1, validation_data=val_dataset)
161
162    # The training loss should be 0.0
163    self.assertAllClose(history.history['loss'][0], 0.0)
164    # The validation loss should be 1.0.
165    self.assertAllClose(history.history['val_loss'][0], 1.0)
166
167  @keras_parameterized.run_all_keras_modes
168  def test_fit_and_validate_training_arg(self):
169
170    class ReturnTraining(layers_module.Layer):
171
172      def call(self, inputs, training=None):
173        return backend.in_train_phase(
174            lambda: array_ops.ones_like(inputs),
175            lambda: array_ops.zeros_like(inputs),
176            training=training)
177
178    model = sequential.Sequential([ReturnTraining(input_shape=(2,))])
179    model.compile(
180        'sgd',
181        loss='mae',
182        run_eagerly=testing_utils.should_run_eagerly())
183
184    inputs = np.ones((40, 2), dtype=np.float32)
185    targets = np.ones((40, 1), dtype=np.float32)
186
187    # Test correctness with `steps_per_epoch`.
188    train_dataset = dataset_ops.Dataset.from_tensor_slices(
189        (inputs, targets)).batch(10)
190    val_dataset = dataset_ops.Dataset.from_tensor_slices(
191        (inputs, targets)).batch(10)
192    history = model.fit(
193        train_dataset, epochs=2, verbose=1, validation_data=val_dataset)
194
195    # The training loss should be 0.0
196    self.assertAllClose(history.history['loss'][0], 0.0)
197    # The validation loss should be 1.0.
198    self.assertAllClose(history.history['val_loss'][0], 1.0)
199
200  @keras_parameterized.run_all_keras_modes
201  @keras_parameterized.run_with_all_model_types
202  def test_target_dtype_matches_output(self):
203
204    def loss_fn(labels, preds):
205      self.assertEqual(labels.dtype, preds.dtype)
206      return labels - preds
207
208    layers = [
209        layers_module.Dense(10, dtype=np.float64),
210        layers_module.Dense(10, dtype=np.float64)
211    ]
212    model = testing_utils.get_model_from_layers(layers, input_shape=(1,))
213    inputs = np.ones(10, dtype=np.float64)
214    targets = np.ones(10, dtype=np.float64)
215    model.compile(
216        'sgd',
217        loss=loss_fn,
218        run_eagerly=testing_utils.should_run_eagerly())
219    model.train_on_batch(inputs, targets)
220    model.test_on_batch(inputs, targets)
221    self.assertEqual(model.predict(inputs).dtype, np.float64)
222
223  @keras_parameterized.run_all_keras_modes
224  def test_fit_and_validate_nested_training_arg(self):
225
226    class NestedReturnTraining(layers_module.Layer):
227
228      def call(self, inputs, training=None):
229        return backend.in_train_phase(
230            lambda: array_ops.ones_like(inputs),
231            lambda: array_ops.zeros_like(inputs),
232            training=training)
233
234    class ReturnTraining(layers_module.Layer):
235
236      def __init__(self, input_shape=None, **kwargs):
237        super(ReturnTraining, self).__init__(input_shape=input_shape, **kwargs)
238        self._nested_layer = None
239
240      def build(self, input_shape):
241        self._nested_layer = NestedReturnTraining()
242        self.built = True
243
244      def call(self, inputs):
245        return self._nested_layer(inputs)
246
247    model = sequential.Sequential([ReturnTraining(input_shape=(2,))])
248    model.compile(
249        'sgd',
250        loss='mae',
251        run_eagerly=testing_utils.should_run_eagerly())
252
253    inputs = np.ones((40, 2), dtype=np.float32)
254    targets = np.ones((40, 1), dtype=np.float32)
255
256    # Test correctness with `steps_per_epoch`.
257    train_dataset = dataset_ops.Dataset.from_tensor_slices(
258        (inputs, targets)).batch(10)
259    val_dataset = dataset_ops.Dataset.from_tensor_slices(
260        (inputs, targets)).batch(10)
261    history = model.fit(
262        train_dataset, epochs=2, verbose=1, validation_data=val_dataset)
263
264    # The training loss should be 0.0
265    self.assertAllClose(history.history['loss'][0], 0.0)
266    # The validation loss should be 1.0.
267    self.assertAllClose(history.history['val_loss'][0], 1.0)
268
269  @keras_parameterized.run_with_all_model_types(exclude_models='sequential')
270  @keras_parameterized.run_all_keras_modes
271  def test_fit_on_arrays(self):
272    input_a = layers_module.Input(shape=(3,), name='input_a')
273    input_b = layers_module.Input(shape=(3,), name='input_b')
274
275    dense = layers_module.Dense(4, name='dense')
276    dropout = layers_module.Dropout(0.5, name='dropout')
277    branch_a = [input_a, dense]
278    branch_b = [input_b, dense, dropout]
279
280    model = testing_utils.get_multi_io_model(branch_a, branch_b)
281
282    optimizer = RMSPropOptimizer(learning_rate=0.001)
283    loss = 'mse'
284    loss_weights = [1., 0.5]
285    model.compile(
286        optimizer,
287        loss,
288        metrics=[metrics_module.CategoricalAccuracy(), 'mae'],
289        loss_weights=loss_weights,
290        run_eagerly=testing_utils.should_run_eagerly())
291
292    input_a_np = np.random.random((10, 3))
293    input_b_np = np.random.random((10, 3))
294
295    output_d_np = np.random.random((10, 4))
296    output_e_np = np.random.random((10, 4))
297
298    # Test fit at different verbosity
299    model.fit(
300        [input_a_np, input_b_np], [output_d_np, output_e_np],
301        epochs=1,
302        batch_size=5,
303        verbose=0)
304    model.fit(
305        [input_a_np, input_b_np], [output_d_np, output_e_np],
306        epochs=1,
307        batch_size=5,
308        verbose=1)
309    model.fit(
310        [input_a_np, input_b_np], [output_d_np, output_e_np],
311        epochs=2,
312        batch_size=5,
313        verbose=2)
314    model.train_on_batch([input_a_np, input_b_np], [output_d_np, output_e_np])
315
316    # Test with validation data
317    model.fit(
318        [input_a_np, input_b_np], [output_d_np, output_e_np],
319        validation_data=([input_a_np, input_b_np], [output_d_np,
320                                                    output_e_np]),
321        epochs=1,
322        batch_size=5,
323        verbose=0)
324    model.fit(
325        [input_a_np, input_b_np], [output_d_np, output_e_np],
326        validation_data=([input_a_np, input_b_np], [output_d_np,
327                                                    output_e_np]),
328        epochs=2,
329        batch_size=5,
330        verbose=1)
331    model.fit(
332        [input_a_np, input_b_np], [output_d_np, output_e_np],
333        validation_data=([input_a_np, input_b_np], [output_d_np,
334                                                    output_e_np]),
335        epochs=2,
336        batch_size=5,
337        verbose=2)
338    # Test with validation split
339    model.fit(
340        [input_a_np, input_b_np], [output_d_np, output_e_np],
341        epochs=2,
342        batch_size=5,
343        verbose=0,
344        validation_split=0.2)
345
346    if testing_utils.get_model_type() == 'functional':
347      # Test with dictionary inputs
348      model.fit(
349          {
350              'input_a': input_a_np,
351              'input_b': input_b_np
352          }, {
353              'dense': output_d_np,
354              'dropout': output_e_np
355          },
356          epochs=1,
357          batch_size=5,
358          verbose=0)
359      model.fit(
360          {
361              'input_a': input_a_np,
362              'input_b': input_b_np
363          }, {
364              'dense': output_d_np,
365              'dropout': output_e_np
366          },
367          epochs=1,
368          batch_size=5,
369          verbose=1)
370      model.fit(
371          {
372              'input_a': input_a_np,
373              'input_b': input_b_np
374          }, {
375              'dense': output_d_np,
376              'dropout': output_e_np
377          },
378          validation_data=({
379              'input_a': input_a_np,
380              'input_b': input_b_np
381          }, {
382              'dense': output_d_np,
383              'dropout': output_e_np
384          }),
385          epochs=1,
386          batch_size=5,
387          verbose=0)
388      model.train_on_batch({
389          'input_a': input_a_np,
390          'input_b': input_b_np
391      }, {
392          'dense': output_d_np,
393          'dropout': output_e_np
394      })
395
396    # Test with lists for loss, metrics
397    loss = ['mae', 'mse']
398    model.compile(
399        optimizer,
400        loss,
401        metrics=[metrics_module.CategoricalAccuracy(), 'mae'],
402        run_eagerly=testing_utils.should_run_eagerly())
403    model.fit(
404        [input_a_np, input_b_np], [output_d_np, output_e_np],
405        epochs=1,
406        batch_size=5,
407        verbose=0)
408
409    # Test with dictionaries for loss, metrics, loss weights
410    if testing_utils.get_model_type() == 'functional':
411      loss = {'dense': 'mse', 'dropout': 'mae'}
412      loss_weights = {'dense': 1., 'dropout': 0.5}
413      metrics = {
414          'dense': 'mse',
415          'dropout': metrics_module.CategoricalAccuracy()
416      }
417      model.compile(
418          optimizer,
419          loss,
420          metrics=metrics,
421          loss_weights=loss_weights,
422          run_eagerly=testing_utils.should_run_eagerly())
423    model.fit(
424        [input_a_np, input_b_np], [output_d_np, output_e_np],
425        epochs=1,
426        batch_size=5,
427        verbose=0)
428
429    # Build single-input model
430    x = layers_module.Input(shape=(3,), name='input_a')
431    y = layers_module.Dense(4)(x)
432    model = training_module.Model(x, y)
433    model.compile(
434        optimizer,
435        loss='mse',
436        run_eagerly=testing_utils.should_run_eagerly())
437    # This will work
438    model.fit([input_a_np], output_d_np, epochs=1)
439
440    # Test model on a list of floats
441    input_a_np = np.random.random((10, 3))
442    input_b_np = np.random.random((10, 4))
443
444    # Test execution on inputs that are lists of scalars.
445    # TF2 and TF1 have slightly different semantics:
446    if context.executing_eagerly():
447      # In TF2 to avoid any ambiguity when there are nested lists
448      # the entire input gets converted to a
449      # single numpy array (& it only works in the case of a single io model)
450      model.fit(np.ndarray.tolist(input_a_np),
451                np.ndarray.tolist(input_b_np),
452                epochs=2,
453                batch_size=5,
454                verbose=2)
455    else:
456      # In TF1 there was logic to try disambiguating between the individual
457      # inputs when lists are nested. This allowed multi-io functional models
458      # to support lists of scalars as input, but it caused ambiguity issues
459      # for subclass models & made it trickier to pass multi-dimensional inputs
460      # as lists of scalars to single io models. This was an excessive amount
461      # of complexity for what boiled down to a convenience method we were
462      # mainly just using for writing tests.
463      model.fit([np.ndarray.tolist(input_a_np)],
464                [np.ndarray.tolist(input_b_np)],
465                epochs=2,
466                batch_size=5,
467                verbose=2)
468
469  @keras_parameterized.run_all_keras_modes
470  def test_evaluate_predict_on_arrays(self):
471    a = layers_module.Input(shape=(3,), name='input_a')
472    b = layers_module.Input(shape=(3,), name='input_b')
473
474    dense = layers_module.Dense(4, name='dense')
475    c = dense(a)
476    d = dense(b)
477    e = layers_module.Dropout(0.5, name='dropout')(c)
478
479    model = training_module.Model([a, b], [d, e])
480
481    optimizer = RMSPropOptimizer(learning_rate=0.001)
482    loss = 'mse'
483    loss_weights = [1., 0.5]
484    model.compile(
485        optimizer,
486        loss,
487        metrics=['mae', metrics_module.CategoricalAccuracy()],
488        loss_weights=loss_weights,
489        sample_weight_mode=None,
490        run_eagerly=testing_utils.should_run_eagerly())
491
492    input_a_np = np.random.random((10, 3))
493    input_b_np = np.random.random((10, 3))
494
495    output_d_np = np.random.random((10, 4))
496    output_e_np = np.random.random((10, 4))
497
498    # Test evaluate at different verbosity
499    out = model.evaluate(
500        [input_a_np, input_b_np], [output_d_np, output_e_np],
501        batch_size=5,
502        verbose=0)
503    self.assertEqual(len(out), 7)
504    out = model.evaluate(
505        [input_a_np, input_b_np], [output_d_np, output_e_np],
506        batch_size=5,
507        verbose=1)
508    self.assertEqual(len(out), 7)
509    out = model.evaluate(
510        [input_a_np, input_b_np], [output_d_np, output_e_np],
511        batch_size=5,
512        verbose=2)
513    self.assertEqual(len(out), 7)
514    out = model.test_on_batch([input_a_np, input_b_np],
515                              [output_d_np, output_e_np])
516    self.assertEqual(len(out), 7)
517
518    # Test evaluate with dictionary inputs
519    model.evaluate(
520        {
521            'input_a': input_a_np,
522            'input_b': input_b_np
523        }, {
524            'dense': output_d_np,
525            'dropout': output_e_np
526        },
527        batch_size=5,
528        verbose=0)
529    model.evaluate(
530        {
531            'input_a': input_a_np,
532            'input_b': input_b_np
533        }, {
534            'dense': output_d_np,
535            'dropout': output_e_np
536        },
537        batch_size=5,
538        verbose=1)
539
540    # Test predict
541    out = model.predict([input_a_np, input_b_np], batch_size=5)
542    self.assertEqual(len(out), 2)
543    out = model.predict({'input_a': input_a_np, 'input_b': input_b_np})
544    self.assertEqual(len(out), 2)
545    out = model.predict_on_batch({
546        'input_a': input_a_np,
547        'input_b': input_b_np
548    })
549    self.assertEqual(len(out), 2)
550
551  def _make_sequence_input_functions(self, input_type):
552    # train and test
553    xy_namedtuple = collections.namedtuple('xy_namedtuple', ['x', 'y'])
554
555    # predict
556    x_namedtuple = collections.namedtuple('x_namedtuple', ['x'])
557
558    if input_type == 'dataset':
559      dataset = dataset_ops.Dataset.range(16).map(
560          lambda _: array_ops.ones(shape=(1,)))
561
562      xy_dataset = dataset_ops.Dataset.zip((dataset, dataset)).batch(4)
563      x_dataset = dataset.batch(4)
564      def xy_function(use_namedtuple):
565        return xy_dataset.map(xy_namedtuple) if use_namedtuple else xy_dataset
566
567      def x_function(use_namedtuple):
568        return x_dataset.map(x_namedtuple) if use_namedtuple else x_dataset
569
570      return xy_function, x_function
571
572    elif input_type == 'generator':
573      def xy_generator(use_namedtuple):
574        x, y = np.ones((4, 1)), np.ones((4, 1))
575        for _ in range(4):
576          if use_namedtuple:
577            yield xy_namedtuple(x, y)
578          else:
579            yield x, y
580
581      def x_generator(use_namedtuple):
582        x = np.ones((4, 1))
583        for _ in range(4):
584          if use_namedtuple:
585            yield x_namedtuple(x)
586          else:
587            yield x
588
589      return xy_generator, x_generator
590
591    elif input_type == 'sequence':
592      class XYSequence(data_utils.Sequence):
593
594        def __init__(self, use_namedtuple):
595          self._use_namedtuple = use_namedtuple
596          super(XYSequence, self).__init__()
597
598        def __getitem__(self, idx):
599          x, y = np.ones((4, 1)), np.ones((4, 1))
600          if self._use_namedtuple:
601            return xy_namedtuple(x, y)
602          return x, y
603
604        def __len__(self):
605          return 4
606
607      class XSequence(data_utils.Sequence):
608
609        def __init__(self, use_namedtuple):
610          self._use_namedtuple = use_namedtuple
611          super(XSequence, self).__init__()
612
613        def __getitem__(self, idx):
614          x = np.ones((4, 1))
615          if self._use_namedtuple:
616            return x_namedtuple(x)
617          return x
618
619        def __len__(self):
620          return 4
621
622      return XYSequence, XSequence
623
624  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
625  @keras_parameterized.run_with_all_model_types
626  @parameterized.named_parameters(
627      ('dataset', 'dataset'),
628      ('generator', 'generator'),
629      ('sequence', 'sequence'),
630  )
631  def test_sequence_input_types(self, input_type):
632    """Ensure that namedtuples and tuples are plumbed identically."""
633    if not context.executing_eagerly():
634      self.skipTest('Improved checking is only present in data_adapter.')
635
636    xy_function, x_function = self._make_sequence_input_functions(input_type)
637    fit_kwargs, evaluate_kwargs, predict_kwargs = {}, {}, {}
638    if input_type == 'generator':
639      fit_kwargs['steps_per_epoch'] = 4
640      evaluate_kwargs['steps'] = 4
641      predict_kwargs['steps'] = 4
642
643    model = testing_utils.get_small_mlp(1, 1, 1)
644    model.compile(
645        loss='mse',
646        optimizer='sgd',
647        run_eagerly=testing_utils.should_run_eagerly())
648
649    model.fit(xy_function(use_namedtuple=False), **fit_kwargs)
650    model.evaluate(xy_function(use_namedtuple=False), **evaluate_kwargs)
651    model.predict(x_function(use_namedtuple=False), **predict_kwargs)
652
653  @keras_parameterized.run_all_keras_modes
654  def test_custom_mapping_in_config(self):
655
656    class MyModel(training_module.Model):
657
658      def call(self, inputs):
659        return inputs
660
661      def get_config(self):
662        self.a = {}
663        return {'a': self.a}
664
665    model = MyModel()
666    self.assertIn('{"a": {}}', model.to_json())
667
668  def test_training_on_sparse_data_with_dense_placeholders_v1(self):
669    with ops.Graph().as_default():
670      if scipy_sparse is None:
671        return
672
673      test_inputs = [
674          scipy_sparse.random(6, 3, density=0.25).tocsr() for _ in range(2)
675      ]
676      test_outputs = [
677          scipy_sparse.random(6, i, density=0.25).tocsr() for i in range(3, 5)
678      ]
679      in1 = layers_module.Input(shape=(3,))
680      in2 = layers_module.Input(shape=(3,))
681      out1 = layers_module.Dropout(0.5, name='dropout')(in1)
682      out2 = layers_module.Dense(4, name='dense_1')(in2)
683      model = training_module.Model([in1, in2], [out1, out2])
684      model.predict(test_inputs, batch_size=2)
685      optimizer = 'rmsprop'
686      model.compile(
687          optimizer,
688          'mse',
689          metrics=['mae', metrics_module.CategoricalAccuracy()])
690      model.fit(test_inputs, test_outputs,
691                epochs=1, batch_size=2, validation_split=0.5)
692      model.evaluate(test_inputs, test_outputs, batch_size=2)
693
694  @keras_parameterized.run_all_keras_modes
695  def test_compile_with_sparse_placeholders(self):
696    inputs = layers_module.Input(shape=(10,), sparse=True)
697    weights = variables_module.Variable(
698        np.ones((10, 1)).astype(np.float32), name='weights')
699    weights_mult = lambda x: sparse_ops.sparse_tensor_dense_matmul(x, weights)
700    output_layer = layers_module.Lambda(weights_mult)(inputs)
701    model = training_module.Model([inputs], output_layer)
702    model.compile(
703        loss='binary_crossentropy',
704        optimizer='adam',
705        metrics=['accuracy'],
706        run_eagerly=testing_utils.should_run_eagerly())
707
708  @keras_parameterized.run_all_keras_modes
709  def test_that_trainable_disables_updates(self):
710    val_a = np.random.random((10, 4))
711    val_out = np.random.random((10, 4))
712
713    a = layers_module.Input(shape=(4,))
714    layer = layers_module.BatchNormalization(input_shape=(4,))
715    b = layer(a)
716    model = training_module.Model(a, b)
717
718    model.trainable = False
719    if not ops.executing_eagerly_outside_functions():
720      self.assertEmpty(model.updates)
721
722    model.compile(
723        'sgd',
724        'mse',
725        run_eagerly=testing_utils.should_run_eagerly())
726    if not ops.executing_eagerly_outside_functions():
727      self.assertEmpty(model.updates)
728
729    x1 = model.predict(val_a)
730    model.train_on_batch(val_a, val_out)
731    x2 = model.predict(val_a)
732    self.assertAllClose(x1, x2, atol=1e-7)
733
734    model.trainable = True
735    model.compile(
736        'sgd',
737        'mse',
738        run_eagerly=testing_utils.should_run_eagerly())
739    if not ops.executing_eagerly_outside_functions():
740      self.assertAllGreater(len(model.updates), 0)
741
742    model.train_on_batch(val_a, val_out)
743    x2 = model.predict(val_a)
744    assert np.abs(np.sum(x1 - x2)) > 1e-5
745
746    layer.trainable = False
747    model.compile(
748        'sgd',
749        'mse',
750        run_eagerly=testing_utils.should_run_eagerly())
751    if not ops.executing_eagerly_outside_functions():
752      self.assertEmpty(model.updates)
753
754    x1 = model.predict(val_a)
755    model.train_on_batch(val_a, val_out)
756    x2 = model.predict(val_a)
757    self.assertAllClose(x1, x2, atol=1e-7)
758
759  def test_weight_deduplication_in_methods(self):
760    inp = layers_module.Input(shape=(1,))
761    bn = layers_module.BatchNormalization()
762    d = layers_module.Dense(1)
763
764    m0 = training_module.Model(inp, d(bn(inp)))
765    m1 = training_module.Model(inp, d(bn(inp)))
766
767    x0 = m0(inp)
768    x1 = m1(inp)
769    x = layers_module.Add()([x0, x1])
770
771    model = training_module.Model(inp, x)
772    self.assertLen(model.trainable_weights, 4)
773    self.assertLen(model.non_trainable_weights, 2)
774    self.assertLen(model.weights, 6)
775
776  @keras_parameterized.run_all_keras_modes
777  def test_weight_deduplication(self):
778
779    class WatchingLayer(layers_module.Layer):
780
781      def __init__(self, dense_to_track):
782        # This will cause the kernel and bias to be double counted, effectively
783        # doubling the learning rate if weights are not deduped.
784        self._kernel = dense_to_track.kernel
785        self._bias = dense_to_track.bias
786        super(WatchingLayer, self).__init__()
787
788    inp = layers_module.Input(shape=(1,))
789    dense_layer = layers_module.Dense(1)
790    dense_output = dense_layer(inp)  # This will build the dense kernel
791
792    # Deterministically set weights to make the test repeatable.
793    dense_layer.set_weights([np.ones((1, 1)), np.zeros((1,))])
794    output = WatchingLayer(dense_layer)(dense_output)
795
796    model = training_module.Model(inp, output)
797
798    # 0.25 is the edge of the radius of convergence for the double apply case.
799    # At lr=0.24, the double apply case will very slowly descend while the
800    # correct case will drop very quickly.
801    model.compile(
802        loss='mse',
803        optimizer=optimizer_v2.gradient_descent.SGD(0.24),
804        run_eagerly=testing_utils.should_run_eagerly())
805
806    x = np.ones((64 * 2,))
807    y = 4.5 * x - 3.
808
809    history = model.fit(x, y, batch_size=64, epochs=2, verbose=2)
810
811    # If the gradient apply is duplicated then the loss after 2 epochs will
812    # be ~0.15, compared to the correct answer of O(1e-7).
813    self.assertLess(history.history['loss'][-1], 1e-6)
814
815  @keras_parameterized.run_all_keras_modes
816  def test_weight_shared_across_layers(self):
817
818    class AddWeightLayer(layers_module.Layer):
819
820      def __init__(self, trainable_var, non_trainable_var):
821        self.trainable_var = trainable_var
822        self.non_trainable_var = non_trainable_var
823        super(AddWeightLayer, self).__init__()
824
825      def call(self, inputs):
826        return inputs + self.trainable_var
827
828    class LayerWithWeightSharedLayers(layers_module.Layer):
829
830      def __init__(self):
831        super(LayerWithWeightSharedLayers, self).__init__()
832        shared_trainable_var = variables_module.Variable(1.)
833        shared_non_trainable_var = variables_module.Variable(
834            1., trainable=False)
835        self.layer1 = AddWeightLayer(shared_trainable_var,
836                                     shared_non_trainable_var)
837        self.layer2 = AddWeightLayer(shared_trainable_var,
838                                     shared_non_trainable_var)
839
840      def call(self, inputs):
841        return self.layer2(self.layer1(inputs))
842
843    l = LayerWithWeightSharedLayers()
844    layers = list(l._flatten_layers(include_self=False, recursive=False))
845    self.assertEqual(layers, [l.layer1, l.layer2])
846    self.assertEqual(l.variables,
847                     [l.layer1.trainable_var, l.layer1.non_trainable_var])
848    self.assertEqual(l.trainable_variables, [l.layer1.trainable_var])
849    self.assertEqual(l.non_trainable_variables, [l.layer1.non_trainable_var])
850    self.assertLen(l.get_weights(), 2)
851
852  @keras_parameterized.run_all_keras_modes
853  def test_weight_tracking_for_template(self):
854    def variable_scoped_function(trainable=True):
855      return variable_scope.get_variable(
856          'dummy', shape=[1], trainable=trainable,
857          initializer=init_ops.zeros_initializer())
858    def nested_template():
859      nested1 = template.make_template('nested', variable_scoped_function)
860      nested2 = template.make_template('nested', variable_scoped_function)
861      v1 = nested1()
862      v2 = nested2()
863
864      # nested1 and nested2 should not share variables
865      self.assertIsNot(v1, v2)
866
867      # Variables created by nested1 should be isolated from variables
868      # created by nested2.
869      self.assertEqual(1, len(nested1.variables))
870      self.assertEqual(1, len(nested2.variables))
871      self.assertIs(nested1.variables[0], v1)
872      self.assertIs(nested2.variables[0], v2)
873      self.assertEqual(1, len(nested1.trainable_variables))
874      self.assertEqual(1, len(nested2.trainable_variables))
875      self.assertIs(nested1.trainable_variables[0], v1)
876      self.assertIs(nested2.trainable_variables[0], v2)
877      self.assertEqual(len(nested1.non_trainable_variables), 0)
878      self.assertEqual(len(nested2.non_trainable_variables), 0)
879      return v1, v2
880
881    tmpl1 = template.make_template('s1', nested_template)
882    tmpl2 = template.make_template('s1', nested_template)
883
884    v1, v2 = tmpl1()
885    v5, v6 = tmpl2()
886
887    model = training_module.Model()
888    model.template = tmpl1
889    self.assertEqual(2, len(model.variables))
890    self.assertIs(model.variables[0], v1)
891    self.assertIs(model.variables[1], v2)
892    self.assertEqual(2, len(model.variables))
893    self.assertIs(model.trainable_variables[0], v1)
894    self.assertIs(model.trainable_variables[1], v2)
895    self.assertEqual(len(model.non_trainable_variables), 0)
896    model.templates = [tmpl2]
897    for v, w in zip(model.variables, [v1, v2, v5, v6]):
898      self.assertIs(v, w)
899    for v, w in zip(model.trainable_variables, [v1, v2, v5, v6]):
900      self.assertIs(v, w)
901    self.assertEqual(len(model.non_trainable_variables), 0)
902    # Make sure losses, layers, and updates aren't broken by having a Template
903    # in the mix, which does not expose any updates or losses.
904    self.assertEqual([], model.layers)
905    self.assertEqual([], model.updates)
906    self.assertEqual([], model.losses)
907    self.assertEqual([], model.templates.layers)
908    self.assertEqual([], model.templates.updates)
909    self.assertEqual([], model.templates.losses)
910
911  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
912  def test_logs_passed_to_callbacks(self):
913    input_dim = 5
914    num_classes = 1
915
916    class TestCallback(Callback):
917
918      def __init__(self):
919        super(TestCallback, self).__init__()
920        self.epoch_end_logs = None
921        self.batch_end_logs = None
922        self.epoch_end_call_count = 0
923        self.batch_end_call_count = 0
924
925      def on_epoch_end(self, epoch, logs=None):
926        self.epoch_end_logs = logs
927        self.epoch_end_call_count += 1
928
929      def on_batch_end(self, batch, logs=None):
930        self.batch_end_logs = logs
931        self.batch_end_call_count += 1
932
933    model = testing_utils.get_small_sequential_mlp(
934        num_hidden=10, num_classes=num_classes, input_dim=input_dim)
935    model.compile(
936        loss='binary_crossentropy',
937        metrics=['acc'],
938        weighted_metrics=['mae'],
939        optimizer=RMSPropOptimizer(learning_rate=0.01),
940        run_eagerly=testing_utils.should_run_eagerly())
941
942    np.random.seed(1337)
943    (x_train, y_train), (_, _) = testing_utils.get_test_data(
944        train_samples=10,
945        test_samples=10,
946        input_shape=(input_dim,),
947        num_classes=num_classes)
948
949    test_callback = TestCallback()
950    model.fit(
951        x_train,
952        y_train,
953        batch_size=2,
954        epochs=2,
955        verbose=0,
956        callbacks=[test_callback],
957        validation_data=(x_train, y_train))
958    self.assertEqual(test_callback.batch_end_call_count, 10)
959    self.assertEqual(test_callback.epoch_end_call_count, 2)
960
961    self.assertSetEqual(
962        set(test_callback.batch_end_logs.keys()), set(['acc', 'loss', 'mae']))
963    self.assertSetEqual(
964        set(test_callback.epoch_end_logs.keys()),
965        set(['acc', 'loss', 'mae', 'val_acc', 'val_loss', 'val_mae']))
966
967  @keras_parameterized.run_all_keras_modes
968  def test_mismatched_output_shape_and_target_shape(self):
969    model = sequential.Sequential([
970        layers_module.Dense(2, input_shape=(3, 4)),
971        layers_module.Dense(5),
972    ])
973    model.compile(
974        RMSPropOptimizer(learning_rate=0.001),
975        loss='sparse_categorical_crossentropy',
976        run_eagerly=testing_utils.should_run_eagerly())
977    # Test with Numpy data
978    x_train = np.random.random((10, 3, 4)).astype(np.float32)
979    y_train = np.random.randint(0, 5, size=(10, 3)).astype(np.float32)
980    model.fit(x_train, y_train, batch_size=5, epochs=1)
981
982    # Test with iterator
983    dataset = dataset_ops.Dataset.from_tensor_slices((x_train, y_train))
984    dataset = dataset.repeat(10)
985    dataset = dataset.batch(10)
986    model.fit(dataset, epochs=1, steps_per_epoch=2)
987
988    if context.executing_eagerly():
989      # Test with eager execution
990      model.compile(RMSPropOptimizer(learning_rate=0.001),
991                    loss='sparse_categorical_crossentropy',
992                    run_eagerly=True)
993      model.fit(x_train, y_train, batch_size=5, epochs=1)
994
995      # Test with eager execution and iterator
996      model.fit(dataset, epochs=1, steps_per_epoch=2)
997
998  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
999  def test_losses_in_defun(self):
1000    layer = layers_module.Dense(1, kernel_regularizer='l1')
1001    layer(array_ops.ones([1, 10]))
1002
1003    @def_function.function
1004    def get_losses():
1005      return layer.losses
1006
1007    self.assertAllEqual(
1008        self.evaluate(layer.losses), self.evaluate(get_losses()))
1009
1010  @keras_parameterized.run_all_keras_modes
1011  def test_logging(self):
1012    mock_stdout = io.StringIO()
1013    model = sequential.Sequential()
1014    model.add(layers_module.Dense(10, activation='relu'))
1015    model.add(layers_module.Dense(1, activation='sigmoid'))
1016    model.compile(
1017        RMSPropOptimizer(learning_rate=0.001),
1018        loss='binary_crossentropy',
1019        run_eagerly=testing_utils.should_run_eagerly())
1020    with test.mock.patch.object(sys, 'stdout', mock_stdout):
1021      model.fit(
1022          np.ones((10, 10), 'float32'), np.ones((10, 1), 'float32'), epochs=10)
1023    self.assertTrue('Epoch 5/10' in mock_stdout.getvalue())
1024
1025  @combinations.generate(combinations.combine(mode=['graph', 'eager']))
1026  def test_training_with_loss_instance(self):
1027    a = layers_module.Input(shape=(3,), name='input_a')
1028    b = layers_module.Input(shape=(3,), name='input_b')
1029
1030    dense = layers_module.Dense(4, name='dense')
1031    c = dense(a)
1032    d = dense(b)
1033    e = layers_module.Dropout(0.5, name='dropout')(c)
1034
1035    model = training_module.Model([a, b], [d, e])
1036    loss_weights = [1., 0.5]
1037    model.compile(
1038        RMSPropOptimizer(learning_rate=0.001),
1039        loss=losses.MeanSquaredError(),
1040        metrics=[metrics_module.CategoricalAccuracy(), 'mae'],
1041        loss_weights=loss_weights)
1042
1043    input_a_np = np.random.random((10, 3))
1044    input_b_np = np.random.random((10, 3))
1045
1046    output_d_np = np.random.random((10, 4))
1047    output_e_np = np.random.random((10, 4))
1048
1049    model.fit([input_a_np, input_b_np], [output_d_np, output_e_np],
1050              epochs=1,
1051              batch_size=5)
1052
1053  @combinations.generate(combinations.combine(mode=['graph', 'eager']))
1054  def test_static_batch_in_input_layer(self):
1055    if context.executing_eagerly():
1056      self.skipTest('Not inferred in eager.')
1057
1058    class Counter(Callback):
1059
1060      def __init__(self):
1061        self.batches = 0
1062
1063      def on_batch_end(self, batch, logs=None):
1064        self.batches += 1
1065
1066    x, y = np.ones((64, 10), 'float32'), np.ones((64, 1), 'float32')
1067
1068    for batch_size, expected_batches in [(None, 2), (4, 16)]:
1069      inputs = input_layer.Input(batch_size=batch_size, shape=(10,))
1070      outputs = layers_module.Dense(1, activation='sigmoid')(inputs)
1071      model = training_module.Model(inputs, outputs)
1072
1073      model.compile(optimizer_v2.adam.Adam(0.001), 'binary_crossentropy')
1074      counter = Counter()
1075      model.fit(x, y, callbacks=[counter])
1076      self.assertEqual(counter.batches, expected_batches)
1077
1078      model = sequential.Sequential(
1079          [layers_module.Dense(1, batch_input_shape=(batch_size, 10))])
1080      model.compile(optimizer_v2.adam.Adam(0.001), 'binary_crossentropy')
1081      counter = Counter()
1082      model.fit(x, y, callbacks=[counter])
1083      self.assertEqual(counter.batches, expected_batches)
1084
1085  @combinations.generate(combinations.combine(mode=['graph', 'eager']))
1086  def test_static_batch_in_input_layer_consistency_checks(self):
1087    if context.executing_eagerly():
1088      self.skipTest('Not inferred in eager.')
1089    x, y = np.ones((64, 10), 'float32'), np.ones((64, 1), 'float32')
1090
1091    inputs = input_layer.Input(batch_size=2, shape=(10,))
1092    outputs = layers_module.Dense(1, activation='sigmoid')(inputs)
1093    model = training_module.Model(inputs, outputs)
1094    model.compile(optimizer_v2.adam.Adam(0.001), 'binary_crossentropy')
1095    with self.assertRaisesRegex(ValueError,
1096                                'incompatible with the specified batch size'):
1097      model.fit(x, y, batch_size=4)
1098
1099  @combinations.generate(combinations.combine(mode=['graph', 'eager']))
1100  def test_compatible_batch_size_functional_model(self):
1101
1102    class MyLayer(layers_module.Layer):
1103
1104      def call(self, inputs):
1105        return array_ops.concat(inputs, axis=0)
1106
1107    input1 = input_layer.Input(batch_size=2, shape=(10,))
1108    input2 = input_layer.Input(batch_size=3, shape=(10,))
1109    outputs = MyLayer()([input1, input2])
1110    with self.assertRaisesRegex(ValueError,
1111                                'specified batch sizes of the Input Layers'):
1112      training_module.Model([input1, input2], outputs)
1113
1114  @combinations.generate(combinations.combine(mode=['graph', 'eager']))
1115  def test_calling_subclass_model_on_different_datasets(self):
1116
1117    class SubclassedModel(training_module.Model):
1118
1119      def call(self, inputs):
1120        return inputs * 2
1121
1122    model = SubclassedModel()
1123    dataset_one = dataset_ops.Dataset.range(2).batch(2)
1124    dataset_two = dataset_ops.Dataset.range(3, 10).batch(2)
1125    self.assertAllEqual([[0], [2]], model.predict(dataset_one, steps=1))
1126    self.assertAllEqual([[6], [8], [10], [12]],
1127                        model.predict(dataset_two, steps=2))
1128
1129  @combinations.generate(combinations.combine(mode=['eager']))
1130  def test_training_on_sparse_categorical_crossentropy_loss_with_softmax(self):
1131    np.random.seed(1337)
1132    train_x = np.ones((100, 4))
1133    train_y = np.random.randint(0, 1, size=(100, 1))
1134
1135    reference_model = testing_utils.get_small_sequential_mlp(16, 2,
1136                                                             input_dim=4)
1137    reference_model.compile(loss='sparse_categorical_crossentropy',
1138                            optimizer=RMSPropOptimizer(learning_rate=0.001),
1139                            run_eagerly=True)
1140    fixed_weights = reference_model.get_weights()
1141    reference_model_loss = reference_model.train_on_batch(train_x, train_y)
1142
1143    test_model = testing_utils.get_small_sequential_mlp(16, 2, input_dim=4)
1144    test_model.compile(loss='sparse_categorical_crossentropy',
1145                       optimizer=RMSPropOptimizer(learning_rate=0.001),
1146                       run_eagerly=False)
1147    test_model.set_weights(fixed_weights)
1148    test_model_loss = test_model.train_on_batch(train_x, train_y)
1149    self.assertAlmostEqual(test_model_loss, reference_model_loss, places=4)
1150
1151  @combinations.generate(combinations.combine(mode=['eager']))
1152  def test_training_on_categorical_crossentropy_loss_with_softmax(self):
1153    np.random.seed(1337)
1154    train_x = np.ones((100, 4))
1155    train_y = np_utils.to_categorical(
1156        np.random.randint(0, 1, size=(100, 1)), 2)
1157
1158    reference_model = testing_utils.get_small_sequential_mlp(16, 2,
1159                                                             input_dim=4)
1160    reference_model.compile(loss='categorical_crossentropy',
1161                            optimizer=RMSPropOptimizer(learning_rate=0.001),
1162                            run_eagerly=True)
1163    fixed_weights = reference_model.get_weights()
1164    reference_model_loss = reference_model.train_on_batch(train_x, train_y)
1165
1166    test_model = testing_utils.get_small_sequential_mlp(16, 2, input_dim=4)
1167    test_model.compile(loss='categorical_crossentropy',
1168                       optimizer=RMSPropOptimizer(learning_rate=0.001),
1169                       run_eagerly=False)
1170    test_model.set_weights(fixed_weights)
1171    test_model_loss = test_model.train_on_batch(train_x, train_y)
1172    self.assertAlmostEqual(test_model_loss, reference_model_loss, places=4)
1173
1174  @combinations.generate(combinations.combine(mode=['eager']))
1175  def test_training_on_binary_crossentropy_loss(self):
1176    train_x = np.ones((100, 4), dtype=np.float32)
1177    train_y = np.ones((100, 1), dtype=np.float32)
1178    reference_model = testing_utils.get_small_sequential_mlp(16, 1,
1179                                                             input_dim=4)
1180    reference_model.compile(loss='binary_crossentropy',
1181                            optimizer=RMSPropOptimizer(learning_rate=0.001),
1182                            run_eagerly=True)
1183    fixed_weights = reference_model.get_weights()
1184    reference_model_loss = reference_model.train_on_batch(train_x, train_y)
1185
1186    test_model = testing_utils.get_small_sequential_mlp(16, 1, input_dim=4)
1187    test_model.compile(loss='binary_crossentropy',
1188                       optimizer=RMSPropOptimizer(learning_rate=0.001),
1189                       run_eagerly=False)
1190    test_model.set_weights(fixed_weights)
1191    test_model_loss = test_model.train_on_batch(train_x, train_y)
1192    self.assertAlmostEqual(test_model_loss, reference_model_loss, places=4)
1193
1194  @keras_parameterized.run_with_all_model_types
1195  @keras_parameterized.run_all_keras_modes
1196  @parameterized.named_parameters(
1197      ('default', 1, 4), ('integer_two', 2, 2), ('integer_four', 4, 1),
1198      ('simple_list', [1, 3, 4], 3), ('duplicated_list', [4, 2, 2], 2))
1199  def test_validation_freq(self, validation_freq, expected_runs):
1200    x, y = np.ones((10, 10)), np.ones((10, 1))
1201    model = testing_utils.get_small_mlp(2, 1, 10)
1202    model.compile(
1203        'sgd',
1204        'mse',
1205        run_eagerly=testing_utils.should_run_eagerly())
1206
1207    class ValCounter(Callback):
1208
1209      def __init__(self):
1210        self.val_runs = 0
1211
1212      def on_test_begin(self, logs=None):
1213        self.val_runs += 1
1214
1215    val_counter = ValCounter()
1216    model.fit(
1217        x,
1218        y,
1219        epochs=4,
1220        validation_data=(x, y),
1221        validation_freq=validation_freq,
1222        callbacks=[val_counter])
1223    self.assertEqual(val_counter.val_runs, expected_runs)
1224
1225  @keras_parameterized.run_with_all_model_types
1226  @keras_parameterized.run_all_keras_modes
1227  def test_validation_steps_without_data(self):
1228    if context.executing_eagerly():
1229      self.skipTest('Check removed in new `fit`')
1230    x, y = np.ones((10, 10)), np.ones((10, 1))
1231    model = testing_utils.get_small_mlp(2, 1, 10)
1232    model.compile(
1233        'sgd',
1234        'mse',
1235        run_eagerly=testing_utils.should_run_eagerly())
1236
1237    with self.assertRaisesRegex(
1238        ValueError, '`validation_steps` should not be specified if '
1239        '`validation_data` is None.'):
1240      model.fit(x, y, epochs=4, validation_data=None, validation_steps=3)
1241
1242  @keras_parameterized.run_with_all_model_types
1243  @keras_parameterized.run_all_keras_modes
1244  def test_layer_with_variable_output(self):
1245
1246    class VariableOutputLayer(layers_module.Layer):
1247
1248      def build(self, input_shape):
1249        self.v = self.add_weight('output_var', shape=(2, 5), initializer='ones')
1250
1251      def call(self, inputs):
1252        return self.v
1253
1254    model = testing_utils.get_model_from_layers(
1255        [VariableOutputLayer(), layers_module.Dense(1)], input_shape=(10,))
1256    # TODO(omalleyt): Make this work with `run_eagerly=True`.
1257    model.compile('sgd', 'mse', run_eagerly=False)
1258    model.fit(np.ones((10, 10)), np.ones((10, 1)), batch_size=2, epochs=5)
1259
1260    self.assertLen(model.trainable_variables, 3)
1261
1262  @keras_parameterized.run_with_all_model_types
1263  @keras_parameterized.run_all_keras_modes
1264  @testing_utils.enable_v2_dtype_behavior
1265  def test_model_dtype(self):
1266
1267    class AssertTypeLayer(layers_module.Layer):
1268
1269      def call(self, inputs):
1270        assert inputs.dtype.name == self.dtype, (
1271            'Input tensor has type %s which does not match assert type %s' %
1272            (inputs.dtype.name, self.assert_type))
1273        return inputs + 1.
1274
1275    for dtype in ('float16', 'float32', 'float64'):
1276      model = testing_utils.get_model_from_layers(
1277          [AssertTypeLayer(dtype=dtype)], input_shape=(10,))
1278      model.compile(
1279          'sgd',
1280          'mse',
1281          run_eagerly=testing_utils.should_run_eagerly())
1282
1283      x = np.ones((10, 10))
1284      y = np.ones((10, 10))
1285      model.fit(x, y)
1286      model.test_on_batch(x, y)
1287      model(x)
1288
1289  @keras_parameterized.run_with_all_model_types
1290  @keras_parameterized.run_all_keras_modes
1291  @testing_utils.enable_v2_dtype_behavior
1292  def test_model_input_dtype(self):
1293    model = testing_utils.get_small_mlp(1, 10, 10)
1294    model.compile(
1295        'sgd',
1296        'mse',
1297        run_eagerly=testing_utils.should_run_eagerly())
1298    x = np.ones((10, 10)).astype(np.float64)
1299    y = np.ones((10, 10)).astype(np.float64)
1300    dataset = dataset_ops.Dataset.from_tensor_slices((x, y)).batch(2)
1301    model.fit(dataset)
1302    self.assertEqual(model._compute_dtype, 'float32')
1303
1304  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
1305  def test_subclassed_model_with_training_arg(self):
1306
1307    class LayerWithTrainingArg(layers_module.Layer):
1308
1309      def call(self, inputs, training=None):
1310        self.training = training
1311        return inputs
1312
1313    class ModelWithTrainingArg(training_module.Model):
1314
1315      def __init__(self):
1316        super(ModelWithTrainingArg, self).__init__()
1317        self.l1 = LayerWithTrainingArg()
1318
1319      def call(self, inputs, training=None):
1320        self.training = training
1321        inputs = self.l1(inputs, training=training)
1322        return inputs
1323
1324    x = np.zeros((1, 2))
1325    model = ModelWithTrainingArg()
1326    model.compile(
1327        loss='mse',
1328        optimizer='sgd',
1329        run_eagerly=testing_utils.should_run_eagerly())
1330    model.fit(x, x, epochs=1)
1331
1332    if context.executing_eagerly():
1333      expected_training_arg = True
1334    else:
1335      expected_training_arg = backend.symbolic_learning_phase()
1336
1337    self.assertIs(model.training, expected_training_arg)
1338    self.assertIs(model.l1.training, expected_training_arg)
1339
1340  @keras_parameterized.run_all_keras_modes
1341  def test_error_when_model_is_not_compiled(self):
1342    inputs = input_layer.Input(shape=(1,))
1343    outputs = layers_module.Dense(1)(inputs)
1344    model = training_module.Model(inputs, outputs)
1345    with self.assertRaisesRegex(RuntimeError, 'must compile your model'):
1346      model.fit(np.ones((1, 1)), np.ones((1, 1)))
1347
1348    class MyModel(training_module.Model):
1349
1350      def call(self, x):
1351        self.add_loss(math_ops.reduce_sum(x))
1352        return x
1353
1354    model = MyModel()
1355    with self.assertRaisesRegex(RuntimeError, 'must compile your model'):
1356      model.fit(np.random.random((32, 1)), epochs=2)
1357
1358  @keras_parameterized.run_all_keras_modes
1359  @testing_utils.enable_v2_dtype_behavior
1360  def test_losses_of_different_dtypes(self):
1361    inp = input_layer.Input(shape=(2,))
1362    out_1 = layers_module.Dense(
1363        2, dtype='float32', kernel_regularizer='l2')(
1364            inp)
1365    out_2 = layers_module.Dense(
1366        2, dtype='float16', kernel_regularizer='l2')(
1367            inp)
1368    model = training_module.Model(inp, [out_1, out_2])
1369    extra_loss = math_ops.reduce_sum(math_ops.cast(out_2, 'float64'))
1370    model.add_loss(extra_loss)
1371    model.compile('sgd', ['mse', 'mse'],
1372                  run_eagerly=testing_utils.should_run_eagerly())
1373    x, y = np.ones((10, 2)), np.ones((10, 2))
1374    model.fit(x, [y, y])
1375
1376  @keras_parameterized.run_all_keras_modes
1377  @testing_utils.enable_v2_dtype_behavior
1378  def test_losses_of_different_dtypes_with_subclassed_model(self):
1379
1380    class MyModel(training_module.Model):
1381
1382      def build(self, _):
1383        self.dense = layers_module.Dense(2)
1384
1385      def call(self, inputs):
1386        self.add_loss(math_ops.cast(nn_ops.l2_loss(inputs), 'float64'))
1387        return self.dense(inputs)
1388
1389    model = MyModel(dtype='float32')
1390    model.compile('sgd', 'mse', run_eagerly=testing_utils.should_run_eagerly())
1391    x, y = np.ones((10, 2)), np.ones((10, 2))
1392    model.fit(x, y)
1393
1394  @keras_parameterized.run_all_keras_modes
1395  @testing_utils.enable_v2_dtype_behavior
1396  def test_regularizer_of_different_dtype(self):
1397    inp = input_layer.Input(shape=(2,))
1398
1399    def regularizer(weight):
1400      return math_ops.cast(nn_ops.l2_loss(weight), 'float64')
1401
1402    out = layers_module.Dense(
1403        2, dtype='float32', kernel_regularizer=regularizer)(
1404            inp)
1405    model = training_module.Model(inp, out)
1406    model.compile('sgd', 'mse', run_eagerly=testing_utils.should_run_eagerly())
1407    x, y = np.ones((10, 2)), np.ones((10, 2))
1408    model.fit(x, y)
1409
1410  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
1411  def test_outputs_are_floats(self):
1412    x, y = np.ones((10, 1)), np.ones((10, 1))
1413    model = sequential.Sequential([layers_module.Dense(1)])
1414    model.compile('sgd', 'mse', metrics=['accuracy'],
1415                  run_eagerly=testing_utils.should_run_eagerly())
1416
1417    history = model.fit(x, y, epochs=2)
1418    self.assertIsInstance(history.history['loss'][0], float)
1419    self.assertIsInstance(history.history['accuracy'][0], float)
1420
1421    loss, accuracy = model.train_on_batch(x, y)
1422    self.assertIsInstance(loss, float)
1423    self.assertIsInstance(accuracy, float)
1424
1425    loss, accuracy = model.evaluate(x, y)
1426    self.assertIsInstance(loss, float)
1427    self.assertIsInstance(accuracy, float)
1428
1429    loss, accuracy = model.test_on_batch(x, y)
1430    self.assertIsInstance(loss, float)
1431    self.assertIsInstance(accuracy, float)
1432
1433  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
1434  def test_int_output(self):
1435    x, y = np.ones((10, 1)), np.ones((10, 1))
1436    model = sequential.Sequential([layers_module.Dense(1)])
1437
1438    class MyMetric(metrics_module.Metric):
1439
1440      def update_state(self, y_true, y_pred, sample_weight=None):
1441        del y_true, y_pred, sample_weight
1442
1443      def result(self):
1444        return array_ops.constant(1, dtype='int64')
1445
1446    model.compile('sgd', 'mse', metrics=[MyMetric()],
1447                  run_eagerly=testing_utils.should_run_eagerly())
1448    history = model.fit(x, y, epochs=2)
1449    self.assertIsInstance(history.history['my_metric'][0], int)
1450
1451  @keras_parameterized.run_all_keras_modes
1452  def test_calling_aggregate_gradient(self):
1453
1454    class _Optimizer(optimizer_v2.gradient_descent.SGD):
1455      """Mock optimizer to check if _aggregate_gradient is called."""
1456
1457      _HAS_AGGREGATE_GRAD = True
1458
1459      def __init__(self):
1460        self.aggregate_gradients_called = False
1461        super(_Optimizer, self).__init__(name='MyOptimizer')
1462
1463      def _aggregate_gradients(self, grads):
1464        self.aggregate_gradients_called = True
1465        return super(_Optimizer, self)._aggregate_gradients(grads)
1466
1467    mock_optimizer = _Optimizer()
1468
1469    model = sequential.Sequential()
1470    model.add(layers_module.Dense(10, activation='relu'))
1471
1472    model.compile(mock_optimizer, 'mse',
1473                  run_eagerly=testing_utils.should_run_eagerly())
1474    x, y = np.ones((10, 10)), np.ones((10, 10))
1475    model.fit(x, y)
1476    self.assertEqual(model.optimizer.aggregate_gradients_called, True)
1477
1478    class _OptimizerOverrideApplyGradients(_Optimizer):
1479      """Override apply_gradients.
1480
1481      To test the case where the optimizer does not define the
1482      experimental_aggregate_gradients parameter.
1483      """
1484
1485      _HAS_AGGREGATE_GRAD = False
1486
1487      def apply_gradients(self, grads_and_vars, name=None):  # pylint: disable=useless-super-delegation
1488        return super(_OptimizerOverrideApplyGradients,
1489                     self).apply_gradients(grads_and_vars, name)
1490
1491    mock_optimizer = _OptimizerOverrideApplyGradients()
1492    model.compile(mock_optimizer, 'mse',
1493                  run_eagerly=testing_utils.should_run_eagerly())
1494    x, y = np.ones((10, 10)), np.ones((10, 10))
1495    model.fit(x, y)
1496    self.assertEqual(model.optimizer.aggregate_gradients_called, True)
1497
1498  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
1499  def test_gradients_are_none(self):
1500
1501    class DenseWithExtraWeight(layers_module.Dense):
1502
1503      def build(self, input_shape):
1504        # Gradients w.r.t. extra_weights are None
1505        self.extra_weight_1 = self.add_weight('extra_weight_1', shape=(),
1506                                              initializer='ones')
1507        super(DenseWithExtraWeight, self).build(input_shape)
1508        self.extra_weight_2 = self.add_weight('extra_weight_2', shape=(),
1509                                              initializer='ones')
1510
1511    model = sequential.Sequential([DenseWithExtraWeight(4, input_shape=(4,))])
1512    # Test clipping can handle None gradients
1513    opt = optimizer_v2.adam.Adam(clipnorm=1.0, clipvalue=1.0)
1514    model.compile(opt, 'mse', run_eagerly=testing_utils.should_run_eagerly())
1515    inputs = np.random.normal(size=(64, 4))
1516    targets = np.random.normal(size=(64, 4))
1517    old_kernel = model.get_weights()[1]
1518    model.fit(inputs, targets)
1519    new_kernel = model.get_weights()[1]
1520    self.assertNotAllEqual(old_kernel, new_kernel)
1521
1522  @keras_parameterized.run_all_keras_modes
1523  def test_layer_ordering(self):
1524
1525    class MyLayer(layers_module.Layer):
1526      pass
1527
1528    class MyModel(training_module.Model):
1529
1530      def __init__(self, name):
1531        super(MyModel, self).__init__(name=name)
1532
1533        self.weight = variables_module.Variable(0, name=name)
1534
1535        self.direct_sublayer = MyLayer(name='direct')
1536        self.direct_sublayer.d = {'d': MyLayer(name='direct/dict')}
1537
1538        self.dict_sublayer = {'d': MyLayer(name='dict')}
1539        self.dict_sublayer['d'].direct = MyLayer(name='dict/direct')
1540
1541    model = MyModel('model')
1542    # All sublayers, including self and recursive sublayers.
1543    self.assertEqual(['model', 'direct', 'direct/dict', 'dict', 'dict/direct'],
1544                     [l.name for l in model._flatten_layers()])
1545    # Only direct sublayers, including those in data structures.
1546    self.assertEqual(['direct', 'dict'], [l.name for l in model.layers])
1547
1548  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
1549  def test_trainable_state_setting(self):
1550
1551    class UpdateLayer(layers_module.Layer):
1552
1553      def __init__(self):
1554        super(UpdateLayer, self).__init__()
1555        self.v = variables_module.Variable(0., trainable=False)
1556
1557      def call(self, x):
1558        self.add_update(lambda: self.v.assign_add(1.))
1559        return x * self.v
1560
1561    layer = UpdateLayer()
1562    model_with_updates = sequential.Sequential([layer])
1563    model_with_updates.compile(
1564        'sgd', 'mse', run_eagerly=testing_utils.should_run_eagerly())
1565
1566    layer.trainable = False
1567    model_without_updates = sequential.Sequential([layer])
1568    model_without_updates.compile(
1569        'sgd', 'mse', run_eagerly=testing_utils.should_run_eagerly())
1570
1571    x, y = np.ones((10, 1)), np.ones((10, 1))
1572
1573    self.assertEqual(self.evaluate(layer.v), 0.)
1574    model_with_updates.fit(x, y, batch_size=10)
1575    # assign_add called.
1576    self.assertEqual(self.evaluate(layer.v), 1.)
1577    model_without_updates.fit(x, y, batch_size=10)
1578    # assign_add not called.
1579    self.assertEqual(self.evaluate(layer.v), 1.)
1580
1581  @keras_parameterized.run_all_keras_modes(
1582      always_skip_v1=True)
1583  @parameterized.named_parameters(
1584      ('numpy_array', 'numpy_array'),
1585      ('dataset_array', 'dataset_array'),
1586      ('dataset_dict', 'dataset_dict'))
1587  def test_single_input_no_tuple_wrapping(self, input_type):
1588    x = np.ones((10, 1))
1589
1590    if input_type == 'numpy_array':
1591      batch_size = 3
1592      expected_data_type = ops.Tensor
1593    elif input_type == 'dataset_array':
1594      x = dataset_ops.Dataset.from_tensor_slices(x).batch(3)
1595      batch_size = None
1596      expected_data_type = ops.Tensor
1597    else:
1598      x = {'my_input': x}
1599      x = dataset_ops.Dataset.from_tensor_slices(x).batch(3)
1600      batch_size = None
1601      expected_data_type = dict
1602
1603    test_case = self
1604
1605    class MyModel(training_module.Model):
1606
1607      def train_step(self, data):
1608        # No tuple wrapping for single x input and no targets.
1609        test_case.assertIsInstance(data, expected_data_type)
1610        return super(MyModel, self).train_step(data)
1611
1612      def test_step(self, data):
1613        test_case.assertIsInstance(data, expected_data_type)
1614        return super(MyModel, self).test_step(data)
1615
1616      def predict_step(self, data):
1617        test_case.assertIsInstance(data, expected_data_type)
1618        return super(MyModel, self).predict_step(data)
1619
1620    inputs = layers_module.Input(shape=(1,), name='my_input')
1621    outputs = layers_module.Dense(1)(inputs)
1622    model = MyModel(inputs, outputs)
1623    model.add_loss(math_ops.reduce_sum(outputs))
1624    model.compile('sgd', 'mse')
1625    model.fit(x, batch_size=batch_size)
1626    model.evaluate(x, batch_size=batch_size)
1627    model.predict(x, batch_size=batch_size)
1628
1629  @keras_parameterized.run_all_keras_modes(
1630      always_skip_v1=True)
1631  @parameterized.named_parameters(
1632      ('custom_metrics', False, True),
1633      ('compiled_metrics', True, False),
1634      ('both_compiled_and_custom_metrics', True, True))
1635  def test_evaluate_with_custom_test_step(
1636      self, use_compiled_metrics, use_custom_metrics):
1637
1638    class MyModel(training_module.Model):
1639
1640      def test_step(self, data):
1641        x, y = data
1642        pred = self(x)
1643        metrics = {}
1644        if use_compiled_metrics:
1645          self.compiled_metrics.update_state(y, pred)
1646          self.compiled_loss(y, pred)
1647          for metric in self.metrics:
1648            metrics[metric.name] = metric.result()
1649        if use_custom_metrics:
1650          custom_metrics = {
1651              'mean': math_ops.reduce_mean(pred),
1652              'sum': math_ops.reduce_sum(pred)
1653          }
1654          metrics.update(custom_metrics)
1655        return metrics
1656
1657    inputs = layers_module.Input((2,))
1658    outputs = layers_module.Dense(3)(inputs)
1659    model = MyModel(inputs, outputs)
1660    if use_compiled_metrics:
1661      model.compile('adam', 'mse', metrics=['mae', 'mape'],
1662                    run_eagerly=testing_utils.should_run_eagerly())
1663    else:
1664      model.compile('adam', 'mse',
1665                    run_eagerly=testing_utils.should_run_eagerly())
1666    x = np.random.random((4, 2))
1667    y = np.random.random((4, 3))
1668    results_list = model.evaluate(x, y)
1669    results_dict = model.evaluate(x, y, return_dict=True)
1670    self.assertLen(results_list, len(results_dict))
1671    if use_compiled_metrics and use_custom_metrics:
1672      self.assertLen(results_list, 5)
1673      self.assertEqual(results_list,
1674                       [results_dict['loss'],
1675                        results_dict['mae'], results_dict['mape'],
1676                        results_dict['mean'], results_dict['sum']])
1677    if use_compiled_metrics and not use_custom_metrics:
1678      self.assertLen(results_list, 3)
1679      self.assertEqual(results_list,
1680                       [results_dict['loss'],
1681                        results_dict['mae'], results_dict['mape']])
1682    if not use_compiled_metrics and use_custom_metrics:
1683      self.assertLen(results_list, 2)
1684      self.assertEqual(results_list,
1685                       [results_dict['mean'], results_dict['sum']])
1686
1687
1688class TestExceptionsAndWarnings(keras_parameterized.TestCase):
1689
1690  @keras_parameterized.run_all_keras_modes
1691  def test_compile_warning_for_loss_missing_output(self):
1692    with self.cached_session():
1693      inp = layers_module.Input(shape=(16,), name='input_a')
1694      out_1 = layers_module.Dense(8, name='dense_1')(inp)
1695      out_2 = layers_module.Dense(
1696          3, activation='softmax', name='dense_2')(
1697              out_1)
1698      model = training_module.Model(inputs=[inp], outputs=[out_1, out_2])
1699      optimizer = RMSPropOptimizer(learning_rate=0.001)
1700
1701      model.compile(
1702          optimizer,
1703          loss={
1704              'dense_2': 'categorical_crossentropy',
1705          },
1706          metrics={
1707              'dense_2': 'categorical_accuracy',
1708              'dense_1': metrics_module.CategoricalAccuracy(),
1709          },
1710          run_eagerly=testing_utils.should_run_eagerly())
1711
1712  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
1713  def test_predict_error_with_empty_x(self):
1714    inputs = layers_module.Input(shape=(2,))
1715    outputs = layers_module.Dense(4)(inputs)
1716    model = training_module.Model(inputs=inputs, outputs=outputs)
1717    model.compile(loss='mse')
1718
1719    with self.assertRaisesRegex(ValueError,
1720                                'Expect x to be a non-empty array or dataset.'):
1721      model.predict(np.array([]))
1722
1723  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
1724  def test_on_batch_error_inconsistent_batch_size(self):
1725    input_node1 = layers_module.Input(shape=(5,))
1726    input_node2 = layers_module.Input(shape=(5,))
1727    output_node = layers_module.Concatenate()([input_node1, input_node2])
1728    output_node = layers_module.Dense(4)(output_node)
1729    model = training_module.Model([input_node1, input_node2], output_node)
1730    model.compile(loss='mse')
1731
1732    with self.assertRaisesRegex(ValueError, 'Data cardinality is ambiguous'):
1733      model.train_on_batch([np.ones((10, 5)), np.ones((10, 5))],
1734                           np.ones((11, 4)))
1735
1736    with self.assertRaisesRegex(ValueError, 'Data cardinality is ambiguous'):
1737      model.test_on_batch([np.ones((10, 5)), np.ones((10, 5))],
1738                          np.ones((11, 4)))
1739
1740    with self.assertRaisesRegex(ValueError, 'Data cardinality is ambiguous'):
1741      model.predict_on_batch([np.ones((10, 5)), np.ones((11, 5))])
1742
1743
1744class LossWeightingTest(keras_parameterized.TestCase):
1745
1746  @keras_parameterized.run_all_keras_modes
1747  def test_class_weights(self):
1748    num_classes = 5
1749    batch_size = 5
1750    epochs = 10
1751    weighted_class = 3
1752    weight = .5
1753    train_samples = 1000
1754    test_samples = 1000
1755    input_dim = 5
1756    learning_rate = 0.001
1757
1758    model = testing_utils.get_small_sequential_mlp(
1759        num_hidden=10, num_classes=num_classes, input_dim=input_dim)
1760    model.compile(
1761        loss='categorical_crossentropy',
1762        metrics=['acc', metrics_module.CategoricalAccuracy()],
1763        weighted_metrics=['mae', metrics_module.CategoricalAccuracy()],
1764        optimizer=RMSPropOptimizer(learning_rate=learning_rate),
1765        run_eagerly=testing_utils.should_run_eagerly())
1766
1767    np.random.seed(1337)
1768    (x_train, y_train), (x_test, y_test) = testing_utils.get_test_data(
1769        train_samples=train_samples,
1770        test_samples=test_samples,
1771        input_shape=(input_dim,),
1772        num_classes=num_classes)
1773    int_y_test = y_test.copy()
1774    # convert class vectors to binary class matrices
1775    y_train = np_utils.to_categorical(y_train, num_classes)
1776    y_test = np_utils.to_categorical(y_test, num_classes)
1777    test_ids = np.where(int_y_test == np.array(weighted_class))[0]
1778
1779    class_weight = dict([(i, 1.) for i in range(num_classes)])
1780    class_weight[weighted_class] = weight
1781
1782    model.fit(
1783        x_train,
1784        y_train,
1785        batch_size=batch_size,
1786        epochs=epochs // 3,
1787        verbose=0,
1788        class_weight=class_weight,
1789        validation_data=(x_train, y_train))
1790    model.fit(
1791        x_train,
1792        y_train,
1793        batch_size=batch_size,
1794        epochs=epochs // 2,
1795        verbose=0,
1796        class_weight=class_weight)
1797    model.fit(
1798        x_train,
1799        y_train,
1800        batch_size=batch_size,
1801        epochs=epochs // 2,
1802        verbose=0,
1803        class_weight=class_weight,
1804        validation_split=0.1)
1805
1806    model.train_on_batch(
1807        x_train[:batch_size], y_train[:batch_size], class_weight=class_weight)
1808    ref_score = model.evaluate(x_test, y_test, verbose=0)  # pylint: disable=unused-variable
1809    score = model.evaluate(  # pylint: disable=unused-variable
1810        x_test[test_ids, :], y_test[test_ids, :], verbose=0)
1811    # TODO(b/152990697): Fix the class weights test here.
1812    # self.assertLess(score[0], ref_score[0])
1813
1814  @keras_parameterized.run_all_keras_modes
1815  def test_temporal_sample_weights(self):
1816    num_classes = 5
1817    batch_size = 5
1818    epochs = 10
1819    weighted_class = 3
1820    weight = 10.
1821    train_samples = 1000
1822    test_samples = 1000
1823    input_dim = 5
1824    timesteps = 3
1825    learning_rate = 0.001
1826
1827    with self.cached_session():
1828      model = sequential.Sequential()
1829      model.add(
1830          layers_module.TimeDistributed(
1831              layers_module.Dense(num_classes),
1832              input_shape=(timesteps, input_dim)))
1833      model.add(layers_module.Activation('softmax'))
1834
1835      np.random.seed(1337)
1836      (x_train, y_train), (x_test, y_test) = testing_utils.get_test_data(
1837          train_samples=train_samples,
1838          test_samples=test_samples,
1839          input_shape=(input_dim,),
1840          num_classes=num_classes)
1841      int_y_test = y_test.copy()
1842      int_y_train = y_train.copy()
1843      # convert class vectors to binary class matrices
1844      y_train = np_utils.to_categorical(y_train, num_classes)
1845      y_test = np_utils.to_categorical(y_test, num_classes)
1846      test_ids = np.where(int_y_test == np.array(weighted_class))[0]
1847
1848      sample_weight = np.ones((y_train.shape[0]))
1849      sample_weight[int_y_train == weighted_class] = weight
1850
1851      temporal_x_train = np.reshape(x_train, (len(x_train), 1,
1852                                              x_train.shape[1]))
1853      temporal_x_train = np.repeat(temporal_x_train, timesteps, axis=1)
1854      temporal_x_test = np.reshape(x_test, (len(x_test), 1, x_test.shape[1]))
1855      temporal_x_test = np.repeat(temporal_x_test, timesteps, axis=1)
1856
1857      temporal_y_train = np.reshape(y_train, (len(y_train), 1,
1858                                              y_train.shape[1]))
1859      temporal_y_train = np.repeat(temporal_y_train, timesteps, axis=1)
1860      temporal_y_test = np.reshape(y_test, (len(y_test), 1, y_test.shape[1]))
1861      temporal_y_test = np.repeat(temporal_y_test, timesteps, axis=1)
1862
1863      temporal_sample_weight = np.reshape(sample_weight, (len(sample_weight),
1864                                                          1))
1865      temporal_sample_weight = np.repeat(
1866          temporal_sample_weight, timesteps, axis=1)
1867
1868      model.compile(
1869          RMSPropOptimizer(learning_rate=learning_rate),
1870          loss='categorical_crossentropy',
1871          metrics=['acc', metrics_module.CategoricalAccuracy()],
1872          weighted_metrics=['mae', metrics_module.CategoricalAccuracy()],
1873          sample_weight_mode='temporal',
1874          run_eagerly=testing_utils.should_run_eagerly())
1875
1876      model.fit(
1877          temporal_x_train,
1878          temporal_y_train,
1879          batch_size=batch_size,
1880          epochs=epochs // 3,
1881          verbose=0,
1882          sample_weight=temporal_sample_weight)
1883      model.fit(
1884          temporal_x_train,
1885          temporal_y_train,
1886          batch_size=batch_size,
1887          epochs=epochs // 3,
1888          verbose=0,
1889          sample_weight=temporal_sample_weight,
1890          validation_split=0.1)
1891
1892      model.train_on_batch(
1893          temporal_x_train[:batch_size],
1894          temporal_y_train[:batch_size],
1895          sample_weight=temporal_sample_weight[:batch_size])
1896      model.test_on_batch(
1897          temporal_x_train[:batch_size],
1898          temporal_y_train[:batch_size],
1899          sample_weight=temporal_sample_weight[:batch_size])
1900      ref_score = model.evaluate(temporal_x_test, temporal_y_test, verbose=0)
1901      if not context.executing_eagerly():
1902        score = model.evaluate(
1903            temporal_x_test[test_ids], temporal_y_test[test_ids], verbose=0)
1904        self.assertLess(score[0], ref_score[0])
1905
1906  @keras_parameterized.run_all_keras_modes
1907  @keras_parameterized.run_with_all_model_types(exclude_models='sequential')
1908  def test_fit_with_incorrect_weights(self):
1909    input_a = layers_module.Input(shape=(3,), name='input_a')
1910    input_b = layers_module.Input(shape=(3,), name='input_b')
1911
1912    dense = layers_module.Dense(2, name='output_1')
1913    dropout = layers_module.Dropout(0.5, name='output_2')
1914    branch_a = [input_a, dense]
1915    branch_b = [input_b, dense, dropout]
1916
1917    model = testing_utils.get_multi_io_model(branch_a, branch_b)
1918    model.compile(
1919        optimizer='adam',
1920        loss='mse',
1921        run_eagerly=testing_utils.should_run_eagerly())
1922    x = np.random.random((10, 3))
1923    y = np.random.random((10, 2))
1924
1925    with self.assertRaises(ValueError):
1926      model.fit([x, x], [y, y], epochs=1, sample_weight={'unknown': x})
1927
1928    with self.assertRaises(ValueError):
1929      model.fit([x, x], [y, y], epochs=1, class_weight={'unknown': 1})
1930
1931  @keras_parameterized.run_all_keras_modes
1932  def test_default_sample_weight(self):
1933    """Verifies that fit works without having to set sample_weight."""
1934    num_classes = 5
1935    input_dim = 5
1936    timesteps = 3
1937    learning_rate = 0.001
1938
1939    with self.cached_session():
1940      model = sequential.Sequential()
1941      model.add(
1942          layers_module.TimeDistributed(
1943              layers_module.Dense(num_classes),
1944              input_shape=(timesteps, input_dim)))
1945
1946      x = np.random.random((10, timesteps, input_dim))
1947      y = np.random.random((10, timesteps, num_classes))
1948      optimizer = RMSPropOptimizer(learning_rate=learning_rate)
1949
1950      # sample_weight_mode is a list and mode value is None
1951      model.compile(
1952          optimizer,
1953          loss='mse',
1954          sample_weight_mode=[None],
1955          run_eagerly=testing_utils.should_run_eagerly())
1956      model.fit(x, y, epochs=1, batch_size=10)
1957
1958      # sample_weight_mode is a list and mode value is `temporal`
1959      model.compile(
1960          optimizer,
1961          loss='mse',
1962          sample_weight_mode=['temporal'],
1963          run_eagerly=testing_utils.should_run_eagerly())
1964      model.fit(x, y, epochs=1, batch_size=10)
1965
1966      # sample_weight_mode is a dict and mode value is None
1967      model.compile(
1968          optimizer,
1969          loss='mse',
1970          sample_weight_mode={'time_distributed': None},
1971          run_eagerly=testing_utils.should_run_eagerly())
1972      model.fit(x, y, epochs=1, batch_size=10)
1973
1974      # sample_weight_mode is a dict and mode value is `temporal`
1975      model.compile(
1976          optimizer,
1977          loss='mse',
1978          sample_weight_mode={'time_distributed': 'temporal'},
1979          run_eagerly=testing_utils.should_run_eagerly())
1980      model.fit(x, y, epochs=1, batch_size=10)
1981
1982      # sample_weight_mode is a not a list/dict and mode value is None
1983      model.compile(
1984          optimizer,
1985          loss='mse',
1986          sample_weight_mode=None,
1987          run_eagerly=testing_utils.should_run_eagerly())
1988      model.fit(x, y, epochs=1, batch_size=10)
1989
1990      # sample_weight_mode is a not a list/dict and mode value is `temporal`
1991      model.compile(
1992          optimizer,
1993          loss='mse',
1994          sample_weight_mode='temporal',
1995          run_eagerly=testing_utils.should_run_eagerly())
1996      model.fit(x, y, epochs=1, batch_size=10)
1997
1998  def test_sample_weight_tensor(self):
1999    """Tests that sample weight may be defined as a tensor in the graph."""
2000    with ops.get_default_graph().as_default():
2001      # Create a simple pass-through model
2002      inputs = layers_module.Input(shape=1, name='input_layer')
2003      model = training_module.Model(inputs=inputs, outputs=inputs)
2004      model.compile(
2005          loss='mean_absolute_error',
2006          optimizer='adam')
2007
2008      # Prepare sample weights iterator tensor
2009      sample_weights = array_ops.constant(
2010          [[0, .4, 1, 1], [2, .4, .3, 1]])
2011      dataset = dataset_ops.Dataset.from_tensor_slices(sample_weights)
2012      sample_weights = dataset_ops.make_one_shot_iterator(dataset).get_next()
2013      sample_weights = training_utils_v1.standardize_sample_weights(
2014          sample_weights, model.output_names)
2015
2016      # Update model loss with sample weight tensor.
2017      model._compile_weights_loss_and_weighted_metrics(sample_weights)
2018
2019      feeds = {'input_layer:0': [[0], [0], [0], [0]],
2020               'input_layer_target:0': [[1], [1], [1], [1]]}
2021      with self.cached_session() as sess:
2022        self.assertAllClose(
2023            (.4 + 1 + 1) / 4, sess.run(model.total_loss, feed_dict=feeds))
2024        self.assertAllClose(
2025            (2+ .4 + .3 + 1) / 4, sess.run(model.total_loss, feed_dict=feeds))
2026
2027
2028@keras_parameterized.run_all_keras_modes
2029class MaskingTest(keras_parameterized.TestCase):
2030
2031  def _get_model(self, input_shape=None):
2032    layers = [
2033        layers_module.Masking(mask_value=0),
2034        layers_module.TimeDistributed(
2035            layers_module.Dense(1, kernel_initializer='one'))
2036    ]
2037    model = testing_utils.get_model_from_layers(layers, input_shape)
2038    model.compile(
2039        loss='mse',
2040        optimizer=RMSPropOptimizer(learning_rate=0.001),
2041        run_eagerly=testing_utils.should_run_eagerly())
2042    return model
2043
2044  @keras_parameterized.run_with_all_model_types
2045  def test_masking(self):
2046    model = self._get_model(input_shape=(2, 1))
2047    x = np.array([[[1], [1]], [[0], [0]]])
2048    y = np.array([[[1], [1]], [[1], [1]]])
2049    loss = model.train_on_batch(x, y)
2050    self.assertEqual(loss, 0)
2051
2052  @keras_parameterized.run_with_all_model_types(exclude_models='functional')
2053  def test_masking_deferred(self):
2054    model = self._get_model()
2055    x = np.array([[[1], [1]], [[0], [0]]])
2056    y = np.array([[[1], [1]], [[1], [1]]])
2057    loss = model.train_on_batch(x, y)
2058    self.assertEqual(loss, 0)
2059
2060  def test_mask_argument_in_layer(self):
2061    # Test that the mask argument gets correctly passed to a layer in the
2062    # functional API.
2063
2064    class CustomMaskedLayer(layers_module.Layer):
2065
2066      def __init__(self):
2067        super(CustomMaskedLayer, self).__init__()
2068        self.supports_masking = True
2069
2070      def call(self, inputs, mask=None):
2071        assert mask is not None
2072        return inputs
2073
2074      def compute_output_shape(self, input_shape):
2075        return input_shape
2076
2077    x = np.random.random((5, 3))
2078    inputs = layers_module.Input((3,))
2079    masked = layers_module.Masking(mask_value=0)(inputs)
2080    outputs = CustomMaskedLayer()(masked)
2081
2082    model = training_module.Model(inputs, outputs)
2083    model.compile(
2084        loss='mse',
2085        optimizer=RMSPropOptimizer(learning_rate=0.001),
2086        run_eagerly=testing_utils.should_run_eagerly())
2087    y = np.random.random((5, 3))
2088    model.train_on_batch(x, y)
2089
2090
2091@keras_parameterized.run_all_keras_modes
2092class TestDynamicTrainability(keras_parameterized.TestCase):
2093
2094  def test_trainable_warning(self):
2095    x = np.random.random((5, 3))
2096    y = np.random.random((5, 2))
2097
2098    model = sequential.Sequential()
2099    model.add(layers_module.Dense(2, input_dim=3))
2100    model.trainable = False
2101    model.compile(
2102        'rmsprop',
2103        'mse',
2104        run_eagerly=testing_utils.should_run_eagerly())
2105    model.trainable = True
2106    model.train_on_batch(x, y)
2107    self.assertRaises(Warning)
2108
2109  def test_trainable_argument(self):
2110    with self.cached_session():
2111      x = np.random.random((5, 3))
2112      y = np.random.random((5, 2))
2113
2114      model = sequential.Sequential()
2115      model.add(layers_module.Dense(2, input_dim=3, trainable=False))
2116      model.compile(
2117          'rmsprop',
2118          'mse',
2119          run_eagerly=testing_utils.should_run_eagerly())
2120      out = model.predict(x)
2121      model.train_on_batch(x, y)
2122      out_2 = model.predict(x)
2123      self.assertAllClose(out, out_2)
2124
2125      # test with nesting
2126      inputs = layers_module.Input(shape=(3,))
2127      output = model(inputs)
2128      model = training_module.Model(inputs, output)
2129      model.compile(
2130          'rmsprop',
2131          'mse',
2132          run_eagerly=testing_utils.should_run_eagerly())
2133      out = model.predict(x)
2134      model.train_on_batch(x, y)
2135      out_2 = model.predict(x)
2136      self.assertAllClose(out, out_2)
2137
2138  def test_layer_trainability_switch(self):
2139    # with constructor argument, in Sequential
2140    model = sequential.Sequential()
2141    model.add(layers_module.Dense(2, trainable=False, input_dim=1))
2142    self.assertListEqual(model.trainable_weights, [])
2143
2144    # by setting the `trainable` argument, in Sequential
2145    model = sequential.Sequential()
2146    layer = layers_module.Dense(2, input_dim=1)
2147    model.add(layer)
2148    self.assertListEqual(model.trainable_weights, layer.trainable_weights)
2149    layer.trainable = False
2150    self.assertListEqual(model.trainable_weights, [])
2151
2152    # with constructor argument, in Model
2153    x = layers_module.Input(shape=(1,))
2154    y = layers_module.Dense(2, trainable=False)(x)
2155    model = training_module.Model(x, y)
2156    self.assertListEqual(model.trainable_weights, [])
2157
2158    # by setting the `trainable` argument, in Model
2159    x = layers_module.Input(shape=(1,))
2160    layer = layers_module.Dense(2)
2161    y = layer(x)
2162    model = training_module.Model(x, y)
2163    self.assertListEqual(model.trainable_weights, layer.trainable_weights)
2164    layer.trainable = False
2165    self.assertListEqual(model.trainable_weights, [])
2166
2167  def test_model_trainability_switch(self):
2168    # a non-trainable model has no trainable weights
2169    x = layers_module.Input(shape=(1,))
2170    y = layers_module.Dense(2)(x)
2171    model = training_module.Model(x, y)
2172    model.trainable = False
2173    self.assertListEqual(model.trainable_weights, [])
2174
2175    # same for Sequential
2176    model = sequential.Sequential()
2177    model.add(layers_module.Dense(2, input_dim=1))
2178    model.trainable = False
2179    self.assertListEqual(model.trainable_weights, [])
2180
2181  def test_nested_model_trainability(self):
2182    # a Sequential inside a Model
2183    inner_model = sequential.Sequential()
2184    inner_model.add(layers_module.Dense(2, input_dim=1))
2185
2186    x = layers_module.Input(shape=(1,))
2187    y = inner_model(x)
2188    outer_model = training_module.Model(x, y)
2189    self.assertListEqual(outer_model.trainable_weights,
2190                         inner_model.trainable_weights)
2191    inner_model.trainable = False
2192    self.assertListEqual(outer_model.trainable_weights, [])
2193    inner_model.trainable = True
2194    inner_model.layers[-1].trainable = False
2195    self.assertListEqual(outer_model.trainable_weights, [])
2196
2197    # a Sequential inside a Sequential
2198    inner_model = sequential.Sequential()
2199    inner_model.add(layers_module.Dense(2, input_dim=1))
2200    outer_model = sequential.Sequential()
2201    outer_model.add(inner_model)
2202    self.assertListEqual(outer_model.trainable_weights,
2203                         inner_model.trainable_weights)
2204    inner_model.trainable = False
2205    self.assertListEqual(outer_model.trainable_weights, [])
2206    inner_model.trainable = True
2207    inner_model.layers[-1].trainable = False
2208    self.assertListEqual(outer_model.trainable_weights, [])
2209
2210    # a Model inside a Model
2211    x = layers_module.Input(shape=(1,))
2212    y = layers_module.Dense(2)(x)
2213    inner_model = training_module.Model(x, y)
2214    x = layers_module.Input(shape=(1,))
2215    y = inner_model(x)
2216    outer_model = training_module.Model(x, y)
2217    self.assertListEqual(outer_model.trainable_weights,
2218                         inner_model.trainable_weights)
2219    inner_model.trainable = False
2220    self.assertListEqual(outer_model.trainable_weights, [])
2221    inner_model.trainable = True
2222    inner_model.layers[-1].trainable = False
2223    self.assertListEqual(outer_model.trainable_weights, [])
2224
2225    # a Model inside a Sequential
2226    x = layers_module.Input(shape=(1,))
2227    y = layers_module.Dense(2)(x)
2228    inner_model = training_module.Model(x, y)
2229    outer_model = sequential.Sequential()
2230    outer_model.add(inner_model)
2231    self.assertListEqual(outer_model.trainable_weights,
2232                         inner_model.trainable_weights)
2233    inner_model.trainable = False
2234    self.assertListEqual(outer_model.trainable_weights, [])
2235    inner_model.trainable = True
2236    inner_model.layers[-1].trainable = False
2237    self.assertListEqual(outer_model.trainable_weights, [])
2238
2239  def test_gan_workflow(self):
2240    shared_layer = layers_module.BatchNormalization()
2241
2242    inputs1 = input_layer.Input(10)
2243    outputs1 = shared_layer(inputs1)
2244    model1 = training_module.Model(inputs1, outputs1)
2245    shared_layer.trainable = False
2246    model1.compile(
2247        'sgd',
2248        'mse',
2249        run_eagerly=testing_utils.should_run_eagerly())
2250
2251    inputs2 = input_layer.Input(10)
2252    outputs2 = shared_layer(inputs2)
2253    model2 = training_module.Model(inputs2, outputs2)
2254    shared_layer.trainable = True
2255    model2.compile(
2256        'sgd',
2257        'mse',
2258        run_eagerly=testing_utils.should_run_eagerly())
2259
2260    x, y = np.ones((10, 10)), np.ones((10, 10))
2261
2262    out1_0 = model1.predict_on_batch(x)
2263    model1.train_on_batch(x, y)
2264    out1_1 = model1.predict_on_batch(x)
2265    self.assertAllClose(out1_0, out1_1)
2266
2267    out2_0 = model2.predict_on_batch(x)
2268    model2.train_on_batch(x, y)
2269    out2_1 = model2.predict_on_batch(x)
2270    self.assertNotAllClose(out2_0, out2_1)
2271
2272  def test_toggle_value(self):
2273    input_0 = layers_module.Input(shape=(1,))
2274    dense_0 = layers_module.Dense(
2275        1, kernel_initializer='ones', bias_initializer='ones')
2276    dense_1 = layers_module.Dense(
2277        1, kernel_initializer='ones', bias_initializer='ones')
2278    result = layers_module.Add()([dense_0(input_0), dense_1(input_0)])
2279    model = training_module.Model(input_0, result)
2280    dense_0.trainable = False
2281    model.compile(
2282        'sgd',
2283        'mse',
2284        run_eagerly=testing_utils.should_run_eagerly())
2285
2286    x = np.ones((10, 1))
2287    y = 5 * x + 2
2288    model.train_on_batch(x, y)
2289    dense_0.trainable = True
2290    model.train_on_batch(x, y)
2291    kernel, bias = dense_0.get_weights()
2292    self.assertAllEqual([kernel[0, 0], bias[0]], [1., 1.])
2293
2294    kernel, bias = dense_1.get_weights()
2295    self.assertAllClose([kernel[0, 0], bias[0]], [1.1176, 1.1176])
2296
2297
2298class TestTrainingWithDataTensors(keras_parameterized.TestCase):
2299
2300  def test_training_and_eval_methods_on_symbolic_tensors_single_io(self):
2301    with ops.Graph().as_default():
2302      x = layers_module.Input(shape=(3,), name='input')
2303      y = layers_module.Dense(4, name='dense')(x)
2304      model = training_module.Model(x, y)
2305
2306      optimizer = RMSPropOptimizer(learning_rate=0.001)
2307      loss = 'mse'
2308      model.compile(
2309          optimizer,
2310          loss,
2311          metrics=['mae', metrics_module.CategoricalAccuracy()])
2312
2313      inputs = backend.zeros(shape=(10, 3))
2314      targets = backend.zeros(shape=(10, 4))
2315
2316      model.fit(inputs, targets, epochs=1, steps_per_epoch=2, verbose=0)
2317      model.evaluate(inputs, targets, steps=2, verbose=0)
2318      model.predict(inputs, steps=2)
2319      model.train_on_batch(inputs, targets)
2320      model.test_on_batch(inputs, targets)
2321      model.fit(inputs, targets,
2322                epochs=1, steps_per_epoch=2, verbose=0,
2323                validation_data=(inputs, targets), validation_steps=2)
2324
2325      # Test with dynamic shape
2326      inputs = array_ops.placeholder_with_default(
2327          np.zeros((2, 3)), shape=tensor_shape.TensorShape([None, 3]))
2328      targets = array_ops.placeholder_with_default(
2329          np.zeros((2, 4)), shape=tensor_shape.TensorShape([None, 4]))
2330      self.assertEqual(inputs.shape.dims[0].value, None)
2331      model.fit(inputs, targets, epochs=1, steps_per_epoch=2, verbose=0)
2332      model.evaluate(inputs, targets, steps=2, verbose=0)
2333      model.predict(inputs, steps=2)
2334      model.train_on_batch(inputs, targets)
2335      model.test_on_batch(inputs, targets)
2336      model.fit(inputs, targets,
2337                epochs=1, steps_per_epoch=2, verbose=0,
2338                validation_data=(inputs, targets), validation_steps=2)
2339
2340  def test_training_and_eval_methods_on_symbolic_tensors_multi_io(self):
2341    a = layers_module.Input(shape=(3,), name='input_a')
2342    b = layers_module.Input(shape=(3,), name='input_b')
2343
2344    dense = layers_module.Dense(4, name='dense')
2345    c = dense(a)
2346    d = dense(b)
2347    e = layers_module.Dropout(0.5, name='dropout')(c)
2348
2349    model = training_module.Model([a, b], [d, e])
2350
2351    optimizer = 'rmsprop'
2352    loss = 'mse'
2353    loss_weights = [1., 0.5]
2354    model.compile(
2355        optimizer,
2356        loss,
2357        metrics=['mae', metrics_module.CategoricalAccuracy()],
2358        loss_weights=loss_weights)
2359
2360    input_a_tf = array_ops.zeros(shape=(10, 3))
2361    input_b_tf = array_ops.zeros(shape=(10, 3))
2362
2363    output_d_tf = array_ops.zeros(shape=(10, 4))
2364    output_e_tf = array_ops.zeros(shape=(10, 4))
2365
2366    model.fit([input_a_tf, input_b_tf], [output_d_tf, output_e_tf],
2367              epochs=1,
2368              steps_per_epoch=2,
2369              verbose=0)
2370    model.train_on_batch([input_a_tf, input_b_tf], [output_d_tf, output_e_tf])
2371
2372    # Test with dictionary inputs
2373    model.fit({
2374        'input_a': input_a_tf,
2375        'input_b': input_b_tf
2376    }, {
2377        'dense': output_d_tf,
2378        'dropout': output_e_tf
2379    },
2380              epochs=1,
2381              steps_per_epoch=2,
2382              verbose=0)
2383    model.fit({
2384        'input_a': input_a_tf,
2385        'input_b': input_b_tf
2386    }, {
2387        'dense': output_d_tf,
2388        'dropout': output_e_tf
2389    },
2390              validation_data=({
2391                  'input_a': input_a_tf,
2392                  'input_b': input_b_tf
2393              }, {
2394                  'dense': output_d_tf,
2395                  'dropout': output_e_tf
2396              }),
2397              epochs=1,
2398              steps_per_epoch=2,
2399              validation_steps=2,
2400              verbose=0)
2401    model.train_on_batch({
2402        'input_a': input_a_tf,
2403        'input_b': input_b_tf
2404    }, {
2405        'dense': output_d_tf,
2406        'dropout': output_e_tf
2407    })
2408
2409    # Test with validation data
2410    model.fit([input_a_tf, input_b_tf], [output_d_tf, output_e_tf],
2411              validation_data=([input_a_tf,
2412                                input_b_tf], [output_d_tf, output_e_tf]),
2413              epochs=1,
2414              steps_per_epoch=2,
2415              validation_steps=2,
2416              verbose=0)
2417    # Test evaluation / prediction methods
2418    model.evaluate([input_a_tf, input_b_tf], [output_d_tf, output_e_tf],
2419                   steps=2,
2420                   verbose=0)
2421    model.predict([input_a_tf, input_b_tf], steps=2)
2422    model.test_on_batch([input_a_tf, input_b_tf], [output_d_tf, output_e_tf])
2423
2424  @tf_test_util.run_deprecated_v1
2425  def test_model_with_input_feed_tensor(self):
2426    """We test building a model with a TF variable as input.
2427
2428    We should be able to call fit, evaluate, predict,
2429    by only passing them data for the placeholder inputs
2430    in the model.
2431    """
2432    with ops.Graph().as_default(), self.cached_session():
2433      input_a_np = np.random.random((10, 3))
2434      input_b_np = np.random.random((10, 3))
2435
2436      output_a_np = np.random.random((10, 4))
2437      output_b_np = np.random.random((10, 3))
2438
2439      input_v = variables_module.Variable(input_a_np, dtype='float32')
2440      self.evaluate(variables_module.variables_initializer([input_v]))
2441      a = input_layer.Input(tensor=input_v)
2442      b = input_layer.Input(shape=(3,), name='input_b')
2443
2444      a_2 = layers_module.Dense(4, name='dense_1')(a)
2445      dp = layers_module.Dropout(0.5, name='dropout')
2446      b_2 = dp(b)
2447
2448      model = training_module.Model([a, b], [a_2, b_2])
2449      model.summary()
2450
2451      optimizer = 'rmsprop'
2452      loss = 'mse'
2453      loss_weights = [1., 0.5]
2454      model.compile(optimizer, loss, metrics=['mean_squared_error'],
2455                    loss_weights=loss_weights,
2456                    sample_weight_mode=None)
2457
2458      # test train_on_batch
2459      out = model.train_on_batch(input_b_np,
2460                                 [output_a_np, output_b_np])
2461      out = model.train_on_batch({'input_b': input_b_np},
2462                                 [output_a_np, output_b_np])
2463      out = model.test_on_batch({'input_b': input_b_np},
2464                                [output_a_np, output_b_np])
2465      out = model.predict_on_batch({'input_b': input_b_np})
2466
2467      # test fit
2468      out = model.fit({'input_b': input_b_np},
2469                      [output_a_np, output_b_np], epochs=1, batch_size=10)
2470      out = model.fit(input_b_np,
2471                      [output_a_np, output_b_np], epochs=1, batch_size=10)
2472
2473      # test evaluate
2474      out = model.evaluate({'input_b': input_b_np},
2475                           [output_a_np, output_b_np], batch_size=10)
2476      out = model.evaluate(input_b_np,
2477                           [output_a_np, output_b_np], batch_size=10)
2478
2479      # test predict
2480      out = model.predict({'input_b': input_b_np}, batch_size=10)
2481      out = model.predict(input_b_np, batch_size=10)
2482      self.assertEqual(len(out), 2)
2483
2484      # Now test a model with a single input
2485      # i.e. we don't pass any data to fit the model.
2486      self.evaluate(variables_module.variables_initializer([input_v]))
2487      a = input_layer.Input(tensor=input_v)
2488      a_2 = layers_module.Dense(4, name='dense_1')(a)
2489      a_2 = layers_module.Dropout(0.5, name='dropout')(a_2)
2490      model = training_module.Model(a, a_2)
2491      model.summary()
2492
2493      optimizer = 'rmsprop'
2494      loss = 'mse'
2495      model.compile(optimizer, loss, metrics=['mean_squared_error'])
2496
2497      # test train_on_batch
2498      out = model.train_on_batch(None,
2499                                 output_a_np)
2500      out = model.train_on_batch(None,
2501                                 output_a_np)
2502      out = model.test_on_batch(None,
2503                                output_a_np)
2504      out = model.predict_on_batch(None)
2505      out = model.train_on_batch([],
2506                                 output_a_np)
2507      out = model.train_on_batch({},
2508                                 output_a_np)
2509
2510      # test fit
2511      _ = model.fit(None, output_a_np, epochs=1, steps_per_epoch=3)
2512      _ = model.fit(None, output_a_np, epochs=1, steps_per_epoch=3)
2513
2514      # test evaluate
2515      _ = model.evaluate(None, output_a_np, steps=3)
2516      _ = model.evaluate(None, output_a_np, steps=3)
2517
2518      # test predict
2519      out = model.predict(None, steps=3)
2520      out = model.predict(None, steps=3)
2521      self.assertEqual(out.shape, (10 * 3, 4))
2522
2523      # Same, without learning phase
2524      # i.e. we don't pass any data to fit the model.
2525      self.evaluate(variables_module.variables_initializer([input_v]))
2526      a = input_layer.Input(tensor=input_v)
2527      a_2 = layers_module.Dense(4, name='dense_1')(a)
2528      model = training_module.Model(a, a_2)
2529      model.summary()
2530
2531      optimizer = 'rmsprop'
2532      loss = 'mse'
2533      model.compile(optimizer, loss, metrics=['mean_squared_error'])
2534
2535      # test train_on_batch
2536      out = model.train_on_batch(None,
2537                                 output_a_np)
2538      out = model.train_on_batch(None,
2539                                 output_a_np)
2540      out = model.test_on_batch(None,
2541                                output_a_np)
2542      out = model.predict_on_batch(None)
2543      out = model.train_on_batch([],
2544                                 output_a_np)
2545      out = model.train_on_batch({},
2546                                 output_a_np)
2547
2548      # test fit
2549      _ = model.fit(None, output_a_np, epochs=1, steps_per_epoch=10)
2550      _ = model.fit(None, output_a_np, epochs=1, steps_per_epoch=10)
2551
2552      # test evaluate
2553      _ = model.evaluate(None, output_a_np, steps=10)
2554      _ = model.evaluate(None, output_a_np, steps=10)
2555
2556      # test predict
2557      out = model.predict(None, steps=3)
2558      out = model.predict(None, steps=3)
2559      self.assertEqual(out.shape, (10 * 3, 4))
2560
2561  @keras_parameterized.run_all_keras_modes
2562  def test_model_with_partial_loss(self):
2563    with self.cached_session():
2564      a = input_layer.Input(shape=(3,), name='input_a')
2565      a_2 = layers_module.Dense(4, name='dense_1')(a)
2566      dp = layers_module.Dropout(0.5, name='dropout')
2567      a_3 = dp(a_2)
2568      model = training_module.Model(a, [a_2, a_3])
2569
2570      optimizer = 'rmsprop'
2571      loss = {'dropout': 'mse'}
2572      model.compile(optimizer, loss, metrics=['mae'])
2573
2574      input_a_np = np.random.random((10, 3))
2575      output_a_np = np.random.random((10, 4))
2576
2577      # test train_on_batch
2578      _ = model.train_on_batch(input_a_np, output_a_np)
2579      _ = model.test_on_batch(input_a_np, output_a_np)
2580      # fit
2581      _ = model.fit(input_a_np, output_a_np)
2582      # evaluate
2583      _ = model.evaluate(input_a_np, output_a_np)
2584
2585      # Same without dropout.
2586      a = input_layer.Input(shape=(3,), name='input_a')
2587      a_2 = layers_module.Dense(4, name='dense_1')(a)
2588      a_3 = layers_module.Dense(4, name='dense_2')(a_2)
2589      model = training_module.Model(a, [a_2, a_3])
2590
2591      optimizer = 'rmsprop'
2592      loss = {'dense_2': 'mse'}
2593      model.compile(optimizer, loss, metrics={'dense_1': 'mae'})
2594
2595      # test train_on_batch
2596      _ = model.train_on_batch(input_a_np, output_a_np)
2597      _ = model.test_on_batch(input_a_np, output_a_np)
2598      # fit
2599      _ = model.fit(input_a_np, output_a_np)
2600      # evaluate
2601      _ = model.evaluate(input_a_np, output_a_np)
2602
2603  def test_model_with_external_loss(self):
2604    with ops.Graph().as_default(), self.cached_session():
2605      # None loss, only regularization loss.
2606      a = input_layer.Input(shape=(3,), name='input_a')
2607      a_2 = layers_module.Dense(
2608          4, name='dense_1', kernel_regularizer='l1', bias_regularizer='l2')(
2609              a)
2610      dp = layers_module.Dropout(0.5, name='dropout')
2611      a_3 = dp(a_2)
2612
2613      model = training_module.Model(a, [a_2, a_3])
2614
2615      optimizer = 'rmsprop'
2616      loss = None
2617      model.compile(optimizer, loss, metrics=['mae'])
2618
2619      input_a_np = np.random.random((10, 3))
2620
2621      # test train_on_batch
2622      out = model.train_on_batch(input_a_np, None)
2623      out = model.test_on_batch(input_a_np, None)
2624      # fit
2625      out = model.fit(input_a_np, None)
2626      # evaluate
2627      out = model.evaluate(input_a_np, None)
2628
2629      # No dropout, external loss.
2630      a = input_layer.Input(shape=(3,), name='input_a')
2631      a_2 = layers_module.Dense(4, name='dense_1')(a)
2632      a_3 = layers_module.Dense(4, name='dense_2')(a)
2633
2634      model = training_module.Model(a, [a_2, a_3])
2635      model.add_loss(backend.mean(a_3 + a_2))
2636
2637      optimizer = 'rmsprop'
2638      loss = None
2639      model.compile(optimizer, loss, metrics=['mae'])
2640
2641      # test train_on_batch
2642      out = model.train_on_batch(input_a_np, None)
2643      out = model.test_on_batch(input_a_np, None)
2644      # fit
2645      out = model.fit(input_a_np, None)
2646      # evaluate
2647      out = model.evaluate(input_a_np, None)
2648
2649      # Test model with no external data at all.
2650      input_v = variables_module.Variable(input_a_np, dtype='float32')
2651      self.evaluate(variables_module.variables_initializer([input_v]))
2652      a = input_layer.Input(tensor=input_v)
2653      a_2 = layers_module.Dense(4, name='dense_1')(a)
2654      a_2 = layers_module.Dropout(0.5, name='dropout')(a_2)
2655      model = training_module.Model(a, a_2)
2656      model.add_loss(backend.mean(a_2))
2657
2658      model.compile(optimizer='rmsprop',
2659                    loss=None,
2660                    metrics=['mean_squared_error'])
2661
2662      # test train_on_batch
2663      out = model.train_on_batch(None, None)
2664      out = model.test_on_batch(None, None)
2665      out = model.predict_on_batch(None)
2666
2667      # Test multi-output model with no external data at all.
2668      self.evaluate(variables_module.variables_initializer([input_v]))
2669      a = input_layer.Input(tensor=input_v)
2670      a_1 = layers_module.Dense(4, name='dense_1')(a)
2671      a_2 = layers_module.Dropout(0.5, name='dropout')(a_1)
2672      model = training_module.Model(a, [a_1, a_2])
2673      model.add_loss(backend.mean(a_2))
2674
2675      model.compile(optimizer='rmsprop',
2676                    loss=None,
2677                    metrics=['mean_squared_error'])
2678
2679      # test train_on_batch
2680      out = model.train_on_batch(None, None)
2681      out = model.test_on_batch(None, None)
2682      out = model.predict_on_batch(None)
2683
2684      out = model.predict(None, steps=3)
2685      self.assertEqual(len(out), 2)
2686      self.assertEqual(out[0].shape, (10 * 3, 4))
2687      self.assertEqual(out[1].shape, (10 * 3, 4))
2688
2689  def test_target_tensors(self):
2690    with ops.Graph().as_default(), self.cached_session():
2691      # single-output, as list
2692      model = sequential.Sequential()
2693      model.add(layers_module.Dense(4, input_shape=(4,), name='dense'))
2694      input_val = np.random.random((10, 4))
2695      target_val = np.random.random((10, 4))
2696      target = backend.variable(target_val)
2697      model.compile(optimizer='rmsprop', loss='mse', target_tensors=[target])
2698      model.train_on_batch(input_val, None)
2699
2700      # single-output, as single tensor
2701      model.compile(optimizer='rmsprop', loss='mse', target_tensors=target)
2702      model.train_on_batch(input_val, None)
2703
2704      # single-output, as dict
2705      model.compile(optimizer='rmsprop', loss='mse',
2706                    target_tensors={'dense': target})
2707      model.train_on_batch(input_val, None)
2708
2709      # test invalid arguments
2710      with self.assertRaises(TypeError):
2711        model.compile(optimizer='rmsprop', loss='mse',
2712                      target_tensors=set())
2713      with self.assertRaises(ValueError):
2714        model.compile(optimizer='rmsprop', loss='mse',
2715                      target_tensors=[target, target])
2716      with self.assertRaises(ValueError):
2717        model.compile(optimizer='rmsprop', loss='mse',
2718                      target_tensors={'dense2': None})
2719      with self.assertRaises(ValueError):
2720        model.compile(optimizer='rmsprop', loss='mse',
2721                      target_tensors=[target])
2722        model.train_on_batch(input_val, target_val)
2723
2724      # multi-output, as list
2725      input_val = np.random.random((10, 4))
2726      target_val_a = np.random.random((10, 4))
2727      target_val_b = np.random.random((10, 4))
2728      target_a = backend.variable(target_val_a)
2729      target_b = backend.variable(target_val_b)
2730
2731      inputs = layers_module.Input(shape=(4,))
2732      output_a = layers_module.Dense(4, name='dense_a')(inputs)
2733      output_b = layers_module.Dense(4, name='dense_b')(inputs)
2734      model = training_module.Model(inputs, [output_a, output_b])
2735      model.compile(optimizer='rmsprop', loss='mse',
2736                    target_tensors=[target_a, target_b])
2737      model.train_on_batch(input_val, None)
2738
2739      # multi-output, as dict
2740      model.compile(optimizer='rmsprop', loss='mse',
2741                    target_tensors={'dense_a': target_a,
2742                                    'dense_b': target_b})
2743      model.train_on_batch(input_val, None)
2744
2745      # test with sample weights
2746      model.compile(
2747          optimizer='rmsprop',
2748          loss='mse',
2749          metrics=['mae', metrics_module.CategoricalAccuracy()],
2750          target_tensors=[target_a, target_b])
2751      model.train_on_batch(input_val, None,
2752                           sample_weight={'dense_a': np.random.random((10,))})
2753
2754  def test_model_custom_target_tensors(self):
2755    with ops.Graph().as_default(), self.cached_session():
2756      a = input_layer.Input(shape=(3,), name='input_a')
2757      b = input_layer.Input(shape=(3,), name='input_b')
2758
2759      a_2 = layers_module.Dense(4, name='dense_1')(a)
2760      dp = layers_module.Dropout(0.5, name='dropout')
2761      b_2 = dp(b)
2762
2763      y = backend.placeholder([10, 4], name='y')
2764      y1 = backend.placeholder([10, 3], name='y1')
2765      y2 = backend.placeholder([7, 5], name='y2')
2766      model = training_module.Model([a, b], [a_2, b_2])
2767
2768      optimizer = 'rmsprop'
2769      loss = 'mse'
2770      loss_weights = [1., 0.5]
2771
2772      # test list of target tensors
2773      with self.assertRaises(ValueError):
2774        model.compile(optimizer, loss, metrics=[], loss_weights=loss_weights,
2775                      sample_weight_mode=None, target_tensors=[y, y1, y2])
2776      model.compile(optimizer, loss, metrics=[], loss_weights=loss_weights,
2777                    sample_weight_mode=None, target_tensors=[y, y1])
2778      input_a_np = np.random.random((10, 3))
2779      input_b_np = np.random.random((10, 3))
2780
2781      output_a_np = np.random.random((10, 4))
2782      output_b_np = np.random.random((10, 3))
2783
2784      _ = model.train_on_batch([input_a_np, input_b_np],
2785                               [output_a_np, output_b_np], {
2786                                   'dense_1': np.random.random((10,)),
2787                                   'dropout': np.random.random((10,))
2788                               })
2789      # test dictionary of target_tensors
2790      with self.assertRaises(ValueError):
2791        model.compile(optimizer, loss,
2792                      metrics=[],
2793                      loss_weights=loss_weights,
2794                      sample_weight_mode=None,
2795                      target_tensors={'does_not_exist': y2})
2796      # test dictionary of target_tensors
2797      model.compile(optimizer, loss,
2798                    metrics=[],
2799                    loss_weights=loss_weights,
2800                    sample_weight_mode=None,
2801                    target_tensors={'dense_1': y, 'dropout': y1})
2802      _ = model.train_on_batch([input_a_np, input_b_np],
2803                               [output_a_np, output_b_np], {
2804                                   'dense_1': np.random.random((10,)),
2805                                   'dropout': np.random.random((10,))
2806                               })
2807
2808      # test with custom TF placeholder as target
2809      pl_target_a = array_ops.placeholder('float32', shape=(None, 4))
2810      model.compile(optimizer='rmsprop', loss='mse',
2811                    target_tensors={'dense_1': pl_target_a})
2812      model.train_on_batch([input_a_np, input_b_np],
2813                           [output_a_np, output_b_np])
2814
2815
2816class TestTrainingWithMetrics(keras_parameterized.TestCase):
2817  """Training tests related to metrics."""
2818
2819  @keras_parameterized.run_all_keras_modes
2820  def test_metrics_names(self):
2821    a = layers_module.Input(shape=(3,), name='input_a')
2822    b = layers_module.Input(shape=(3,), name='input_b')
2823
2824    dense = layers_module.Dense(4, name='dense')
2825    c = dense(a)
2826    d = dense(b)
2827    e = layers_module.Dropout(0.5, name='dropout')(c)
2828
2829    model = training_module.Model([a, b], [d, e])
2830
2831    optimizer = RMSPropOptimizer(learning_rate=0.001)
2832    metrics = ['mse', metrics_module.BinaryAccuracy()]
2833    model.compile(
2834        optimizer,
2835        loss='mae',
2836        metrics=metrics,
2837        run_eagerly=testing_utils.should_run_eagerly())
2838
2839    mse_metric = 'mse' if context.executing_eagerly() else 'mean_squared_error'
2840    reference_metric_names = [
2841        'loss', 'dense_loss', 'dropout_loss', 'dense_' + mse_metric,
2842        'dense_binary_accuracy', 'dropout_' + mse_metric,
2843        'dropout_binary_accuracy'
2844    ]
2845
2846    input_a_np = np.random.random((10, 3))
2847    input_b_np = np.random.random((10, 3))
2848
2849    output_d_np = np.random.random((10, 4))
2850    output_e_np = np.random.random((10, 4))
2851
2852    model.fit([input_a_np, input_b_np], [output_d_np, output_e_np],
2853              epochs=1,
2854              batch_size=5)
2855    self.assertEqual(reference_metric_names, model.metrics_names)
2856
2857  @keras_parameterized.run_all_keras_modes
2858  def test_metric_state_reset_between_fit_and_evaluate(self):
2859    model = sequential.Sequential()
2860    model.add(layers_module.Dense(3, activation='relu', input_dim=4))
2861    model.add(layers_module.Dense(1, activation='sigmoid'))
2862    acc_obj = metrics_module.BinaryAccuracy()
2863    model.compile(
2864        loss='mae',
2865        metrics=[acc_obj],
2866        optimizer=RMSPropOptimizer(learning_rate=0.001),
2867        run_eagerly=testing_utils.should_run_eagerly())
2868
2869    x_train = np.random.random((100, 4))
2870    y_train = np.random.random((100, 1))
2871    model.fit(x_train, y_train, batch_size=5, epochs=2)
2872    self.assertEqual(self.evaluate(acc_obj.count), 100)
2873
2874    x_test = np.random.random((10, 4))
2875    y_test = np.random.random((10, 1))
2876    model.evaluate(x_test, y_test, batch_size=5)
2877    self.assertEqual(self.evaluate(acc_obj.count), 10)
2878
2879  @keras_parameterized.run_with_all_model_types(exclude_models=['sequential'])
2880  @keras_parameterized.run_all_keras_modes
2881  def test_metrics_valid_compile_input_formats(self):
2882    inp_1 = layers_module.Input(shape=(1,), name='input_1')
2883    inp_2 = layers_module.Input(shape=(1,), name='input_2')
2884    x = layers_module.Dense(3, kernel_initializer='ones', trainable=False)
2885    out_1 = layers_module.Dense(
2886        1, kernel_initializer='ones', name='output_1', trainable=False)
2887    out_2 = layers_module.Dense(
2888        1, kernel_initializer='ones', name='output_2', trainable=False)
2889
2890    branch_a = [inp_1, x, out_1]
2891    branch_b = [inp_2, x, out_2]
2892    model = testing_utils.get_multi_io_model(branch_a, branch_b)
2893
2894    # list of metrics.
2895    model.compile(
2896        optimizer='rmsprop',
2897        loss='mse',
2898        metrics=[metrics_module.MeanSquaredError()],
2899        weighted_metrics=[metrics_module.MeanSquaredError()],
2900        run_eagerly=testing_utils.should_run_eagerly())
2901
2902    # list of list of metrics.
2903    model.compile(
2904        optimizer='rmsprop',
2905        loss='mse',
2906        metrics=[
2907            metrics_module.MeanSquaredError(),
2908            [metrics_module.MeanSquaredError(),
2909             metrics_module.Accuracy()]
2910        ],
2911        weighted_metrics=[
2912            metrics_module.MeanSquaredError(),
2913            [metrics_module.MeanSquaredError(),
2914             metrics_module.Accuracy()]
2915        ],
2916        run_eagerly=testing_utils.should_run_eagerly())
2917
2918    # dict of metrics.
2919    model.compile(
2920        optimizer='rmsprop',
2921        loss='mse',
2922        metrics={
2923            'output_1':
2924                metrics_module.MeanSquaredError(),
2925            'output_2': [
2926                metrics_module.MeanSquaredError(),
2927                metrics_module.Accuracy()
2928            ],
2929        },
2930        weighted_metrics={
2931            'output_1':
2932                metrics_module.MeanSquaredError(),
2933            'output_2': [
2934                metrics_module.MeanSquaredError(),
2935                metrics_module.Accuracy()
2936            ],
2937        },
2938        run_eagerly=testing_utils.should_run_eagerly())
2939
2940  @keras_parameterized.run_all_keras_modes
2941  def test_metrics_masking(self):
2942    np.random.seed(1337)
2943    model = sequential.Sequential()
2944    model.add(layers_module.Masking(mask_value=0, input_shape=(2, 1)))
2945    model.add(
2946        layers_module.TimeDistributed(
2947            layers_module.Dense(1, kernel_initializer='ones')))
2948    model.compile(
2949        RMSPropOptimizer(learning_rate=0.001),
2950        loss='mse',
2951        weighted_metrics=['accuracy'],
2952        run_eagerly=testing_utils.should_run_eagerly())
2953
2954    # verify that masking is applied.
2955    x = np.array([[[1], [1]], [[1], [1]], [[0], [0]]])
2956    y = np.array([[[1], [1]], [[0], [1]], [[1], [1]]])
2957    scores = model.train_on_batch(x, y)
2958    self.assertArrayNear(scores, [0.25, 0.75], 0.1)
2959
2960    # verify that masking is combined with sample weights.
2961    w = np.array([3, 2, 4])
2962    scores = model.train_on_batch(x, y, sample_weight=w)
2963    self.assertArrayNear(scores, [0.3328, 0.8], 0.001)
2964
2965  @keras_parameterized.run_all_keras_modes
2966  def test_add_metric_with_tensor_on_model(self):
2967    x = layers_module.Input(shape=(1,))
2968    y = layers_module.Dense(1, kernel_initializer='ones')(x)
2969    model = training_module.Model(x, y)
2970    model.add_metric(
2971        math_ops.reduce_sum(y), name='metric_1', aggregation='mean')
2972
2973    if context.executing_eagerly():
2974      # This is not a use case in v1 graph mode.
2975      mean_result = metrics_module.Mean()(y)
2976      with self.assertRaisesRegex(
2977          ValueError, 'Expected a symbolic Tensor for the metric value'):
2978        model.add_metric(mean_result, name='metric_2')
2979    else:
2980      with self.assertRaisesRegex(
2981          ValueError, 'Using the result of calling a `Metric` object '):
2982        with backend.get_graph().as_default():
2983          model.add_metric(metrics_module.Mean(name='metric_2')(y))
2984
2985    model.compile(
2986        'sgd',
2987        loss='mse',
2988        run_eagerly=testing_utils.should_run_eagerly())
2989
2990    inputs = np.ones(shape=(10, 1))
2991    targets = np.ones(shape=(10, 1))
2992    history = model.fit(
2993        inputs,
2994        targets,
2995        epochs=2,
2996        batch_size=5,
2997        validation_data=(inputs, targets))
2998    self.assertEqual(history.history['metric_1'][-1], 5)
2999    self.assertEqual(history.history['val_metric_1'][-1], 5)
3000
3001    eval_results = model.evaluate(inputs, targets, batch_size=5)
3002    self.assertEqual(eval_results[-1], 5)
3003
3004    model.predict(inputs, batch_size=5)
3005    model.train_on_batch(inputs, targets)
3006    model.test_on_batch(inputs, targets)
3007
3008  @keras_parameterized.run_all_keras_modes
3009  def test_add_metric_in_model_call(self):
3010
3011    class TestModel(training_module.Model):
3012
3013      def __init__(self):
3014        super(TestModel, self).__init__(name='test_model')
3015        self.dense1 = layers_module.Dense(2, kernel_initializer='ones')
3016        self.mean = metrics_module.Mean(name='metric_1')
3017
3018      def call(self, x):
3019        self.add_metric(
3020            math_ops.reduce_sum(x), name='metric_2', aggregation='mean')
3021        # Provide same name as in the instance created in __init__
3022        # for eager mode
3023        self.add_metric(self.mean(x), name='metric_1')
3024        return self.dense1(x)
3025
3026    model = TestModel()
3027    model.compile(
3028        loss='mse',
3029        optimizer=RMSPropOptimizer(0.01),
3030        run_eagerly=testing_utils.should_run_eagerly())
3031
3032    x = np.ones(shape=(10, 1))
3033    y = np.ones(shape=(10, 2))
3034    history = model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y))
3035    self.assertAlmostEqual(history.history['metric_1'][-1], 1, 0)
3036    self.assertAlmostEqual(history.history['val_metric_1'][-1], 1, 0)
3037    self.assertAlmostEqual(history.history['metric_2'][-1], 5, 0)
3038    self.assertAlmostEqual(history.history['val_metric_2'][-1], 5, 0)
3039
3040    eval_results = model.evaluate(x, y, batch_size=5)
3041    self.assertAlmostEqual(eval_results[1], 1, 0)
3042    self.assertAlmostEqual(eval_results[2], 5, 0)
3043
3044    model.predict(x, batch_size=5)
3045    model.train_on_batch(x, y)
3046    model.test_on_batch(x, y)
3047
3048  @keras_parameterized.run_with_all_model_types
3049  @keras_parameterized.run_all_keras_modes
3050  def test_add_metric_in_layer_call(self):
3051
3052    class TestLayer(layers_module.Layer):
3053
3054      def build(self, input_shape):
3055        self.a = self.add_variable(
3056            'a', (1, 1), initializer='ones', trainable=False)
3057        self.built = True
3058
3059      def call(self, inputs):
3060        self.add_metric(
3061            math_ops.reduce_sum(inputs), name='metric_1', aggregation='mean')
3062        return inputs + 1
3063
3064    layers = [
3065        TestLayer(input_shape=(1,)),
3066        layers_module.Dense(2, kernel_initializer='ones')
3067    ]
3068    model = testing_utils.get_model_from_layers(layers, input_shape=(1,))
3069    model.compile(
3070        loss='mse',
3071        optimizer=RMSPropOptimizer(0.01),
3072        run_eagerly=testing_utils.should_run_eagerly())
3073
3074    x = np.ones(shape=(10, 1))
3075    y = np.ones(shape=(10, 2))
3076    history = model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y))
3077    self.assertEqual(history.history['metric_1'][-1], 5)
3078    self.assertAlmostEqual(history.history['val_metric_1'][-1], 5, 0)
3079
3080  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
3081  def test_model_metrics_list(self):
3082
3083    class LayerWithAddMetric(layers_module.Layer):
3084
3085      def __init__(self):
3086        super(LayerWithAddMetric, self).__init__()
3087        self.dense = layers_module.Dense(1, kernel_initializer='ones')
3088
3089      def __call__(self, inputs):
3090        outputs = self.dense(inputs)
3091        self.add_metric(
3092            math_ops.reduce_sum(outputs), name='metric_1', aggregation='mean')
3093        return outputs
3094
3095    class LayerWithNestedAddMetricLayer(layers_module.Layer):
3096
3097      def __init__(self):
3098        super(LayerWithNestedAddMetricLayer, self).__init__()
3099        self.layer = LayerWithAddMetric()
3100
3101      def call(self, inputs):
3102        outputs = self.layer(inputs)
3103        self.add_metric(
3104            math_ops.reduce_sum(outputs), name='metric_2', aggregation='mean')
3105        return outputs
3106
3107    x = layers_module.Input(shape=(1,))
3108    y = LayerWithNestedAddMetricLayer()(x)
3109
3110    model = training_module.Model(x, y)
3111    model.add_metric(
3112        math_ops.reduce_sum(y), name='metric_3', aggregation='mean')
3113
3114    if context.executing_eagerly():
3115      # This is not a use case in v1 graph mode.
3116      mean_result = metrics_module.Mean()(y)
3117      with self.assertRaisesRegex(
3118          ValueError, 'Expected a symbolic Tensor for the metric value'):
3119        model.add_metric(mean_result, name='metric_4')
3120
3121    else:
3122      with self.assertRaisesRegex(
3123          ValueError, 'Using the result of calling a `Metric` object '):
3124        with backend.get_graph().as_default():
3125          model.add_metric(metrics_module.Mean(name='metric_4')(y))
3126
3127    model.compile(
3128        'sgd',
3129        loss='mse',
3130        metrics=[metrics_module.Accuracy('metric_4')],
3131        run_eagerly=testing_utils.should_run_eagerly())
3132
3133    model.fit(np.ones((10, 1)), np.ones((10, 1)), batch_size=10)
3134
3135    # Verify that the metrics added using `compile` and `add_metric` API are
3136    # included
3137    self.assertEqual([m.name for m in model.metrics],
3138                     ['loss', 'metric_4', 'metric_2', 'metric_1', 'metric_3'])
3139
3140  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
3141  def test_model_metrics_list_in_call(self):
3142
3143    class TestModel(training_module.Model):
3144
3145      def __init__(self):
3146        super(TestModel, self).__init__(name='test_model')
3147        self.dense1 = layers_module.Dense(2, kernel_initializer='ones')
3148
3149      def call(self, x):
3150        self.add_metric(
3151            math_ops.reduce_sum(x), name='metric_1', aggregation='mean')
3152        return self.dense1(x)
3153
3154    model = TestModel()
3155    model.compile(
3156        loss='mse',
3157        optimizer=RMSPropOptimizer(0.01),
3158        metrics=[metrics_module.Accuracy('acc')],
3159        run_eagerly=testing_utils.should_run_eagerly())
3160    x = np.ones(shape=(10, 1))
3161    y = np.ones(shape=(10, 2))
3162    model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y))
3163
3164    self.assertEqual([m.name for m in model.metrics],
3165                     ['loss', 'acc', 'metric_1'])
3166
3167  @keras_parameterized.run_all_keras_modes
3168  def test_multiple_add_metric_calls(self):
3169
3170    class TestModel(training_module.Model):
3171
3172      def __init__(self):
3173        super(TestModel, self).__init__(name='test_model')
3174        self.dense1 = layers_module.Dense(2, kernel_initializer='ones')
3175        self.mean1 = metrics_module.Mean(name='metric_1')
3176        self.mean2 = metrics_module.Mean(name='metric_2')
3177
3178      def call(self, x):
3179        self.add_metric(self.mean2(x), name='metric_2')
3180        self.add_metric(self.mean1(x), name='metric_1')
3181        self.add_metric(
3182            math_ops.reduce_sum(x), name='metric_3', aggregation='mean')
3183        return self.dense1(x)
3184
3185    model = TestModel()
3186    self.assertListEqual([m.name for m in model.metrics],
3187                         ['metric_1', 'metric_2'])
3188    model.compile(
3189        loss='mse',
3190        optimizer=RMSPropOptimizer(0.01),
3191        run_eagerly=testing_utils.should_run_eagerly())
3192
3193    x = np.ones(shape=(10, 1))
3194    y = np.ones(shape=(10, 2))
3195    history = model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y))
3196    self.assertAlmostEqual(history.history['metric_1'][-1], 1, 0)
3197    self.assertAlmostEqual(history.history['metric_2'][-1], 1, 0)
3198    self.assertAlmostEqual(history.history['metric_3'][-1], 5, 0)
3199
3200    eval_results = model.evaluate(x, y, batch_size=5)
3201    self.assertArrayNear(eval_results[1:4], [1, 1, 5], 0.1)
3202
3203    model.predict(x, batch_size=5)
3204    model.train_on_batch(x, y)
3205    model.test_on_batch(x, y)
3206
3207  @keras_parameterized.run_all_keras_modes
3208  def test_multiple_add_metric_calls_layer(self):
3209
3210    class TestLayer(layers_module.Layer):
3211
3212      def __init__(self):
3213        super(TestLayer, self).__init__(name='test_layer')
3214        self.dense1 = layers_module.Dense(2, kernel_initializer='ones')
3215        self.m1 = metrics_module.Mean(name='m_1')
3216        self.m2 = [
3217            metrics_module.Mean(name='m_2'),
3218            metrics_module.Mean(name='m_3')
3219        ]
3220        self.m3 = {
3221            'mean4': metrics_module.Mean(name='m_4'),
3222            'mean5': metrics_module.Mean(name='m_5')
3223        }
3224
3225      def call(self, x):
3226        self.add_metric(self.m2[0](x))
3227        self.add_metric(self.m2[1](x))
3228        self.add_metric(self.m1(x))
3229        self.add_metric(self.m3['mean4'](x))
3230        self.add_metric(self.m3['mean5'](x))
3231        self.add_metric(math_ops.reduce_sum(x), name='m_6', aggregation='mean')
3232        return self.dense1(x)
3233
3234    layer = TestLayer()
3235    self.assertListEqual([m.name for m in layer.metrics],
3236                         ['m_1', 'm_2', 'm_3', 'm_4', 'm_5'])
3237
3238    layer(np.ones((10, 10)))
3239    self.assertListEqual([m.name for m in layer.metrics],
3240                         ['m_1', 'm_2', 'm_3', 'm_4', 'm_5', 'm_6'])
3241
3242  @keras_parameterized.run_all_keras_modes
3243  def test_duplicate_metric_name_in_add_metric(self):
3244
3245    class TestModel(training_module.Model):
3246
3247      def __init__(self):
3248        super(TestModel, self).__init__(name='test_model')
3249        self.dense1 = layers_module.Dense(2, kernel_initializer='ones')
3250        self.mean = metrics_module.Mean(name='metric_1')
3251        self.mean2 = metrics_module.Mean(name='metric_1')
3252
3253      def call(self, x):
3254        self.add_metric(self.mean(x), name='metric_1')
3255        return self.dense1(x)
3256
3257    model = TestModel()
3258    model.compile(
3259        loss='mse',
3260        optimizer=RMSPropOptimizer(0.01),
3261        run_eagerly=testing_utils.should_run_eagerly())
3262
3263    x = np.ones(shape=(10, 1))
3264    y = np.ones(shape=(10, 2))
3265    with self.assertRaisesRegex(
3266        ValueError,
3267        'Please provide different names for the metrics you have added. '
3268        'We found 2 metrics with the name: "metric_1"'):
3269      model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y))
3270
3271  @keras_parameterized.run_all_keras_modes
3272  def test_add_metric_without_name(self):
3273
3274    class TestModel(training_module.Model):
3275
3276      def __init__(self):
3277        super(TestModel, self).__init__(name='test_model')
3278        self.dense1 = layers_module.Dense(2, kernel_initializer='ones')
3279
3280      def call(self, x):
3281        self.add_metric(math_ops.reduce_sum(x), aggregation='mean')
3282        return self.dense1(x)
3283
3284    model = TestModel()
3285    model.compile(
3286        loss='mse',
3287        optimizer=RMSPropOptimizer(0.01),
3288        run_eagerly=testing_utils.should_run_eagerly())
3289    x = np.ones(shape=(10, 1))
3290    y = np.ones(shape=(10, 2))
3291
3292    with self.assertRaisesRegex(ValueError,
3293                                'Please provide a name for your metric like'):
3294      model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y))
3295
3296  @keras_parameterized.run_all_keras_modes
3297  def test_add_metric_correctness(self):
3298    inputs = input_layer.Input(shape=(1,))
3299    targets = input_layer.Input(shape=(1,))
3300
3301    class Bias(layers_module.Layer):
3302
3303      def build(self, input_shape):
3304        self.bias = self.add_variable('bias', (1,), initializer='zeros')
3305        self.mae = metrics_module.MeanAbsoluteError(name='mae_1')
3306
3307      def call(self, inputs):
3308        inputs, targets = inputs
3309        outputs = inputs + self.bias
3310        self.add_metric(self.mae(targets, outputs), name='mae_1')
3311        return outputs
3312
3313    outputs = Bias()([inputs, targets])
3314    model = training_module.Model([inputs, targets], outputs)
3315
3316    model.add_metric(
3317        metrics_module.mean_absolute_error(targets, outputs),
3318        name='mae_2',
3319        aggregation='mean')
3320
3321    model.compile(
3322        loss='mae',
3323        optimizer=optimizer_v2.gradient_descent.SGD(0.1),
3324        metrics=[metrics_module.MeanAbsoluteError(name='mae_3')],
3325        run_eagerly=testing_utils.should_run_eagerly())
3326
3327    x = np.array([[0.], [1.], [2.]])
3328    y = np.array([[0.5], [2.], [3.5]])
3329    history = model.fit([x, y], y, batch_size=3, epochs=5)
3330
3331    expected_val = [1., 0.9, 0.8, 0.7, 0.6]
3332    for key in ['loss', 'mae_1', 'mae_2', 'mae_3']:
3333      self.assertAllClose(history.history[key], expected_val, 1e-3)
3334
3335  @keras_parameterized.run_all_keras_modes
3336  def test_add_metric_order(self):
3337
3338    class MyLayer(layers_module.Layer):
3339
3340      def call(self, inputs, training=None, mask=None):
3341        self.add_metric(
3342            array_ops.ones([32]) * 2.0, name='two', aggregation='mean')
3343        return inputs
3344
3345    class MyModel(training_module.Model):
3346
3347      def __init__(self, **kwargs):
3348        super(MyModel, self).__init__(**kwargs)
3349        self._sampler = MyLayer(name='sampler')
3350
3351      def call(self, inputs, training=None, mask=None):
3352        z = self._sampler(inputs)
3353        self.add_metric(
3354            array_ops.ones([32]) * 1.0, name='one', aggregation='mean')
3355        self.add_metric(
3356            array_ops.ones([32]) * 3.0, name='three', aggregation='mean')
3357        return z
3358
3359    xdata = np.random.uniform(size=[32, 16]).astype(np.float32)
3360    dataset_train = dataset_ops.Dataset.from_tensor_slices((xdata, xdata))
3361    dataset_train = dataset_train.batch(32, drop_remainder=True)
3362
3363    model = MyModel()
3364    model.compile(
3365        optimizer='sgd',
3366        loss='mse',
3367        run_eagerly=testing_utils.should_run_eagerly())
3368    history = model.fit(dataset_train, epochs=3)
3369    self.assertDictEqual(
3370        history.history, {
3371            'loss': [0.0, 0.0, 0.0],
3372            'three': [3.0, 3.0, 3.0],
3373            'two': [2.0, 2.0, 2.0],
3374            'one': [1.0, 1.0, 1.0]
3375        })
3376
3377  @keras_parameterized.run_all_keras_modes
3378  def test_add_metric_aggregation_mean(self):
3379
3380    class TestModel(training_module.Model):
3381
3382      def __init__(self):
3383        super(TestModel, self).__init__(name='test_model')
3384        self.dense1 = layers_module.Dense(2, kernel_initializer='ones')
3385
3386      def call(self, x):
3387        self.add_metric(
3388            math_ops.reduce_sum(x), name='metric_1', aggregation='mean')
3389        return self.dense1(x)
3390
3391    model = TestModel()
3392    model.compile(
3393        'rmsprop', 'mse', run_eagerly=testing_utils.should_run_eagerly())
3394    model.fit(np.ones(shape=(10, 1)), np.ones(shape=(10, 2)), batch_size=5)
3395
3396  @keras_parameterized.run_all_keras_modes
3397  def test_add_metric_aggregation_none(self):
3398
3399    class TestModel(training_module.Model):
3400
3401      def __init__(self):
3402        super(TestModel, self).__init__(name='test_model')
3403        self.dense1 = layers_module.Dense(2, kernel_initializer='ones')
3404        self.mean = metrics_module.Mean(name='metric_1')
3405
3406      def call(self, x):
3407        self.add_metric(self.mean(x), name='metric_1', aggregation=None)
3408        return self.dense1(x)
3409
3410    model = TestModel()
3411    model.compile(
3412        'rmsprop', 'mse', run_eagerly=testing_utils.should_run_eagerly())
3413    model.fit(np.ones(shape=(10, 1)), np.ones(shape=(10, 2)), batch_size=5)
3414
3415  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
3416  def DISABLED_test_add_metric_invalid_aggregation(self):
3417    # TODO(psv): Reenable test once it is fixed.
3418    x = layers_module.Input(shape=(1,))
3419    y = layers_module.Dense(1, kernel_initializer='ones')(x)
3420    model = training_module.Model(x, y)
3421    with self.assertRaisesRegex(ValueError,
3422                                'only `mean` sample-wise metric aggregation'):
3423      model.add_metric(
3424          math_ops.reduce_sum(y), name='metric_1', aggregation='sum')
3425
3426    with self.assertRaisesRegex(ValueError,
3427                                'only `mean` sample-wise metric aggregation'):
3428      model.add_metric(
3429          math_ops.reduce_sum(y), name='metric_1', aggregation=None)
3430
3431  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
3432  def test_calling_evaluate_in_callback_during_fit(self):
3433    # Check fix for a bug that caused `evaluate` to hit a cached dataset
3434    # when run from inside a fit callback.
3435    x = layers_module.Input(shape=(2,))
3436    y = layers_module.Dense(2, kernel_initializer='ones', use_bias=False)(x)
3437    model = training_module.Model(x, y)
3438
3439    ones = np.ones((10, 2), dtype=np.float32)
3440    zeros = np.zeros((10, 2), dtype=np.float32)
3441    train_ds = dataset_ops.Dataset.from_tensor_slices(
3442        (ones, ones)).batch(5)
3443    val_ds_1 = dataset_ops.Dataset.from_tensor_slices(
3444        (ones, ones)).batch(5)
3445    val_ds_2 = dataset_ops.Dataset.from_tensor_slices(
3446        (zeros, zeros)).batch(5)
3447    model.compile('sgd', 'mse', run_eagerly=testing_utils.should_run_eagerly())
3448
3449    class MyCallback(Callback):
3450
3451      def on_epoch_end(self, *args, **kwargs):
3452        eval_result = self.model.evaluate(val_ds_2)
3453        if abs(eval_result) > 1e-7:
3454          raise AssertionError(
3455              'Expected to hit the zeros dataset but got high loss value of %s'
3456              % eval_result)
3457
3458    history = model.fit(
3459        train_ds, validation_data=val_ds_1, callbacks=[MyCallback()])
3460    # Evaluate at the end of fit should hit the ones dataset (cached)
3461    self.assertGreater(abs(history.history['val_loss'][-1]), 0.1)
3462    # Standalone call to evaluate should not hit the cached dataset
3463    eval_result = model.evaluate(val_ds_2)
3464    self.assertLess(abs(eval_result), 1e-7)
3465
3466  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
3467  def test_model_with_nested_compiled_model(self):
3468
3469    class LayerWithAddMetric(layers_module.Layer):
3470
3471      def __init__(self):
3472        super(LayerWithAddMetric, self).__init__()
3473        self.dense = layers_module.Dense(1, kernel_initializer='ones')
3474
3475      def call(self, inputs):
3476        outputs = self.dense(inputs)
3477        self.add_metric(
3478            math_ops.reduce_sum(outputs), name='mean', aggregation='mean')
3479        return outputs
3480
3481    x = layers_module.Input(shape=(1,))
3482    y = LayerWithAddMetric()(x)
3483
3484    inner_model = training_module.Model(x, y)
3485    inner_model.add_metric(
3486        math_ops.reduce_sum(y), name='mean1', aggregation='mean')
3487
3488    inner_model.compile(
3489        'sgd',
3490        loss='mse',
3491        metrics=[metrics_module.Accuracy('acc')],
3492        run_eagerly=testing_utils.should_run_eagerly())
3493    inner_model.fit(np.ones((10, 1)), np.ones((10, 1)), batch_size=10)
3494
3495    self.assertEqual([m.name for m in inner_model.metrics],
3496                     ['loss', 'acc', 'mean', 'mean1'])
3497
3498    x = layers_module.Input(shape=[1])
3499    y = inner_model(x)
3500    outer_model = training_module.Model(x, y)
3501    outer_model.add_metric(
3502        math_ops.reduce_sum(y), name='mean2', aggregation='mean')
3503
3504    outer_model.compile(
3505        'sgd',
3506        loss='mse',
3507        metrics=[metrics_module.Accuracy('acc2')],
3508        run_eagerly=testing_utils.should_run_eagerly())
3509    outer_model.fit(np.ones((10, 1)), np.ones((10, 1)), batch_size=10)
3510    self.assertEqual([m.name for m in outer_model.metrics],
3511                     ['loss', 'acc2', 'mean', 'mean1', 'mean2'])
3512
3513  @keras_parameterized.run_all_keras_modes(always_skip_v1=True)
3514  def test_model_with_metric_class_that_returns_dict(self):
3515    x = layers_module.Input(shape=(2,))
3516    y = layers_module.Dense(3)(x)
3517    model = training_module.Model(x, y)
3518
3519    class DictMetric(metrics_module.Metric):
3520
3521      def __init__(self):
3522        super(DictMetric, self).__init__()
3523        self.sample_count = variables_module.Variable(0)
3524        self.l2_sum = variables_module.Variable(0.)
3525
3526      def update_state(self, y_true, y_pred, sample_weight=None):
3527        self.l2_sum.assign_add(
3528            math_ops.reduce_sum(math_ops.square(y_true - y_pred)))
3529        self.sample_count.assign_add(array_ops.shape(y_true)[0])
3530
3531      def reset_state(self):
3532        self.sample_count.assign(0)
3533        self.l2_sum.assign(0.)
3534
3535      def result(self):
3536        mse = self.l2_sum / math_ops.cast(self.sample_count, 'float32')
3537        rmse = math_ops.sqrt(mse)
3538        return {'my_mse': mse,
3539                'my_rmse': rmse}
3540
3541    model.compile('sgd',
3542                  'mse',
3543                  metrics=['mae', DictMetric()],
3544                  run_eagerly=testing_utils.should_run_eagerly())
3545
3546    history = model.fit(np.ones((10, 2)), np.ones((10, 3)))
3547    self.assertEqual(list(history.history.keys()),
3548                     ['loss', 'mae', 'my_mse', 'my_rmse'])
3549    list_evaluate_res = model.evaluate(
3550        np.ones((10, 2)), np.ones((10, 3)))
3551    self.assertEqual(len(list_evaluate_res), 4)
3552    dict_evaluate_res = model.evaluate(
3553        np.ones((10, 2)), np.ones((10, 3)), return_dict=True)
3554    self.assertEqual(list(dict_evaluate_res.keys()),
3555                     ['loss', 'mae', 'my_mse', 'my_rmse'])
3556    list_train_on_batch_res = model.train_on_batch(
3557        np.ones((10, 2)), np.ones((10, 3)))
3558    self.assertEqual(len(list_train_on_batch_res), 4)
3559    dict_train_on_batch_res = model.train_on_batch(
3560        np.ones((10, 2)), np.ones((10, 3)), return_dict=True)
3561    self.assertEqual(list(dict_train_on_batch_res.keys()),
3562                     ['loss', 'mae', 'my_mse', 'my_rmse'])
3563    list_test_on_batch_res = model.test_on_batch(
3564        np.ones((10, 2)), np.ones((10, 3)))
3565    self.assertEqual(len(list_test_on_batch_res), 4)
3566    dict_test_on_batch_res = model.test_on_batch(
3567        np.ones((10, 2)), np.ones((10, 3)), return_dict=True)
3568    self.assertEqual(list(dict_test_on_batch_res.keys()),
3569                     ['loss', 'mae', 'my_mse', 'my_rmse'])
3570
3571
3572class BareUpdateLayer(layers_module.Layer):
3573
3574  def build(self, input_shape):
3575    self.counter = self.add_weight(
3576        'counter',
3577        dtype='int32',
3578        shape=(),
3579        initializer='zeros',
3580        trainable=False)
3581
3582  def call(self, inputs):
3583    state_ops.assign_add(self.counter, 1)
3584    return math_ops.cast(self.counter, inputs.dtype) * inputs
3585
3586
3587class LambdaUpdateLayer(layers_module.Layer):
3588
3589  def build(self, input_shape):
3590    self.counter = self.add_weight(
3591        'counter',
3592        dtype='int32',
3593        shape=(),
3594        initializer='zeros',
3595        trainable=False)
3596
3597  def call(self, inputs):
3598    # Make sure update isn't run twice.
3599    self.add_update(lambda: state_ops.assign_add(self.counter, 1))
3600    return math_ops.cast(self.counter, inputs.dtype) * inputs
3601
3602
3603class NestedUpdateLayer(layers_module.Layer):
3604
3605  def build(self, input_shape):
3606    self.layer = BareUpdateLayer()
3607    self.layer.build(input_shape)
3608
3609  @property
3610  def counter(self):
3611    return self.layer.counter
3612
3613  def call(self, inputs):
3614    return self.layer(inputs)
3615
3616
3617class SubgraphUpdateLayer(layers_module.Layer):
3618
3619  def build(self, input_shape):
3620    self.counter = self.add_weight(
3621        'counter',
3622        dtype='int32',
3623        shape=(),
3624        initializer='zeros',
3625        trainable=False)
3626
3627  def call(self, inputs, training=None):
3628    if training is None:
3629      training = backend.learning_phase()
3630
3631    if training:
3632      self.counter.assign(self.counter + 1)
3633    return inputs
3634
3635
3636@keras_parameterized.run_all_keras_modes(always_skip_v1=True)
3637class TestAutoUpdates(keras_parameterized.TestCase):
3638
3639  @keras_parameterized.run_with_all_model_types
3640  @parameterized.named_parameters(
3641      ('bare_update', BareUpdateLayer),
3642      ('lambda_update', LambdaUpdateLayer),
3643      ('nested_update', NestedUpdateLayer))
3644  def test_updates_in_model(self, layer_builder):
3645    layer = layer_builder()
3646    x, y = np.ones((10, 10)), np.ones((10, 1))
3647    model = testing_utils.get_model_from_layers(
3648        [layer, layers_module.Dense(1)], input_shape=(10,))
3649    model.compile(
3650        'sgd',
3651        'mse',
3652        run_eagerly=testing_utils.should_run_eagerly())
3653    model.fit(x, y, batch_size=2, epochs=1)
3654    self.assertEqual(self.evaluate(layer.counter), 5)
3655
3656  @keras_parameterized.run_with_all_model_types
3657  def test_lambda_updates_trainable_false(self):
3658    x, y = np.ones((10, 10)), np.ones((10, 1))
3659    layer = LambdaUpdateLayer()
3660    model = testing_utils.get_model_from_layers(
3661        [layer, layers_module.Dense(1)], input_shape=(10,))
3662    model.compile(
3663        'sgd',
3664        'mse',
3665        run_eagerly=testing_utils.should_run_eagerly())
3666    model.fit(x, y, batch_size=2, epochs=1)
3667    self.assertEqual(self.evaluate(layer.counter), 5)
3668    layer.trainable = False
3669    model.compile(
3670        'sgd',
3671        'mse',
3672        run_eagerly=testing_utils.should_run_eagerly())
3673    model.fit(x, y, batch_size=2, epochs=1)
3674    self.assertEqual(self.evaluate(layer.counter), 5)
3675
3676  @keras_parameterized.run_with_all_model_types
3677  def test_subgraph_updates_in_model(self):
3678    layer = SubgraphUpdateLayer()
3679    x, y = np.ones((10, 10)), np.ones((10, 1))
3680    model = testing_utils.get_model_from_layers(
3681        [layer, layers_module.Dense(1)], input_shape=(10,))
3682    model.compile(
3683        'sgd',
3684        'mse',
3685        run_eagerly=testing_utils.should_run_eagerly())
3686    model.fit(x, y, batch_size=2, epochs=1)
3687    self.assertEqual(self.evaluate(layer.counter), 5)
3688
3689  @parameterized.named_parameters(
3690      ('bare_update', BareUpdateLayer),
3691      ('lambda_update', LambdaUpdateLayer),
3692      ('nested_update', NestedUpdateLayer))
3693  def test_updates_standalone_layer(self, layer_builder):
3694    layer = layer_builder()
3695    y = layer(np.ones((10, 10)))
3696    self.evaluate(layer.counter.initializer)
3697    self.evaluate(y)
3698    self.assertEqual(self.evaluate(layer.counter), 1)
3699
3700  def test_trainable_false_standalone_layer(self):
3701    layer = LambdaUpdateLayer()
3702    y = layer(np.ones((10, 10)))
3703    self.evaluate(layer.counter.initializer)
3704    self.evaluate(y)
3705    self.assertEqual(self.evaluate(layer.counter), 1)
3706    layer.trainable = False
3707    y = layer(np.ones((10, 10)))
3708    self.evaluate(y)
3709    self.assertEqual(self.evaluate(layer.counter), 1)
3710
3711  @keras_parameterized.run_with_all_model_types
3712  def test_batchnorm_trainable_false(self):
3713    bn = layers_module.BatchNormalization()
3714    model = testing_utils.get_model_from_layers([bn, layers_module.Dense(1)],
3715                                                input_shape=(10,))
3716    bn.trainable = False
3717    model.compile(
3718        'sgd',
3719        'mse',
3720        run_eagerly=testing_utils.should_run_eagerly())
3721    x, y = np.ones((10, 10)), np.ones((10, 1))
3722    model.fit(x, y, batch_size=2, epochs=1)
3723    self.assertAllEqual(self.evaluate(bn.moving_mean), np.zeros((10,)))
3724    self.assertAllEqual(self.evaluate(bn.moving_variance), np.ones((10,)))
3725
3726
3727class TestFunctionTracing(keras_parameterized.TestCase):
3728
3729  def _seq_model_and_data(self):
3730    model = sequential.Sequential([layers_module.Dense(4, activation='relu')])
3731    model.compile(loss='mse', optimizer='rmsprop')
3732    x = np.random.random((10, 6))
3733    y = np.random.random((10, 4))
3734    return model, x, y
3735
3736  @keras_parameterized.run_all_keras_modes(
3737      always_skip_v1=True, always_skip_eager=True)
3738  def test_no_tracing_between_epoch(self):
3739    model, x, y = self._seq_model_and_data()
3740
3741    logging.set_verbosity(1)
3742    with self.assertLogs(level=1) as logs:
3743      model.fit(x, y, epochs=10, batch_size=5, validation_data=(x, y))
3744
3745    new_func_graph = 'INFO:absl:Creating new FuncGraph for Python function'
3746    self.assertEqual(sum(new_func_graph in log for log in logs.output), 9)
3747
3748  @keras_parameterized.run_all_keras_modes(
3749      always_skip_v1=True, always_skip_eager=True)
3750  def test_evaluate_no_cached_data(self):
3751    model, x, y = self._seq_model_and_data()
3752
3753    new_func_graph = 'INFO:absl:Creating new FuncGraph for Python function'
3754    logging.set_verbosity(1)
3755    with self.assertLogs(level=1) as eval_logs:
3756      for _ in range(6):
3757        model.evaluate(x, y, batch_size=5)
3758    self.assertEqual(sum(new_func_graph in log for log in eval_logs.output), 20)
3759
3760
3761class TestBuildCustomModel(keras_parameterized.TestCase):
3762
3763  @keras_parameterized.run_all_keras_modes
3764  def test_build_list_of_inputs(self):
3765
3766    class MyModel(training_module.Model):
3767
3768      def __init__(self):
3769        super(MyModel, self).__init__()
3770        self.l1 = layers_module.Dense(1)
3771        self.l2 = layers_module.Dense(2)
3772
3773      def call(self, x):
3774        a, b = x
3775        return self.l1(a) + self.l2(b)
3776
3777    # List of tuples
3778    model = MyModel()
3779    model.build([(None, 1), (None, 2)])
3780    self.assertEqual(model.l1.kernel.shape.as_list(), [1, 1])
3781    self.assertEqual(model.l2.kernel.shape.as_list(), [2, 2])
3782    # List of lists
3783    model = MyModel()
3784    model.build([[None, 1], [None, 2]])
3785    self.assertEqual(model.l1.kernel.shape.as_list(), [1, 1])
3786    self.assertEqual(model.l2.kernel.shape.as_list(), [2, 2])
3787
3788  @keras_parameterized.run_all_keras_modes
3789  def test_build_single_inputs(self):
3790
3791    class MyModel(training_module.Model):
3792
3793      def __init__(self):
3794        super(MyModel, self).__init__()
3795        self.l1 = layers_module.Dense(1)
3796
3797      def call(self, x):
3798        return self.l1(x)
3799
3800    model = MyModel()
3801    model.build((None, 1))
3802    self.assertEqual(model.l1.kernel.shape.as_list(), [1, 1])
3803    model = MyModel()
3804    model.build([None, 1])
3805    self.assertEqual(model.l1.kernel.shape.as_list(), [1, 1])
3806
3807  @keras_parameterized.run_all_keras_modes
3808  def test_build_dict_inputs(self):
3809
3810    class MyModel(training_module.Model):
3811
3812      def __init__(self):
3813        super(MyModel, self).__init__()
3814        self.l1 = layers_module.Dense(1)
3815
3816      def call(self, inputs):
3817        return self.l1(inputs['x'])
3818
3819    model = MyModel()
3820    model.build({'x': [None, 16]})
3821    self.assertEqual(model.l1.kernel.shape.as_list(), [16, 1])
3822
3823
3824if __name__ == '__main__':
3825  test.main()
3826