Add keras types package and base Layer.
base_layer.Layer and frozen_copy will be updated to use types.Layer as base class. All the isinstance() check will be updated as well. PiperOrigin-RevId: 300435612 Change-Id: I9416984eb775939962a6071a2484986dcaeb3854
This commit is contained in:
parent
00fbbd9036
commit
73c6de788c
14
tensorflow/python/keras/type/BUILD
Normal file
14
tensorflow/python/keras/type/BUILD
Normal file
@ -0,0 +1,14 @@
|
||||
load("//tensorflow:tensorflow.bzl", "py_strict_library")
|
||||
|
||||
package(
|
||||
default_visibility = ["//tensorflow:__subpackages__"],
|
||||
licenses = ["notice"], # Apache 2.0
|
||||
)
|
||||
|
||||
py_strict_library(
|
||||
name = "types",
|
||||
srcs = ["types.py"],
|
||||
deps = [
|
||||
"@six_archive//:six",
|
||||
],
|
||||
)
|
203
tensorflow/python/keras/type/types.py
Normal file
203
tensorflow/python/keras/type/types.py
Normal file
@ -0,0 +1,203 @@
|
||||
# Copyright 2020 The TensorFlow Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
# pylint: disable=g-classes-have-attributes
|
||||
"""Python module for Keras base types.
|
||||
|
||||
All the classes in this module is abstract classes that contains none or minimal
|
||||
implementations. It is designed be used as base class for other concrete
|
||||
classes, type checks, and python3 type hints.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import abc
|
||||
import six
|
||||
|
||||
# TODO(scottzhu): Export all the types under this module with API symbol.
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class Layer(object):
|
||||
"""This is the class from which all layers inherit.
|
||||
|
||||
A layer is a callable object that takes as input one or more tensors and
|
||||
that outputs one or more tensors. It involves *computation*, defined
|
||||
in the `call()` method, and a *state* (weight variables), defined
|
||||
either in the constructor `__init__()` or in the `build()` method.
|
||||
|
||||
Users will just instantiate a layer and then treat it as a callable.
|
||||
|
||||
We recommend that descendants of `Layer` implement the following methods:
|
||||
|
||||
* `__init__()`: Defines custom layer attributes, and creates layer state
|
||||
variables that do not depend on input shapes, using `add_weight()`.
|
||||
* `build(self, input_shape)`: This method can be used to create weights that
|
||||
depend on the shape(s) of the input(s), using `add_weight()`. `__call__()`
|
||||
will automatically build the layer (if it has not been built yet) by
|
||||
calling `build()`.
|
||||
* `call(self, *args, **kwargs)`: Called in `__call__` after making sure
|
||||
`build()` has been called. `call()` performs the logic of applying the
|
||||
layer to the input tensors (which should be passed in as argument).
|
||||
Two reserved keyword arguments you can optionally use in `call()` are:
|
||||
- `training` (boolean, whether the call is in
|
||||
inference mode or training mode)
|
||||
- `mask` (boolean tensor encoding masked timesteps in the input, used
|
||||
in RNN layers)
|
||||
* `get_config(self)`: Returns a dictionary containing the configuration used
|
||||
to initialize this layer. If the keys differ from the arguments
|
||||
in `__init__`, then override `from_config(self)` as well.
|
||||
This method is used when saving
|
||||
the layer or a model that contains this layer.
|
||||
|
||||
Examples:
|
||||
|
||||
Here's a basic example: a layer with two variables, `w` and `b`,
|
||||
that returns `y = w . x + b`.
|
||||
It shows how to implement `build()` and `call()`.
|
||||
Variables set as attributes of a layer are tracked as weights
|
||||
of the layers (in `layer.weights`).
|
||||
|
||||
```python
|
||||
class SimpleDense(Layer):
|
||||
|
||||
def __init__(self, units=32):
|
||||
super(SimpleDense, self).__init__()
|
||||
self.units = units
|
||||
|
||||
def build(self, input_shape): # Create the state of the layer (weights)
|
||||
w_init = tf.random_normal_initializer()
|
||||
self.w = tf.Variable(
|
||||
initial_value=w_init(shape=(input_shape[-1], self.units),
|
||||
dtype='float32'),
|
||||
trainable=True)
|
||||
b_init = tf.zeros_initializer()
|
||||
self.b = tf.Variable(
|
||||
initial_value=b_init(shape=(self.units,), dtype='float32'),
|
||||
trainable=True)
|
||||
|
||||
def call(self, inputs): # Defines the computation from inputs to outputs
|
||||
return tf.matmul(inputs, self.w) + self.b
|
||||
|
||||
# Instantiates the layer.
|
||||
linear_layer = SimpleDense(4)
|
||||
|
||||
# This will also call `build(input_shape)` and create the weights.
|
||||
y = linear_layer(tf.ones((2, 2)))
|
||||
assert len(linear_layer.weights) == 2
|
||||
|
||||
# These weights are trainable, so they're listed in `trainable_weights`:
|
||||
assert len(linear_layer.trainable_weights) == 2
|
||||
```
|
||||
|
||||
Note that the method `add_weight()` offers a shortcut to create weights:
|
||||
|
||||
```python
|
||||
class SimpleDense(Layer):
|
||||
|
||||
def __init__(self, units=32):
|
||||
super(SimpleDense, self).__init__()
|
||||
self.units = units
|
||||
|
||||
def build(self, input_shape):
|
||||
self.w = self.add_weight(shape=(input_shape[-1], self.units),
|
||||
initializer='random_normal',
|
||||
trainable=True)
|
||||
self.b = self.add_weight(shape=(self.units,),
|
||||
initializer='random_normal',
|
||||
trainable=True)
|
||||
|
||||
def call(self, inputs):
|
||||
return tf.matmul(inputs, self.w) + self.b
|
||||
```
|
||||
|
||||
Besides trainable weights, updated via backpropagation during training,
|
||||
layers can also have non-trainable weights. These weights are meant to
|
||||
be updated manually during `call()`. Here's a example layer that computes
|
||||
the running sum of its inputs:
|
||||
|
||||
```python
|
||||
class ComputeSum(Layer):
|
||||
|
||||
def __init__(self, input_dim):
|
||||
super(ComputeSum, self).__init__()
|
||||
# Create a non-trainable weight.
|
||||
self.total = tf.Variable(initial_value=tf.zeros((input_dim,)),
|
||||
trainable=False)
|
||||
|
||||
def call(self, inputs):
|
||||
self.total.assign_add(tf.reduce_sum(inputs, axis=0))
|
||||
return self.total
|
||||
|
||||
my_sum = ComputeSum(2)
|
||||
x = tf.ones((2, 2))
|
||||
|
||||
y = my_sum(x)
|
||||
print(y.numpy()) # [2. 2.]
|
||||
|
||||
y = my_sum(x)
|
||||
print(y.numpy()) # [4. 4.]
|
||||
|
||||
assert my_sum.weights == [my_sum.total]
|
||||
assert my_sum.non_trainable_weights == [my_sum.total]
|
||||
assert my_sum.trainable_weights == []
|
||||
```
|
||||
|
||||
For more information about creating layers, see the guide
|
||||
[Writing custom layers and models with Keras](
|
||||
https://www.tensorflow.org/guide/keras/custom_layers_and_models)
|
||||
|
||||
Arguments:
|
||||
trainable: Boolean, whether the layer's variables should be trainable.
|
||||
name: String name of the layer.
|
||||
dtype: The dtype of the layer's computations and weights (default of
|
||||
`None` means use `tf.keras.backend.floatx` in TensorFlow 2, or the type
|
||||
of the first input in TensorFlow 1).
|
||||
dynamic: Set this to `True` if your layer should only be run eagerly, and
|
||||
should not be used to generate a static computation graph.
|
||||
This would be the case for a Tree-RNN or a recursive network,
|
||||
for example, or generally for any layer that manipulates tensors
|
||||
using Python control flow. If `False`, we assume that the layer can
|
||||
safely be used to generate a static computation graph.
|
||||
|
||||
Attributes:
|
||||
name: The name of the layer (string).
|
||||
dtype: The dtype of the layer's computations and weights. If mixed
|
||||
precision is used with a `tf.keras.mixed_precision.experimental.Policy`,
|
||||
this is instead just the dtype of the layer's weights, as the computations
|
||||
are done in a different dtype.
|
||||
updates: List of update ops of this layer.
|
||||
losses: List of losses added by this layer.
|
||||
trainable_weights: List of variables to be included in backprop.
|
||||
non_trainable_weights: List of variables that should not be
|
||||
included in backprop.
|
||||
weights: The concatenation of the lists trainable_weights and
|
||||
non_trainable_weights (in this order).
|
||||
trainable: Whether the layer should be trained (boolean).
|
||||
input_spec: Optional (list of) `InputSpec` object(s) specifying the
|
||||
constraints on inputs that can be accepted by the layer.
|
||||
|
||||
Each layer has a dtype, which is typically the dtype of the layer's
|
||||
computations and variables. A layer's dtype can be queried via the
|
||||
`Layer.dtype` property. The dtype is specified with the `dtype` constructor
|
||||
argument. In TensorFlow 2, the dtype defaults to `tf.keras.backend.floatx()`
|
||||
if no dtype is passed. `floatx()` itself defaults to "float32". Additionally,
|
||||
layers will cast their inputs to the layer's dtype in TensorFlow 2. When mixed
|
||||
precision is used, layers may have different computation and variable dtypes.
|
||||
See `tf.keras.mixed_precision.experimental.Policy` for details on layer
|
||||
dtypes.
|
||||
"""
|
||||
pass
|
Loading…
Reference in New Issue
Block a user