xref: /aosp_15_r20/external/tensorflow/tensorflow/python/keras/layers/core.py (revision b6fb3261f9314811a0f4371741dbb8839866f948)
1# Copyright 2015 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"""Core Keras layers."""
16
17import copy
18import functools
19import operator
20import sys
21import textwrap
22import types as python_types
23import warnings
24
25import numpy as np
26
27from tensorflow.python.eager import backprop
28from tensorflow.python.eager import context
29from tensorflow.python.framework import constant_op
30from tensorflow.python.framework import dtypes
31from tensorflow.python.framework import ops
32from tensorflow.python.framework import sparse_tensor
33from tensorflow.python.framework import tensor_shape
34from tensorflow.python.keras import activations
35from tensorflow.python.keras import backend as K
36from tensorflow.python.keras import constraints
37from tensorflow.python.keras import initializers
38from tensorflow.python.keras import regularizers
39from tensorflow.python.keras.engine import keras_tensor
40from tensorflow.python.keras.engine.base_layer import Layer
41from tensorflow.python.keras.engine.input_spec import InputSpec
42from tensorflow.python.keras.utils import control_flow_util
43from tensorflow.python.keras.utils import conv_utils
44from tensorflow.python.keras.utils import generic_utils
45from tensorflow.python.keras.utils import tf_inspect
46from tensorflow.python.keras.utils import tf_utils
47from tensorflow.python.ops import array_ops
48from tensorflow.python.ops import embedding_ops
49from tensorflow.python.ops import gen_math_ops
50from tensorflow.python.ops import math_ops
51from tensorflow.python.ops import nn
52from tensorflow.python.ops import nn_ops
53from tensorflow.python.ops import sparse_ops
54from tensorflow.python.ops import standard_ops
55from tensorflow.python.ops import variable_scope
56from tensorflow.python.ops.ragged import ragged_getitem
57from tensorflow.python.ops.ragged import ragged_tensor
58from tensorflow.python.platform import tf_logging
59from tensorflow.python.trackable import base as trackable
60from tensorflow.python.util import dispatch
61from tensorflow.python.util import nest
62from tensorflow.python.util import tf_decorator
63from tensorflow.python.util.tf_export import get_canonical_name_for_symbol
64from tensorflow.python.util.tf_export import get_symbol_from_name
65from tensorflow.python.util.tf_export import keras_export
66
67
68# pylint: disable=g-classes-have-attributes
69@keras_export('keras.layers.Masking')
70class Masking(Layer):
71  """Masks a sequence by using a mask value to skip timesteps.
72
73  For each timestep in the input tensor (dimension #1 in the tensor),
74  if all values in the input tensor at that timestep
75  are equal to `mask_value`, then the timestep will be masked (skipped)
76  in all downstream layers (as long as they support masking).
77
78  If any downstream layer does not support masking yet receives such
79  an input mask, an exception will be raised.
80
81  Example:
82
83  Consider a Numpy data array `x` of shape `(samples, timesteps, features)`,
84  to be fed to an LSTM layer. You want to mask timestep #3 and #5 because you
85  lack data for these timesteps. You can:
86
87  - Set `x[:, 3, :] = 0.` and `x[:, 5, :] = 0.`
88  - Insert a `Masking` layer with `mask_value=0.` before the LSTM layer:
89
90  ```python
91  samples, timesteps, features = 32, 10, 8
92  inputs = np.random.random([samples, timesteps, features]).astype(np.float32)
93  inputs[:, 3, :] = 0.
94  inputs[:, 5, :] = 0.
95
96  model = tf.keras.models.Sequential()
97  model.add(tf.keras.layers.Masking(mask_value=0.,
98                                    input_shape=(timesteps, features)))
99  model.add(tf.keras.layers.LSTM(32))
100
101  output = model(inputs)
102  # The time step 3 and 5 will be skipped from LSTM calculation.
103  ```
104
105  See [the masking and padding guide](
106    https://www.tensorflow.org/guide/keras/masking_and_padding)
107  for more details.
108  """
109
110  def __init__(self, mask_value=0., **kwargs):
111    super(Masking, self).__init__(**kwargs)
112    self.supports_masking = True
113    self.mask_value = mask_value
114    self._compute_output_and_mask_jointly = True
115
116  def compute_mask(self, inputs, mask=None):
117    return K.any(math_ops.not_equal(inputs, self.mask_value), axis=-1)
118
119  def call(self, inputs):
120    boolean_mask = K.any(
121        math_ops.not_equal(inputs, self.mask_value), axis=-1, keepdims=True)
122    outputs = inputs * math_ops.cast(boolean_mask, inputs.dtype)
123    # Compute the mask and outputs simultaneously.
124    outputs._keras_mask = array_ops.squeeze(boolean_mask, axis=-1)  # pylint: disable=protected-access
125    return outputs
126
127  def compute_output_shape(self, input_shape):
128    return input_shape
129
130  def get_config(self):
131    config = {'mask_value': self.mask_value}
132    base_config = super(Masking, self).get_config()
133    return dict(list(base_config.items()) + list(config.items()))
134
135
136@keras_export('keras.layers.Dropout')
137class Dropout(Layer):
138  """Applies Dropout to the input.
139
140  The Dropout layer randomly sets input units to 0 with a frequency of `rate`
141  at each step during training time, which helps prevent overfitting.
142  Inputs not set to 0 are scaled up by 1/(1 - rate) such that the sum over
143  all inputs is unchanged.
144
145  Note that the Dropout layer only applies when `training` is set to True
146  such that no values are dropped during inference. When using `model.fit`,
147  `training` will be appropriately set to True automatically, and in other
148  contexts, you can set the kwarg explicitly to True when calling the layer.
149
150  (This is in contrast to setting `trainable=False` for a Dropout layer.
151  `trainable` does not affect the layer's behavior, as Dropout does
152  not have any variables/weights that can be frozen during training.)
153
154  >>> tf.random.set_seed(0)
155  >>> layer = tf.keras.layers.Dropout(.2, input_shape=(2,))
156  >>> data = np.arange(10).reshape(5, 2).astype(np.float32)
157  >>> print(data)
158  [[0. 1.]
159   [2. 3.]
160   [4. 5.]
161   [6. 7.]
162   [8. 9.]]
163  >>> outputs = layer(data, training=True)
164  >>> print(outputs)
165  tf.Tensor(
166  [[ 0.    1.25]
167   [ 2.5   3.75]
168   [ 5.    6.25]
169   [ 7.5   8.75]
170   [10.    0.  ]], shape=(5, 2), dtype=float32)
171
172  Args:
173    rate: Float between 0 and 1. Fraction of the input units to drop.
174    noise_shape: 1D integer tensor representing the shape of the
175      binary dropout mask that will be multiplied with the input.
176      For instance, if your inputs have shape
177      `(batch_size, timesteps, features)` and
178      you want the dropout mask to be the same for all timesteps,
179      you can use `noise_shape=(batch_size, 1, features)`.
180    seed: A Python integer to use as random seed.
181
182  Call arguments:
183    inputs: Input tensor (of any rank).
184    training: Python boolean indicating whether the layer should behave in
185      training mode (adding dropout) or in inference mode (doing nothing).
186  """
187
188  def __init__(self, rate, noise_shape=None, seed=None, **kwargs):
189    super(Dropout, self).__init__(**kwargs)
190    if isinstance(rate, (int, float)) and not 0 <= rate <= 1:
191      raise ValueError(f'Invalid value {rate} received for '
192                       f'`rate`, expected a value between 0 and 1.')
193    self.rate = rate
194    self.noise_shape = noise_shape
195    self.seed = seed
196    self.supports_masking = True
197
198  def _get_noise_shape(self, inputs):
199    # Subclasses of `Dropout` may implement `_get_noise_shape(self, inputs)`,
200    # which will override `self.noise_shape`, and allows for custom noise
201    # shapes with dynamically sized inputs.
202    if self.noise_shape is None:
203      return None
204
205    concrete_inputs_shape = array_ops.shape(inputs)
206    noise_shape = []
207    for i, value in enumerate(self.noise_shape):
208      noise_shape.append(concrete_inputs_shape[i] if value is None else value)
209    return ops.convert_to_tensor_v2_with_dispatch(noise_shape)
210
211  def call(self, inputs, training=None):
212    if training is None:
213      training = K.learning_phase()
214
215    def dropped_inputs():
216      return nn.dropout(
217          inputs,
218          noise_shape=self._get_noise_shape(inputs),
219          seed=self.seed,
220          rate=self.rate)
221
222    output = control_flow_util.smart_cond(training, dropped_inputs,
223                                          lambda: array_ops.identity(inputs))
224    return output
225
226  def compute_output_shape(self, input_shape):
227    return input_shape
228
229  def get_config(self):
230    config = {
231        'rate': self.rate,
232        'noise_shape': self.noise_shape,
233        'seed': self.seed
234    }
235    base_config = super(Dropout, self).get_config()
236    return dict(list(base_config.items()) + list(config.items()))
237
238
239@keras_export('keras.layers.SpatialDropout1D')
240class SpatialDropout1D(Dropout):
241  """Spatial 1D version of Dropout.
242
243  This version performs the same function as Dropout, however, it drops
244  entire 1D feature maps instead of individual elements. If adjacent frames
245  within feature maps are strongly correlated (as is normally the case in
246  early convolution layers) then regular dropout will not regularize the
247  activations and will otherwise just result in an effective learning rate
248  decrease. In this case, SpatialDropout1D will help promote independence
249  between feature maps and should be used instead.
250
251  Args:
252    rate: Float between 0 and 1. Fraction of the input units to drop.
253
254  Call arguments:
255    inputs: A 3D tensor.
256    training: Python boolean indicating whether the layer should behave in
257      training mode (adding dropout) or in inference mode (doing nothing).
258
259  Input shape:
260    3D tensor with shape:
261    `(samples, timesteps, channels)`
262
263  Output shape:
264    Same as input.
265
266  References:
267    - [Efficient Object Localization Using Convolutional
268      Networks](https://arxiv.org/abs/1411.4280)
269  """
270
271  def __init__(self, rate, **kwargs):
272    super(SpatialDropout1D, self).__init__(rate, **kwargs)
273    self.input_spec = InputSpec(ndim=3)
274
275  def _get_noise_shape(self, inputs):
276    input_shape = array_ops.shape(inputs)
277    noise_shape = (input_shape[0], 1, input_shape[2])
278    return noise_shape
279
280
281@keras_export('keras.layers.SpatialDropout2D')
282class SpatialDropout2D(Dropout):
283  """Spatial 2D version of Dropout.
284
285  This version performs the same function as Dropout, however, it drops
286  entire 2D feature maps instead of individual elements. If adjacent pixels
287  within feature maps are strongly correlated (as is normally the case in
288  early convolution layers) then regular dropout will not regularize the
289  activations and will otherwise just result in an effective learning rate
290  decrease. In this case, SpatialDropout2D will help promote independence
291  between feature maps and should be used instead.
292
293  Args:
294    rate: Float between 0 and 1. Fraction of the input units to drop.
295    data_format: 'channels_first' or 'channels_last'.
296      In 'channels_first' mode, the channels dimension
297      (the depth) is at index 1,
298      in 'channels_last' mode is it at index 3.
299      It defaults to the `image_data_format` value found in your
300      Keras config file at `~/.keras/keras.json`.
301      If you never set it, then it will be "channels_last".
302
303  Call arguments:
304    inputs: A 4D tensor.
305    training: Python boolean indicating whether the layer should behave in
306      training mode (adding dropout) or in inference mode (doing nothing).
307
308  Input shape:
309    4D tensor with shape:
310    `(samples, channels, rows, cols)` if data_format='channels_first'
311    or 4D tensor with shape:
312    `(samples, rows, cols, channels)` if data_format='channels_last'.
313
314  Output shape:
315    Same as input.
316
317  References:
318    - [Efficient Object Localization Using Convolutional
319      Networks](https://arxiv.org/abs/1411.4280)
320  """
321
322  def __init__(self, rate, data_format=None, **kwargs):
323    super(SpatialDropout2D, self).__init__(rate, **kwargs)
324    if data_format is None:
325      data_format = K.image_data_format()
326    if data_format not in {'channels_last', 'channels_first'}:
327      raise ValueError('data_format must be in '
328                       '{"channels_last", "channels_first"}')
329    self.data_format = data_format
330    self.input_spec = InputSpec(ndim=4)
331
332  def _get_noise_shape(self, inputs):
333    input_shape = array_ops.shape(inputs)
334    if self.data_format == 'channels_first':
335      return (input_shape[0], input_shape[1], 1, 1)
336    elif self.data_format == 'channels_last':
337      return (input_shape[0], 1, 1, input_shape[3])
338
339
340@keras_export('keras.layers.SpatialDropout3D')
341class SpatialDropout3D(Dropout):
342  """Spatial 3D version of Dropout.
343
344  This version performs the same function as Dropout, however, it drops
345  entire 3D feature maps instead of individual elements. If adjacent voxels
346  within feature maps are strongly correlated (as is normally the case in
347  early convolution layers) then regular dropout will not regularize the
348  activations and will otherwise just result in an effective learning rate
349  decrease. In this case, SpatialDropout3D will help promote independence
350  between feature maps and should be used instead.
351
352  Args:
353    rate: Float between 0 and 1. Fraction of the input units to drop.
354    data_format: 'channels_first' or 'channels_last'.
355        In 'channels_first' mode, the channels dimension (the depth)
356        is at index 1, in 'channels_last' mode is it at index 4.
357        It defaults to the `image_data_format` value found in your
358        Keras config file at `~/.keras/keras.json`.
359        If you never set it, then it will be "channels_last".
360
361  Call arguments:
362    inputs: A 5D tensor.
363    training: Python boolean indicating whether the layer should behave in
364      training mode (adding dropout) or in inference mode (doing nothing).
365
366  Input shape:
367    5D tensor with shape:
368    `(samples, channels, dim1, dim2, dim3)` if data_format='channels_first'
369    or 5D tensor with shape:
370    `(samples, dim1, dim2, dim3, channels)` if data_format='channels_last'.
371
372  Output shape:
373    Same as input.
374
375  References:
376    - [Efficient Object Localization Using Convolutional
377      Networks](https://arxiv.org/abs/1411.4280)
378  """
379
380  def __init__(self, rate, data_format=None, **kwargs):
381    super(SpatialDropout3D, self).__init__(rate, **kwargs)
382    if data_format is None:
383      data_format = K.image_data_format()
384    if data_format not in {'channels_last', 'channels_first'}:
385      raise ValueError('data_format must be in '
386                       '{"channels_last", "channels_first"}')
387    self.data_format = data_format
388    self.input_spec = InputSpec(ndim=5)
389
390  def _get_noise_shape(self, inputs):
391    input_shape = array_ops.shape(inputs)
392    if self.data_format == 'channels_first':
393      return (input_shape[0], input_shape[1], 1, 1, 1)
394    elif self.data_format == 'channels_last':
395      return (input_shape[0], 1, 1, 1, input_shape[4])
396
397
398@keras_export('keras.layers.Activation')
399class Activation(Layer):
400  """Applies an activation function to an output.
401
402  Args:
403    activation: Activation function, such as `tf.nn.relu`, or string name of
404      built-in activation function, such as "relu".
405
406  Usage:
407
408  >>> layer = tf.keras.layers.Activation('relu')
409  >>> output = layer([-3.0, -1.0, 0.0, 2.0])
410  >>> list(output.numpy())
411  [0.0, 0.0, 0.0, 2.0]
412  >>> layer = tf.keras.layers.Activation(tf.nn.relu)
413  >>> output = layer([-3.0, -1.0, 0.0, 2.0])
414  >>> list(output.numpy())
415  [0.0, 0.0, 0.0, 2.0]
416
417  Input shape:
418    Arbitrary. Use the keyword argument `input_shape`
419    (tuple of integers, does not include the batch axis)
420    when using this layer as the first layer in a model.
421
422  Output shape:
423    Same shape as input.
424  """
425
426  def __init__(self, activation, **kwargs):
427    super(Activation, self).__init__(**kwargs)
428    self.supports_masking = True
429    self.activation = activations.get(activation)
430
431  def call(self, inputs):
432    return self.activation(inputs)
433
434  def compute_output_shape(self, input_shape):
435    return input_shape
436
437  def get_config(self):
438    config = {'activation': activations.serialize(self.activation)}
439    base_config = super(Activation, self).get_config()
440    return dict(list(base_config.items()) + list(config.items()))
441
442
443@keras_export('keras.layers.Reshape')
444class Reshape(Layer):
445  """Layer that reshapes inputs into the given shape.
446
447  Input shape:
448    Arbitrary, although all dimensions in the input shape must be known/fixed.
449    Use the keyword argument `input_shape` (tuple of integers, does not include
450    the samples/batch size axis) when using this layer as the first layer
451    in a model.
452
453  Output shape:
454    `(batch_size,) + target_shape`
455
456  Example:
457
458  >>> # as first layer in a Sequential model
459  >>> model = tf.keras.Sequential()
460  >>> model.add(tf.keras.layers.Reshape((3, 4), input_shape=(12,)))
461  >>> # model.output_shape == (None, 3, 4), `None` is the batch size.
462  >>> model.output_shape
463  (None, 3, 4)
464
465  >>> # as intermediate layer in a Sequential model
466  >>> model.add(tf.keras.layers.Reshape((6, 2)))
467  >>> model.output_shape
468  (None, 6, 2)
469
470  >>> # also supports shape inference using `-1` as dimension
471  >>> model.add(tf.keras.layers.Reshape((-1, 2, 2)))
472  >>> model.output_shape
473  (None, 3, 2, 2)
474  """
475
476  def __init__(self, target_shape, **kwargs):
477    """Creates a `tf.keras.layers.Reshape`  layer instance.
478
479    Args:
480      target_shape: Target shape. Tuple of integers, does not include the
481        samples dimension (batch size).
482      **kwargs: Any additional layer keyword arguments.
483    """
484    super(Reshape, self).__init__(**kwargs)
485    self.target_shape = tuple(target_shape)
486
487  def _fix_unknown_dimension(self, input_shape, output_shape):
488    """Find and replace a missing dimension in an output shape.
489
490    This is a near direct port of the internal Numpy function
491    `_fix_unknown_dimension` in `numpy/core/src/multiarray/shape.c`
492
493    Args:
494      input_shape: Shape of array being reshaped
495      output_shape: Desired shape of the array with at most
496        a single -1 which indicates a dimension that should be
497        derived from the input shape.
498
499    Returns:
500      The new output shape with a -1 replaced with its computed value.
501
502    Raises:
503      ValueError: If the total array size of the output_shape is
504      different than the input_shape, or more than one unknown dimension
505      is specified.
506    """
507    output_shape = list(output_shape)
508    msg = ('total size of new array must be unchanged, '
509           'input_shape = {}, output_shape = {}'
510           .format(input_shape, output_shape))
511
512    known, unknown = 1, None
513    for index, dim in enumerate(output_shape):
514      if dim < 0:
515        if unknown is None:
516          unknown = index
517        else:
518          raise ValueError('Can only specify one unknown dimension.')
519      else:
520        known *= dim
521
522    original = np.prod(input_shape, dtype=int)
523    if unknown is not None:
524      if known == 0 or original % known != 0:
525        raise ValueError(msg)
526      output_shape[unknown] = original // known
527    elif original != known:
528      raise ValueError(msg)
529    return output_shape
530
531  def compute_output_shape(self, input_shape):
532    input_shape = tensor_shape.TensorShape(input_shape).as_list()
533    if None in input_shape[1:]:
534      output_shape = [input_shape[0]]
535      # input shape (partially) unknown? replace -1's with None's
536      output_shape += tuple(s if s != -1 else None for s in self.target_shape)
537    else:
538      output_shape = [input_shape[0]]
539      output_shape += self._fix_unknown_dimension(input_shape[1:],
540                                                  self.target_shape)
541    return tensor_shape.TensorShape(output_shape)
542
543  def call(self, inputs):
544    result = array_ops.reshape(
545        inputs, (array_ops.shape(inputs)[0],) + self.target_shape)
546    if not context.executing_eagerly():
547      # Set the static shape for the result since it might lost during array_ops
548      # reshape, eg, some `None` dim in the result could be inferred.
549      result.set_shape(self.compute_output_shape(inputs.shape))
550    return result
551
552  def get_config(self):
553    config = {'target_shape': self.target_shape}
554    base_config = super(Reshape, self).get_config()
555    return dict(list(base_config.items()) + list(config.items()))
556
557
558@keras_export('keras.layers.Permute')
559class Permute(Layer):
560  """Permutes the dimensions of the input according to a given pattern.
561
562  Useful e.g. connecting RNNs and convnets.
563
564  Example:
565
566  ```python
567  model = Sequential()
568  model.add(Permute((2, 1), input_shape=(10, 64)))
569  # now: model.output_shape == (None, 64, 10)
570  # note: `None` is the batch dimension
571  ```
572
573  Args:
574    dims: Tuple of integers. Permutation pattern does not include the
575      samples dimension. Indexing starts at 1.
576      For instance, `(2, 1)` permutes the first and second dimensions
577      of the input.
578
579  Input shape:
580    Arbitrary. Use the keyword argument `input_shape`
581    (tuple of integers, does not include the samples axis)
582    when using this layer as the first layer in a model.
583
584  Output shape:
585    Same as the input shape, but with the dimensions re-ordered according
586    to the specified pattern.
587  """
588
589  def __init__(self, dims, **kwargs):
590    super(Permute, self).__init__(**kwargs)
591    self.dims = tuple(dims)
592    if sorted(dims) != list(range(1, len(dims) + 1)):
593      raise ValueError(
594          'Invalid permutation `dims` for Permute Layer: %s. '
595          'The set of indices in `dims` must be consecutive and start from 1.' %
596          (dims,))
597    self.input_spec = InputSpec(ndim=len(self.dims) + 1)
598
599  def compute_output_shape(self, input_shape):
600    input_shape = tensor_shape.TensorShape(input_shape).as_list()
601    output_shape = copy.copy(input_shape)
602    for i, dim in enumerate(self.dims):
603      target_dim = input_shape[dim]
604      output_shape[i + 1] = target_dim
605    return tensor_shape.TensorShape(output_shape)
606
607  def call(self, inputs):
608    return array_ops.transpose(inputs, perm=(0,) + self.dims)
609
610  def get_config(self):
611    config = {'dims': self.dims}
612    base_config = super(Permute, self).get_config()
613    return dict(list(base_config.items()) + list(config.items()))
614
615
616@keras_export('keras.layers.Flatten')
617class Flatten(Layer):
618  """Flattens the input. Does not affect the batch size.
619
620  Note: If inputs are shaped `(batch,)` without a feature axis, then
621  flattening adds an extra channel dimension and output shape is `(batch, 1)`.
622
623  Args:
624    data_format: A string,
625      one of `channels_last` (default) or `channels_first`.
626      The ordering of the dimensions in the inputs.
627      `channels_last` corresponds to inputs with shape
628      `(batch, ..., channels)` while `channels_first` corresponds to
629      inputs with shape `(batch, channels, ...)`.
630      It defaults to the `image_data_format` value found in your
631      Keras config file at `~/.keras/keras.json`.
632      If you never set it, then it will be "channels_last".
633
634  Example:
635
636  >>> model = tf.keras.Sequential()
637  >>> model.add(tf.keras.layers.Conv2D(64, 3, 3, input_shape=(3, 32, 32)))
638  >>> model.output_shape
639  (None, 1, 10, 64)
640
641  >>> model.add(Flatten())
642  >>> model.output_shape
643  (None, 640)
644
645  """
646
647  def __init__(self, data_format=None, **kwargs):
648    super(Flatten, self).__init__(**kwargs)
649    self.data_format = conv_utils.normalize_data_format(data_format)
650    self.input_spec = InputSpec(min_ndim=1)
651    self._channels_first = self.data_format == 'channels_first'
652
653  def call(self, inputs):
654    if self._channels_first:
655      rank = inputs.shape.rank
656      if rank and rank > 1:
657        # Switch to channels-last format.
658        permutation = [0]
659        permutation.extend(range(2, rank))
660        permutation.append(1)
661        inputs = array_ops.transpose(inputs, perm=permutation)
662
663    if context.executing_eagerly():
664      # Full static shape is guaranteed to be available.
665      # Performance: Using `constant_op` is much faster than passing a list.
666      flattened_shape = constant_op.constant([inputs.shape[0], -1])
667      return array_ops.reshape(inputs, flattened_shape)
668    else:
669      input_shape = inputs.shape
670      rank = input_shape.rank
671      if rank == 1:
672        return array_ops.expand_dims_v2(inputs, axis=1)
673      else:
674        batch_dim = tensor_shape.dimension_value(input_shape[0])
675        non_batch_dims = input_shape[1:]
676        # Reshape in a way that preserves as much shape info as possible.
677        if non_batch_dims.is_fully_defined():
678          last_dim = int(functools.reduce(operator.mul, non_batch_dims))
679          flattened_shape = constant_op.constant([-1, last_dim])
680        elif batch_dim is not None:
681          flattened_shape = constant_op.constant([int(batch_dim), -1])
682        else:
683          flattened_shape = [array_ops.shape_v2(inputs)[0], -1]
684        return array_ops.reshape(inputs, flattened_shape)
685
686  def compute_output_shape(self, input_shape):
687    input_shape = tensor_shape.TensorShape(input_shape).as_list()
688    if not input_shape:
689      output_shape = tensor_shape.TensorShape([1])
690    else:
691      output_shape = [input_shape[0]]
692    if np.all(input_shape[1:]):
693      output_shape += [np.prod(input_shape[1:], dtype=int)]
694    else:
695      output_shape += [None]
696    return tensor_shape.TensorShape(output_shape)
697
698  def get_config(self):
699    config = super(Flatten, self).get_config()
700    config.update({'data_format': self.data_format})
701    return config
702
703
704@keras_export('keras.layers.RepeatVector')
705class RepeatVector(Layer):
706  """Repeats the input n times.
707
708  Example:
709
710  ```python
711  model = Sequential()
712  model.add(Dense(32, input_dim=32))
713  # now: model.output_shape == (None, 32)
714  # note: `None` is the batch dimension
715
716  model.add(RepeatVector(3))
717  # now: model.output_shape == (None, 3, 32)
718  ```
719
720  Args:
721    n: Integer, repetition factor.
722
723  Input shape:
724    2D tensor of shape `(num_samples, features)`.
725
726  Output shape:
727    3D tensor of shape `(num_samples, n, features)`.
728  """
729
730  def __init__(self, n, **kwargs):
731    super(RepeatVector, self).__init__(**kwargs)
732    self.n = n
733    if not isinstance(n, int):
734      raise TypeError(f'Expected an integer value for `n`, got {type(n)}.')
735    self.input_spec = InputSpec(ndim=2)
736
737  def compute_output_shape(self, input_shape):
738    input_shape = tensor_shape.TensorShape(input_shape).as_list()
739    return tensor_shape.TensorShape([input_shape[0], self.n, input_shape[1]])
740
741  def call(self, inputs):
742    return K.repeat(inputs, self.n)
743
744  def get_config(self):
745    config = {'n': self.n}
746    base_config = super(RepeatVector, self).get_config()
747    return dict(list(base_config.items()) + list(config.items()))
748
749
750@keras_export('keras.layers.Lambda')
751class Lambda(Layer):
752  """Wraps arbitrary expressions as a `Layer` object.
753
754  The `Lambda` layer exists so that arbitrary expressions can be used
755  as a `Layer` when constructing `Sequential`
756  and Functional API models. `Lambda` layers are best suited for simple
757  operations or quick experimentation. For more advanced use cases, follow
758  [this guide](https://www.tensorflow.org/guide/keras/custom_layers_and_models)
759  for subclassing `tf.keras.layers.Layer`.
760
761  WARNING: `tf.keras.layers.Lambda` layers have (de)serialization limitations!
762
763  The main reason to subclass `tf.keras.layers.Layer` instead of using a
764  `Lambda` layer is saving and inspecting a Model. `Lambda` layers
765  are saved by serializing the Python bytecode, which is fundamentally
766  non-portable. They should only be loaded in the same environment where
767  they were saved. Subclassed layers can be saved in a more portable way
768  by overriding their `get_config` method. Models that rely on
769  subclassed Layers are also often easier to visualize and reason about.
770
771  Examples:
772
773  ```python
774  # add a x -> x^2 layer
775  model.add(Lambda(lambda x: x ** 2))
776  ```
777  ```python
778  # add a layer that returns the concatenation
779  # of the positive part of the input and
780  # the opposite of the negative part
781
782  def antirectifier(x):
783      x -= K.mean(x, axis=1, keepdims=True)
784      x = K.l2_normalize(x, axis=1)
785      pos = K.relu(x)
786      neg = K.relu(-x)
787      return K.concatenate([pos, neg], axis=1)
788
789  model.add(Lambda(antirectifier))
790  ```
791
792  Variables:
793    While it is possible to use Variables with Lambda layers, this practice is
794    discouraged as it can easily lead to bugs. For instance, consider the
795    following layer:
796
797    ```python
798      scale = tf.Variable(1.)
799      scale_layer = tf.keras.layers.Lambda(lambda x: x * scale)
800    ```
801
802    Because scale_layer does not directly track the `scale` variable, it will
803    not appear in `scale_layer.trainable_weights` and will therefore not be
804    trained if `scale_layer` is used in a Model.
805
806    A better pattern is to write a subclassed Layer:
807
808    ```python
809      class ScaleLayer(tf.keras.layers.Layer):
810        def __init__(self):
811          super(ScaleLayer, self).__init__()
812          self.scale = tf.Variable(1.)
813
814        def call(self, inputs):
815          return inputs * self.scale
816    ```
817
818    In general, Lambda layers can be convenient for simple stateless
819    computation, but anything more complex should use a subclass Layer instead.
820
821  Args:
822    function: The function to be evaluated. Takes input tensor as first
823      argument.
824    output_shape: Expected output shape from function. This argument can be
825      inferred if not explicitly provided. Can be a tuple or function. If a
826      tuple, it only specifies the first dimension onward;
827      sample dimension is assumed either the same as the input: `output_shape =
828        (input_shape[0], ) + output_shape` or, the input is `None` and
829      the sample dimension is also `None`: `output_shape = (None, ) +
830        output_shape` If a function, it specifies the entire shape as a function
831        of the
832      input shape: `output_shape = f(input_shape)`
833    mask: Either None (indicating no masking) or a callable with the same
834      signature as the `compute_mask` layer method, or a tensor that will be
835      returned as output mask regardless of what the input is.
836    arguments: Optional dictionary of keyword arguments to be passed to the
837      function.
838
839  Input shape:
840    Arbitrary. Use the keyword argument input_shape (tuple of
841    integers, does not include the samples axis) when using this layer as the
842    first layer in a model.
843
844  Output shape:
845    Specified by `output_shape` argument
846  """
847
848  @trackable.no_automatic_dependency_tracking
849  def __init__(self, function, output_shape=None, mask=None, arguments=None,
850               **kwargs):
851    super(Lambda, self).__init__(**kwargs)
852
853    self.arguments = arguments or {}
854    self.function = function
855
856    if mask is not None:
857      self.supports_masking = True
858    self.mask = mask
859    self._output_shape = output_shape
860
861    # Warning on every invocation will be quite irksome in Eager mode.
862    self._already_warned = False
863
864    function_args = tf_inspect.getfullargspec(function).args
865    self._fn_expects_training_arg = 'training' in function_args
866    self._fn_expects_mask_arg = 'mask' in function_args
867
868  @tf_utils.shape_type_conversion
869  def compute_output_shape(self, input_shape):
870    if self._output_shape is None:
871      # Make use of existing autocomputation but provide Lambda-specific
872      # error message. This is always safe to run even when the outer context
873      # is Graph mode because Lambda layers don't have side effects such as
874      # `add_loss`.
875      with context.eager_mode():
876        try:
877          return super(Lambda, self).compute_output_shape(input_shape)
878        except NotImplementedError:
879          raise NotImplementedError(
880              'We could not automatically infer the shape of the Lambda\'s '
881              'output. Please specify `output_shape` for this Lambda.')
882
883    if callable(self._output_shape):
884      output_shapes = self._output_shape(input_shape)
885      return tf_utils.convert_shapes(output_shapes, to_tuples=False)
886
887    # Output shapes are passed directly and don't include batch dimension.
888    input_tensor_shape = tf_utils.convert_shapes(input_shape, to_tuples=False)
889    batch_size = nest.flatten(input_tensor_shape)[0][0] if input_shape else None
890
891    def _add_batch(shape):
892      return tensor_shape.TensorShape([batch_size] + shape.as_list())
893
894    output_shapes = tf_utils.convert_shapes(self._output_shape, to_tuples=False)
895    return nest.map_structure(_add_batch, output_shapes)
896
897  def call(self, inputs, mask=None, training=None):
898    # We must copy for thread safety, but it only needs to be a shallow copy.
899    kwargs = {k: v for k, v in self.arguments.items()}
900    if self._fn_expects_mask_arg:
901      kwargs['mask'] = mask
902    if self._fn_expects_training_arg:
903      kwargs['training'] = training
904
905    created_variables = []
906    def _variable_creator(next_creator, **kwargs):
907      var = next_creator(**kwargs)
908      created_variables.append(var)
909      return var
910
911    with backprop.GradientTape(watch_accessed_variables=True) as tape,\
912        variable_scope.variable_creator_scope(_variable_creator):
913      result = self.function(inputs, **kwargs)
914    self._check_variables(created_variables, tape.watched_variables())
915    return result
916
917  def _check_variables(self, created_variables, accessed_variables):
918    if not created_variables and not accessed_variables:
919      # In the common case that a Lambda layer does not touch a Variable, we
920      # don't want to incur the runtime cost of assembling any state used for
921      # checking only to immediately discard it.
922      return
923
924    tracked_weights = set(v.ref() for v in self.weights)
925    untracked_new_vars = [
926        v for v in created_variables if v.ref() not in tracked_weights
927    ]
928    if untracked_new_vars:
929      variable_str = '\n'.join('  {}'.format(i) for i in untracked_new_vars)
930      error_str = textwrap.dedent(
931          '''
932          The following Variables were created within a Lambda layer ({name})
933          but are not tracked by said layer:
934          {variable_str}
935          The layer cannot safely ensure proper Variable reuse across multiple
936          calls, and consquently this behavior is disallowed for safety. Lambda
937          layers are not well suited to stateful computation; instead, writing a
938          subclassed Layer is the recommend way to define layers with
939          Variables.'''
940      ).format(name=self.name, variable_str=variable_str)
941      raise ValueError(error_str)
942
943    untracked_used_vars = [
944        v for v in accessed_variables if v.ref() not in tracked_weights
945    ]
946    if untracked_used_vars and not self._already_warned:
947      variable_str = '\n'.join('  {}'.format(i) for i in untracked_used_vars)
948      self._warn(textwrap.dedent(
949          '''
950          The following Variables were used a Lambda layer's call ({name}), but
951          are not present in its tracked objects:
952          {variable_str}
953          It is possible that this is intended behavior, but it is more likely
954          an omission. This is a strong indication that this layer should be
955          formulated as a subclassed Layer rather than a Lambda layer.'''
956      ).format(name=self.name, variable_str=variable_str))
957      self._already_warned = True
958
959  def _warn(self, msg):
960    # This method will be overridden in a unit test to raise an error, because
961    # self.assertWarns is not universally implemented.
962    return tf_logging.warning(msg)
963
964  def compute_mask(self, inputs, mask=None):
965    if callable(self.mask):
966      return self.mask(inputs, mask)
967    return self.mask
968
969  def get_config(self):
970    function_config = self._serialize_function_to_config(self.function)
971    output_shape_config = self._serialize_function_to_config(self._output_shape,
972                                                             allow_raw=True)
973    config = {
974        'function': function_config[0],
975        'function_type': function_config[1],
976        'module': function_config[2],
977        'output_shape': output_shape_config[0],
978        'output_shape_type': output_shape_config[1],
979        'output_shape_module': output_shape_config[2],
980    }
981    if self.mask is not None:
982      mask_config = self._serialize_function_to_config(self.mask)
983      config.update({
984          'mask': mask_config[0],
985          'mask_type': mask_config[1],
986          'mask_module': mask_config[2]
987      })
988    config['arguments'] = self.arguments
989
990    base_config = super(Lambda, self).get_config()
991    return dict(list(base_config.items()) + list(config.items()))
992
993  def _serialize_function_to_config(self, inputs, allow_raw=False):
994    if isinstance(inputs, python_types.LambdaType):
995      output = generic_utils.func_dump(inputs)
996      output_type = 'lambda'
997      module = inputs.__module__
998    elif callable(inputs):
999      output = inputs.__name__
1000      output_type = 'function'
1001      module = inputs.__module__
1002    elif allow_raw:
1003      output = inputs
1004      output_type = 'raw'
1005      module = None
1006    else:
1007      raise ValueError(
1008          'Invalid input for serialization, type: %s ' % type(inputs))
1009
1010    return output, output_type, module
1011
1012  @classmethod
1013  def from_config(cls, config, custom_objects=None):
1014    config = config.copy()
1015    function = cls._parse_function_from_config(
1016        config, custom_objects, 'function', 'module', 'function_type')
1017
1018    output_shape = cls._parse_function_from_config(
1019        config, custom_objects, 'output_shape', 'output_shape_module',
1020        'output_shape_type')
1021    if 'mask' in config:
1022      mask = cls._parse_function_from_config(
1023          config, custom_objects, 'mask', 'mask_module', 'mask_type')
1024    else:
1025      mask = None
1026
1027    config['function'] = function
1028    config['output_shape'] = output_shape
1029    config['mask'] = mask
1030
1031    # If arguments were numpy array, they have been saved as
1032    # list. We need to recover the ndarray
1033    if 'arguments' in config:
1034      for key in config['arguments']:
1035        if isinstance(config['arguments'][key], dict):
1036          arg_dict = config['arguments'][key]
1037          if 'type' in arg_dict and arg_dict['type'] == 'ndarray':
1038            # Overwrite the argument with its numpy translation
1039            config['arguments'][key] = np.array(arg_dict['value'])
1040
1041    return cls(**config)
1042
1043  @classmethod
1044  def _parse_function_from_config(
1045      cls, config, custom_objects, func_attr_name, module_attr_name,
1046      func_type_attr_name):
1047    globs = globals().copy()
1048    module = config.pop(module_attr_name, None)
1049    if module in sys.modules:
1050      globs.update(sys.modules[module].__dict__)
1051    elif module is not None:
1052      # Note: we don't know the name of the function if it's a lambda.
1053      warnings.warn('{} is not loaded, but a Lambda layer uses it. '
1054                    'It may cause errors.'.format(module)
1055                    , UserWarning)
1056    if custom_objects:
1057      globs.update(custom_objects)
1058    function_type = config.pop(func_type_attr_name)
1059    if function_type == 'function':
1060      # Simple lookup in custom objects
1061      function = generic_utils.deserialize_keras_object(
1062          config[func_attr_name],
1063          custom_objects=custom_objects,
1064          printable_module_name='function in Lambda layer')
1065    elif function_type == 'lambda':
1066      # Unsafe deserialization from bytecode
1067      function = generic_utils.func_load(
1068          config[func_attr_name], globs=globs)
1069    elif function_type == 'raw':
1070      function = config[func_attr_name]
1071    else:
1072      raise TypeError('Unknown function type:', function_type)
1073    return function
1074
1075
1076@keras_export('keras.layers.Dense')
1077class Dense(Layer):
1078  """Just your regular densely-connected NN layer.
1079
1080  `Dense` implements the operation:
1081  `output = activation(dot(input, kernel) + bias)`
1082  where `activation` is the element-wise activation function
1083  passed as the `activation` argument, `kernel` is a weights matrix
1084  created by the layer, and `bias` is a bias vector created by the layer
1085  (only applicable if `use_bias` is `True`). These are all attributes of
1086  `Dense`.
1087
1088  Note: If the input to the layer has a rank greater than 2, then `Dense`
1089  computes the dot product between the `inputs` and the `kernel` along the
1090  last axis of the `inputs` and axis 0 of the `kernel` (using `tf.tensordot`).
1091  For example, if input has dimensions `(batch_size, d0, d1)`,
1092  then we create a `kernel` with shape `(d1, units)`, and the `kernel` operates
1093  along axis 2 of the `input`, on every sub-tensor of shape `(1, 1, d1)`
1094  (there are `batch_size * d0` such sub-tensors).
1095  The output in this case will have shape `(batch_size, d0, units)`.
1096
1097  Besides, layer attributes cannot be modified after the layer has been called
1098  once (except the `trainable` attribute).
1099  When a popular kwarg `input_shape` is passed, then keras will create
1100  an input layer to insert before the current layer. This can be treated
1101  equivalent to explicitly defining an `InputLayer`.
1102
1103  Example:
1104
1105  >>> # Create a `Sequential` model and add a Dense layer as the first layer.
1106  >>> model = tf.keras.models.Sequential()
1107  >>> model.add(tf.keras.Input(shape=(16,)))
1108  >>> model.add(tf.keras.layers.Dense(32, activation='relu'))
1109  >>> # Now the model will take as input arrays of shape (None, 16)
1110  >>> # and output arrays of shape (None, 32).
1111  >>> # Note that after the first layer, you don't need to specify
1112  >>> # the size of the input anymore:
1113  >>> model.add(tf.keras.layers.Dense(32))
1114  >>> model.output_shape
1115  (None, 32)
1116
1117  Args:
1118    units: Positive integer, dimensionality of the output space.
1119    activation: Activation function to use.
1120      If you don't specify anything, no activation is applied
1121      (ie. "linear" activation: `a(x) = x`).
1122    use_bias: Boolean, whether the layer uses a bias vector.
1123    kernel_initializer: Initializer for the `kernel` weights matrix.
1124    bias_initializer: Initializer for the bias vector.
1125    kernel_regularizer: Regularizer function applied to
1126      the `kernel` weights matrix.
1127    bias_regularizer: Regularizer function applied to the bias vector.
1128    activity_regularizer: Regularizer function applied to
1129      the output of the layer (its "activation").
1130    kernel_constraint: Constraint function applied to
1131      the `kernel` weights matrix.
1132    bias_constraint: Constraint function applied to the bias vector.
1133
1134  Input shape:
1135    N-D tensor with shape: `(batch_size, ..., input_dim)`.
1136    The most common situation would be
1137    a 2D input with shape `(batch_size, input_dim)`.
1138
1139  Output shape:
1140    N-D tensor with shape: `(batch_size, ..., units)`.
1141    For instance, for a 2D input with shape `(batch_size, input_dim)`,
1142    the output would have shape `(batch_size, units)`.
1143  """
1144
1145  def __init__(self,
1146               units,
1147               activation=None,
1148               use_bias=True,
1149               kernel_initializer='glorot_uniform',
1150               bias_initializer='zeros',
1151               kernel_regularizer=None,
1152               bias_regularizer=None,
1153               activity_regularizer=None,
1154               kernel_constraint=None,
1155               bias_constraint=None,
1156               **kwargs):
1157    super(Dense, self).__init__(
1158        activity_regularizer=activity_regularizer, **kwargs)
1159
1160    self.units = int(units) if not isinstance(units, int) else units
1161    if self.units < 0:
1162      raise ValueError(f'Received an invalid value for `units`, expected '
1163                       f'a positive integer, got {units}.')
1164    self.activation = activations.get(activation)
1165    self.use_bias = use_bias
1166    self.kernel_initializer = initializers.get(kernel_initializer)
1167    self.bias_initializer = initializers.get(bias_initializer)
1168    self.kernel_regularizer = regularizers.get(kernel_regularizer)
1169    self.bias_regularizer = regularizers.get(bias_regularizer)
1170    self.kernel_constraint = constraints.get(kernel_constraint)
1171    self.bias_constraint = constraints.get(bias_constraint)
1172
1173    self.input_spec = InputSpec(min_ndim=2)
1174    self.supports_masking = True
1175
1176  def build(self, input_shape):
1177    dtype = dtypes.as_dtype(self.dtype or K.floatx())
1178    if not (dtype.is_floating or dtype.is_complex):
1179      raise TypeError('Unable to build `Dense` layer with non-floating point '
1180                      'dtype %s' % (dtype,))
1181
1182    input_shape = tensor_shape.TensorShape(input_shape)
1183    last_dim = tensor_shape.dimension_value(input_shape[-1])
1184    if last_dim is None:
1185      raise ValueError('The last dimension of the inputs to `Dense` '
1186                       'should be defined. Found `None`.')
1187    self.input_spec = InputSpec(min_ndim=2, axes={-1: last_dim})
1188    self.kernel = self.add_weight(
1189        'kernel',
1190        shape=[last_dim, self.units],
1191        initializer=self.kernel_initializer,
1192        regularizer=self.kernel_regularizer,
1193        constraint=self.kernel_constraint,
1194        dtype=self.dtype,
1195        trainable=True)
1196    if self.use_bias:
1197      self.bias = self.add_weight(
1198          'bias',
1199          shape=[self.units,],
1200          initializer=self.bias_initializer,
1201          regularizer=self.bias_regularizer,
1202          constraint=self.bias_constraint,
1203          dtype=self.dtype,
1204          trainable=True)
1205    else:
1206      self.bias = None
1207    self.built = True
1208
1209  def call(self, inputs):
1210    if inputs.dtype.base_dtype != self._compute_dtype_object.base_dtype:
1211      inputs = math_ops.cast(inputs, dtype=self._compute_dtype_object)
1212
1213    rank = inputs.shape.rank
1214    if rank == 2 or rank is None:
1215      # We use embedding_lookup_sparse as a more efficient matmul operation for
1216      # large sparse input tensors. The op will result in a sparse gradient, as
1217      # opposed to sparse_ops.sparse_tensor_dense_matmul which results in dense
1218      # gradients. This can lead to sigfinicant speedups, see b/171762937.
1219      if isinstance(inputs, sparse_tensor.SparseTensor):
1220        # We need to fill empty rows, as the op assumes at least one id per row.
1221        inputs, _ = sparse_ops.sparse_fill_empty_rows(inputs, 0)
1222        # We need to do some munging of our input to use the embedding lookup as
1223        # a matrix multiply. We split our input matrix into separate ids and
1224        # weights tensors. The values of the ids tensor should be the column
1225        # indices of our input matrix and the values of the weights tensor
1226        # can continue to the actual matrix weights.
1227        # The column arrangement of ids and weights
1228        # will be summed over and does not matter. See the documentation for
1229        # sparse_ops.sparse_tensor_dense_matmul a more detailed explanation
1230        # of the inputs to both ops.
1231        ids = sparse_tensor.SparseTensor(
1232            indices=inputs.indices,
1233            values=inputs.indices[:, 1],
1234            dense_shape=inputs.dense_shape)
1235        weights = inputs
1236        outputs = embedding_ops.embedding_lookup_sparse_v2(
1237            self.kernel, ids, weights, combiner='sum')
1238      else:
1239        outputs = gen_math_ops.MatMul(a=inputs, b=self.kernel)
1240    # Broadcast kernel to inputs.
1241    else:
1242      outputs = standard_ops.tensordot(inputs, self.kernel, [[rank - 1], [0]])
1243      # Reshape the output back to the original ndim of the input.
1244      if not context.executing_eagerly():
1245        shape = inputs.shape.as_list()
1246        output_shape = shape[:-1] + [self.kernel.shape[-1]]
1247        outputs.set_shape(output_shape)
1248
1249    if self.use_bias:
1250      outputs = nn_ops.bias_add(outputs, self.bias)
1251
1252    if self.activation is not None:
1253      outputs = self.activation(outputs)
1254    return outputs
1255
1256  def compute_output_shape(self, input_shape):
1257    input_shape = tensor_shape.TensorShape(input_shape)
1258    input_shape = input_shape.with_rank_at_least(2)
1259    if tensor_shape.dimension_value(input_shape[-1]) is None:
1260      raise ValueError(
1261          'The innermost dimension of input_shape must be defined, but saw: %s'
1262          % (input_shape,))
1263    return input_shape[:-1].concatenate(self.units)
1264
1265  def get_config(self):
1266    config = super(Dense, self).get_config()
1267    config.update({
1268        'units': self.units,
1269        'activation': activations.serialize(self.activation),
1270        'use_bias': self.use_bias,
1271        'kernel_initializer': initializers.serialize(self.kernel_initializer),
1272        'bias_initializer': initializers.serialize(self.bias_initializer),
1273        'kernel_regularizer': regularizers.serialize(self.kernel_regularizer),
1274        'bias_regularizer': regularizers.serialize(self.bias_regularizer),
1275        'activity_regularizer':
1276            regularizers.serialize(self.activity_regularizer),
1277        'kernel_constraint': constraints.serialize(self.kernel_constraint),
1278        'bias_constraint': constraints.serialize(self.bias_constraint)
1279    })
1280    return config
1281
1282
1283@keras_export('keras.layers.ActivityRegularization')
1284class ActivityRegularization(Layer):
1285  """Layer that applies an update to the cost function based input activity.
1286
1287  Args:
1288    l1: L1 regularization factor (positive float).
1289    l2: L2 regularization factor (positive float).
1290
1291  Input shape:
1292    Arbitrary. Use the keyword argument `input_shape`
1293    (tuple of integers, does not include the samples axis)
1294    when using this layer as the first layer in a model.
1295
1296  Output shape:
1297    Same shape as input.
1298  """
1299
1300  def __init__(self, l1=0., l2=0., **kwargs):
1301    super(ActivityRegularization, self).__init__(
1302        activity_regularizer=regularizers.L1L2(l1=l1, l2=l2), **kwargs)
1303    self.supports_masking = True
1304    self.l1 = l1
1305    self.l2 = l2
1306
1307  def compute_output_shape(self, input_shape):
1308    return input_shape
1309
1310  def get_config(self):
1311    config = {'l1': self.l1, 'l2': self.l2}
1312    base_config = super(ActivityRegularization, self).get_config()
1313    return dict(list(base_config.items()) + list(config.items()))
1314
1315
1316class TFOpLambda(Layer):
1317  """Wraps TF API symbols in a `Layer` object.
1318
1319  It is inserted by the Functional API construction whenever users call
1320  a supported TF symbol on KerasTensors.
1321
1322  Like Lambda layers, this layer tries to raise warnings when it detects users
1323  explicitly use variables in the call. (To let them know
1324  that the layer will not capture the variables).
1325
1326  This is useful in the case where users do something like:
1327  x = keras.Input(...)
1328  y = tf.Variable(...)
1329  out = x * tf_variable
1330  """
1331
1332  @trackable.no_automatic_dependency_tracking
1333  def __init__(self, function, **kwargs):
1334    self.function = function
1335    self.symbol = (
1336        get_canonical_name_for_symbol(self.function,
1337                                      add_prefix_to_v1_names=True) or
1338        get_canonical_name_for_symbol(self.function,
1339                                      api_name='keras',
1340                                      add_prefix_to_v1_names=True))
1341    if 'name' not in kwargs:
1342      # Generate a name.
1343      # TFOpLambda layers avoid already-observed names,
1344      # because users cannot easily control the generated names.
1345      # Without this avoidance, users would be more likely to run
1346      # into unavoidable duplicate layer name collisions.
1347      # (For standard layers users could just set `name` when creating the
1348      # layer to work around a collision, but they can't do that for
1349      # auto-generated layers)
1350      if self.symbol:
1351        name = 'tf.' + self.symbol
1352      else:
1353        name = self.function.__name__
1354      kwargs['name'] = K.unique_object_name(
1355          name, zero_based=True, avoid_observed_names=True)
1356    kwargs['autocast'] = False
1357
1358    # Decorate the function to produce this layer's call method
1359    def _call_wrapper(*args, **kwargs):
1360      return self._call_wrapper(*args, **kwargs)
1361    self.call = tf_decorator.make_decorator(function, _call_wrapper)
1362
1363    # Do not individually trace op layers in the SavedModel.
1364    self._must_restore_from_config = True
1365
1366    super(TFOpLambda, self).__init__(**kwargs)
1367
1368    # Preserve all argument data structures when saving/loading a config
1369    # (e.g., don't unnest lists that contain one element)
1370    self._preserve_input_structure_in_config = True
1371
1372    # Warning on every invocation will be quite irksome in Eager mode.
1373    self._already_warned = False
1374
1375    self._expects_training_arg = False
1376    self._expects_mask_arg = False
1377
1378  def _call_wrapper(self, *args, **kwargs):
1379    created_variables = []
1380    def _variable_creator(next_creator, **creator_kwargs):
1381      var = next_creator(**creator_kwargs)
1382      created_variables.append(var)
1383      return var
1384
1385    with backprop.GradientTape(watch_accessed_variables=True) as tape, \
1386        variable_scope.variable_creator_scope(_variable_creator):
1387      # We explicitly drop `name` arguments here,
1388      # to guard against the case where an op explicitly has a
1389      # `name` passed (which is susceptible to producing
1390      # multiple ops w/ the same name when the layer is reused)
1391      kwargs.pop('name', None)
1392      result = self.function(*args, **kwargs)
1393    self._check_variables(created_variables, tape.watched_variables())
1394    return result
1395
1396  def _check_variables(self, created_variables, accessed_variables):
1397    if not created_variables and not accessed_variables:
1398      # In the common case that a Lambda layer does not touch a Variable, we
1399      # don't want to incur the runtime cost of assembling any state used for
1400      # checking only to immediately discard it.
1401      return
1402
1403    tracked_weights = set(v.ref() for v in self.weights)
1404    untracked_new_vars = [
1405        v for v in created_variables if v.ref() not in tracked_weights
1406    ]
1407    if untracked_new_vars:
1408      variable_str = '\n'.join('  {}'.format(i) for i in untracked_new_vars)
1409      error_str = textwrap.dedent(
1410          '''
1411          The following Variables were created within a Lambda layer ({name})
1412          but are not tracked by said layer:
1413          {variable_str}
1414          The layer cannot safely ensure proper Variable reuse across multiple
1415          calls, and consquently this behavior is disallowed for safety. Lambda
1416          layers are not well suited to stateful computation; instead, writing a
1417          subclassed Layer is the recommend way to define layers with
1418          Variables.'''
1419      ).format(name=self.name, variable_str=variable_str)
1420      raise ValueError(error_str)
1421
1422    untracked_used_vars = [
1423        v for v in accessed_variables if v.ref() not in tracked_weights
1424    ]
1425    if untracked_used_vars and not self._already_warned:
1426      variable_str = '\n'.join('  {}'.format(i) for i in untracked_used_vars)
1427      self._warn(textwrap.dedent(
1428          '''
1429          The following Variables were used a Lambda layer's call ({name}), but
1430          are not present in its tracked objects:
1431          {variable_str}
1432          It is possible that this is intended behavior, but it is more likely
1433          an omission. This is a strong indication that this layer should be
1434          formulated as a subclassed Layer rather than a Lambda layer.'''
1435      ).format(name=self.name, variable_str=variable_str))
1436      self._already_warned = True
1437
1438  def _warn(self, msg):
1439    # This method will be overridden in a unit test to raise an error, because
1440    # self.assertWarns is not universally implemented.
1441    return tf_logging.warning(msg)
1442
1443  def get_config(self):
1444    if not self.symbol:
1445      raise ValueError('This Keras op layer was generated from %s, a method '
1446                       'that is not an exposed in the TensorFlow API. This '
1447                       'may have happened if the method was explicitly '
1448                       'decorated to add dispatching support, and it was used '
1449                       'during Functional model construction. '
1450                       'To ensure cross-version compatibility of Keras models '
1451                       'that use op layers, only op layers produced from '
1452                       'exported TF API symbols can be serialized.'
1453                       % self.function)
1454    config = {
1455        'function': self.symbol
1456    }
1457
1458    base_config = super(TFOpLambda, self).get_config()
1459    return dict(list(base_config.items()) + list(config.items()))
1460
1461  @classmethod
1462  def from_config(cls, config, custom_objects=None):
1463    config = config.copy()
1464    symbol_name = config['function']
1465    function = get_symbol_from_name(symbol_name)
1466    if not function:
1467      raise ValueError(
1468          'TF symbol `tf.%s` could not be found.' % symbol_name)
1469
1470    config['function'] = function
1471
1472    return cls(**config)
1473
1474
1475class KerasOpDispatcher(dispatch.GlobalOpDispatcher):
1476  """A global dispatcher that allows building a functional model with TF Ops."""
1477
1478  def handle(self, op, args, kwargs):
1479    """Handle the specified operation with the specified arguments."""
1480    if any(
1481        isinstance(x, keras_tensor.KerasTensor)
1482        for x in nest.flatten([args, kwargs])):
1483      return TFOpLambda(op)(*args, **kwargs)
1484    else:
1485      return self.NOT_SUPPORTED
1486
1487KerasOpDispatcher().register()
1488
1489
1490def _slice_to_dict(x):
1491  if isinstance(x, slice):
1492    return {'start': x.start, 'stop': x.stop, 'step': x.step}
1493  return x
1494
1495
1496def _dict_to_slice(x):
1497  if isinstance(x, dict):
1498    return slice(x['start'], x['stop'], x['step'])
1499  return x
1500
1501
1502class SlicingOpLambda(TFOpLambda):
1503  """Wraps TF API symbols in a `Layer` object.
1504
1505  It is inserted by the Functional API construction whenever users call
1506  a supported TF symbol on KerasTensors.
1507
1508  Like Lambda layers, this layer tries to raise warnings when it detects users
1509  explicitly use variables in the call. (To let them know
1510  that the layer will not capture the variables).
1511
1512  This is useful in the case where users do something like:
1513  x = keras.Input(...)
1514  y = tf.Variable(...)
1515  out = x * tf_variable
1516  """
1517
1518  @trackable.no_automatic_dependency_tracking
1519  def __init__(self, function, **kwargs):
1520    super(SlicingOpLambda, self).__init__(function, **kwargs)
1521
1522    original_call = self.call
1523    # Decorate the function to produce this layer's call method
1524    def _call_wrapper(*args, **kwargs):
1525      # Turn any slice dicts in the args back into `slice` objects.
1526      # This conversion cannot use nest.flatten/map_structure,
1527      # because dicts are flattened by nest while slices aren't.
1528      # So, map_structure would only see the individual elements in the
1529      # dict.
1530      # This can't use map_structure_up_to either because the 'shallowness' of
1531      # the shallow tree would have to vary depending on if only one dim or
1532      # multiple are being sliced.
1533      new_args = []
1534      for arg in args:
1535        arg = _dict_to_slice(arg)
1536        if isinstance(arg, (list, tuple)):
1537          new_arg = []
1538          for sub_arg in arg:
1539            new_arg.append(_dict_to_slice(sub_arg))
1540          arg = new_arg
1541        new_args.append(arg)
1542
1543      # Handle the kwargs too.
1544      new_kwargs = {}
1545      for key, value in kwargs.items():
1546        value = _dict_to_slice(value)
1547        if isinstance(value, (list, tuple)):
1548          new_value = []
1549          for v in value:
1550            new_value.append(_dict_to_slice(v))
1551          value = new_value
1552        new_kwargs[key] = value
1553
1554      return original_call(*new_args, **new_kwargs)
1555    self.call = tf_decorator.make_decorator(original_call, _call_wrapper)
1556
1557
1558class TFSlicingOpDispatcher(dispatch.OpDispatcher):
1559  """A global dispatcher that allows building a functional model with TF Ops."""
1560
1561  def __init__(self, op):
1562    self.op = op
1563
1564  def handle(self, args, kwargs):
1565    """Handle the specified operation with the specified arguments."""
1566    args = nest.map_structure(_slice_to_dict, args)
1567    kwargs = nest.map_structure(_slice_to_dict, kwargs)
1568    if any(
1569        isinstance(x, keras_tensor.KerasTensor)
1570        for x in nest.flatten([args, kwargs])):
1571      return SlicingOpLambda(self.op)(*args, **kwargs)
1572    else:
1573      return self.NOT_SUPPORTED
1574
1575for slicing_op in [
1576    array_ops._slice_helper,  # pylint: disable=protected-access
1577    array_ops.boolean_mask,
1578    array_ops.boolean_mask_v2,
1579    ragged_getitem.ragged_tensor_getitem
1580]:
1581  TFSlicingOpDispatcher(slicing_op).register(slicing_op)
1582
1583
1584class InstanceProperty(Layer):
1585  """Wraps an instance property access (e.g. `x.foo`) in a Keras Layer.
1586
1587  This layer takes an attribute name `attr_name` in the constructor and,
1588  when called on input tensor `obj` returns `obj.attr_name`.
1589
1590  KerasTensors specialized for specific extension types use it to
1591  represent instance property accesses on the represented object in the
1592  case where the property needs to be dynamically accessed as opposed to
1593  being statically computed from the typespec, e.g.
1594
1595  x = keras.Input(..., ragged=True)
1596  out = x.flat_values
1597  """
1598
1599  @trackable.no_automatic_dependency_tracking
1600  def __init__(self, attr_name, **kwargs):
1601    self.attr_name = attr_name
1602
1603    if 'name' not in kwargs:
1604      kwargs['name'] = K.unique_object_name(
1605          'input.' + self.attr_name, zero_based=True, avoid_observed_names=True)
1606    kwargs['autocast'] = False
1607
1608    # Do not individually trace op layers in the SavedModel.
1609    self._must_restore_from_config = True
1610
1611    super(InstanceProperty, self).__init__(**kwargs)
1612
1613    # Preserve all argument data structures when saving/loading a config
1614    # (e.g., don't unnest lists that contain one element)
1615    self._preserve_input_structure_in_config = True
1616
1617  def call(self, obj):
1618    return getattr(obj, self.attr_name)
1619
1620  def get_config(self):
1621    config = {
1622        'attr_name': self.attr_name
1623    }
1624    base_config = super(InstanceProperty, self).get_config()
1625    return dict(list(base_config.items()) + list(config.items()))
1626
1627  @classmethod
1628  def from_config(cls, config, custom_objects=None):
1629    return cls(**config)
1630
1631
1632class InstanceMethod(InstanceProperty):
1633  """Wraps an instance method access (e.g. `x.foo(arg)` in a Keras Layer.
1634
1635  This layer takes an attribute name `attr_name` in the constructor and,
1636  when called on input tensor `obj` with additional arguments `args` and
1637  `kwargs` returns `obj.attr_name(*args, **kwargs)`.
1638
1639  KerasTensors specialized for specific extension types use it to
1640  represent dynamic instance method calls on the represented object, e.g.
1641
1642  x = keras.Input(..., ragged=True)
1643  new_values = keras.Input(...)
1644  out = x.with_values(new_values)
1645  """
1646
1647  def call(self, obj, args, kwargs):
1648    method = getattr(obj, self.attr_name)
1649    return method(*args, **kwargs)
1650
1651
1652def _delegate_property(keras_tensor_cls, property_name):  # pylint: disable=invalid-name
1653  """Register property on a KerasTensor class.
1654
1655  Calling this multiple times with the same arguments should be a no-op.
1656
1657  This method exposes a property on the KerasTensor class that will use an
1658  `InstanceProperty` layer to access the property on the represented
1659  intermediate values in the model.
1660
1661  Args:
1662    keras_tensor_cls: The KerasTensor subclass that should expose the property.
1663    property_name: The name of the property to expose and delegate to the
1664      represented (Composite)Tensor.
1665  """
1666  # We use a lambda because we can't create a Keras layer at import time
1667  # due to dynamic layer class versioning.
1668  property_access = property(lambda self: InstanceProperty(property_name)(self))  # pylint: disable=unnecessary-lambda
1669  setattr(keras_tensor_cls, property_name, property_access)
1670
1671
1672def _delegate_method(keras_tensor_cls, method_name):  # pylint: disable=invalid-name
1673  """Register method on a KerasTensor class.
1674
1675  Calling this function times with the same arguments should be a no-op.
1676
1677  This method exposes an instance method on the KerasTensor class that will use
1678  an `InstanceMethod` layer to run the desired method on the represented
1679  intermediate values in the model.
1680
1681  Args:
1682    keras_tensor_cls: The KerasTensor subclass that should expose the property.
1683    method_name: The name of the method to expose and delegate to the
1684      represented (Composite)Tensor.
1685  """
1686  def delegate(self, *args, **kwargs):
1687    return InstanceMethod(method_name)(self, args, kwargs)
1688  setattr(keras_tensor_cls, method_name, delegate)
1689
1690# We do not support the `uniform_row_length` property because it
1691# returns either `None` or an int tensor, and code that relies on it tends
1692# to check `is None` directly. Delegating it here would always return a
1693# `KerasTensor`, regardless of what can be statically inferred. This would
1694# never equal `None`, breaking code that expects it to be partially-static
1695# in unpredictable ways.
1696for ragged_property in [
1697    'values',
1698    'flat_values',
1699    'row_splits',
1700    'nested_row_splits'
1701]:
1702  _delegate_property(keras_tensor.RaggedKerasTensor, ragged_property)
1703
1704for ragged_method_name in [
1705    'value_rowids',
1706    'nested_value_rowids',
1707    'nrows',
1708    'row_starts',
1709    'row_limits',
1710    'row_lengths',
1711    'nested_row_lengths',
1712    'bounding_shape',
1713    'with_values',
1714    'with_flat_values',
1715    'with_row_splits_dtype',
1716    'merge_dims',
1717    'to_tensor',
1718    'to_sparse',
1719]:
1720  _delegate_method(keras_tensor.RaggedKerasTensor, ragged_method_name)
1721
1722for sparse_property in [
1723    'indices',
1724    'values',
1725]:
1726  _delegate_property(keras_tensor.SparseKerasTensor, sparse_property)
1727
1728for sparse_method in [
1729    'with_values',
1730]:
1731  _delegate_method(keras_tensor.SparseKerasTensor, sparse_method)
1732
1733
1734class ClassMethod(Layer):
1735  """Wraps a TF API Class's class method  in a `Layer` object.
1736
1737  It is inserted by the Functional API construction whenever users call
1738  a supported TF Class's class method on KerasTensors.
1739
1740  This is useful in the case where users do something like:
1741  x = keras.Input(...)
1742  y = keras.Input(...)
1743  out = tf.RaggedTensor.from_row_splits(x, y)
1744  """
1745
1746  @trackable.no_automatic_dependency_tracking
1747  def __init__(self, cls_ref, method_name, **kwargs):
1748    self.cls_ref = cls_ref
1749    self.method_name = method_name
1750    self.cls_symbol = (
1751        get_canonical_name_for_symbol(self.cls_ref,
1752                                      add_prefix_to_v1_names=True) or
1753        get_canonical_name_for_symbol(self.cls_ref,
1754                                      api_name='keras',
1755                                      add_prefix_to_v1_names=True))
1756    if 'name' not in kwargs:
1757      kwargs['name'] = K.unique_object_name(
1758          'tf.' + self.cls_symbol + '.' + self.method_name, zero_based=True,
1759          avoid_observed_names=True)
1760    kwargs['autocast'] = False
1761
1762    # Do not individually trace op layers in the SavedModel.
1763    self._must_restore_from_config = True
1764
1765    super(ClassMethod, self).__init__(**kwargs)
1766
1767    # Preserve all argument data structures when saving/loading a config
1768    # (e.g., don't unnest lists that contain one element)
1769    self._preserve_input_structure_in_config = True
1770
1771    self._expects_training_arg = False
1772    self._expects_mask_arg = False
1773
1774  def call(self, args, kwargs):
1775    return getattr(self.cls_ref, self.method_name)(*args, **kwargs)
1776
1777  def get_config(self):
1778    if not self.cls_symbol:
1779      raise ValueError('This Keras class method conversion tried to convert '
1780                       'a method belonging to class %s, a class '
1781                       'that is not an exposed in the TensorFlow API. '
1782                       'To ensure cross-version compatibility of Keras models '
1783                       'that use op layers, only op layers produced from '
1784                       'exported TF API symbols can be serialized.'
1785                       % self.cls_symbol)
1786    config = {
1787        'cls_symbol': self.cls_symbol,
1788        'method_name': self.method_name
1789    }
1790
1791    base_config = super(ClassMethod, self).get_config()
1792    return dict(list(base_config.items()) + list(config.items()))
1793
1794  @classmethod
1795  def from_config(cls, config, custom_objects=None):
1796    config = config.copy()
1797    symbol_name = config.pop('cls_symbol')
1798    cls_ref = get_symbol_from_name(symbol_name)
1799    if not cls_ref:
1800      raise ValueError(
1801          'TF symbol `tf.%s` could not be found.' % symbol_name)
1802
1803    config['cls_ref'] = cls_ref
1804
1805    return cls(**config)
1806
1807
1808class TFClassMethodDispatcher(dispatch.OpDispatcher):
1809  """A class method dispatcher that allows building a functional model with TF class methods."""
1810
1811  def __init__(self, cls, method_name):
1812    self.cls = cls
1813    self.method_name = method_name
1814
1815  def handle(self, args, kwargs):
1816    """Handle the specified operation with the specified arguments."""
1817    if any(
1818        isinstance(x, keras_tensor.KerasTensor)
1819        for x in nest.flatten([args, kwargs])):
1820      return ClassMethod(self.cls, self.method_name)(args[1:], kwargs)
1821    else:
1822      return self.NOT_SUPPORTED
1823
1824for ragged_class_method in [
1825    'from_value_rowids',
1826    'from_row_splits',
1827    'from_row_lengths',
1828    'from_row_starts',
1829    'from_row_limits',
1830    'from_uniform_row_length',
1831    'from_nested_value_rowids',
1832    'from_nested_row_splits',
1833    'from_nested_row_lengths',
1834    'from_tensor',
1835    'from_sparse',
1836]:
1837  TFClassMethodDispatcher(
1838      ragged_tensor.RaggedTensor, ragged_class_method).register(
1839          getattr(ragged_tensor.RaggedTensor, ragged_class_method))
1840