404 lines
15 KiB
Python
404 lines
15 KiB
Python
|
# Copyright 2015 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.
|
||
|
# ==============================================================================
|
||
|
"""Long Short-Term Memory V1 layer."""
|
||
|
|
||
|
|
||
|
from keras import activations
|
||
|
from keras import constraints
|
||
|
from keras import initializers
|
||
|
from keras import regularizers
|
||
|
from keras.engine.input_spec import InputSpec
|
||
|
from keras.layers.rnn import lstm
|
||
|
from keras.layers.rnn import rnn_utils
|
||
|
from keras.layers.rnn.base_rnn import RNN
|
||
|
|
||
|
# isort: off
|
||
|
from tensorflow.python.platform import tf_logging as logging
|
||
|
from tensorflow.python.util.tf_export import keras_export
|
||
|
|
||
|
|
||
|
@keras_export(v1=["keras.layers.LSTMCell"])
|
||
|
class LSTMCell(lstm.LSTMCell):
|
||
|
"""Cell class for the LSTM layer.
|
||
|
|
||
|
Args:
|
||
|
units: Positive integer, dimensionality of the output space.
|
||
|
activation: Activation function to use.
|
||
|
Default: hyperbolic tangent (`tanh`).
|
||
|
If you pass `None`, no activation is applied
|
||
|
(ie. "linear" activation: `a(x) = x`).
|
||
|
recurrent_activation: Activation function to use
|
||
|
for the recurrent step.
|
||
|
Default: hard sigmoid (`hard_sigmoid`).
|
||
|
If you pass `None`, no activation is applied
|
||
|
(ie. "linear" activation: `a(x) = x`).
|
||
|
use_bias: Boolean, whether the layer uses a bias vector.
|
||
|
kernel_initializer: Initializer for the `kernel` weights matrix,
|
||
|
used for the linear transformation of the inputs.
|
||
|
recurrent_initializer: Initializer for the `recurrent_kernel`
|
||
|
weights matrix,
|
||
|
used for the linear transformation of the recurrent state.
|
||
|
bias_initializer: Initializer for the bias vector.
|
||
|
unit_forget_bias: Boolean.
|
||
|
If True, add 1 to the bias of the forget gate at initialization.
|
||
|
Setting it to true will also force `bias_initializer="zeros"`.
|
||
|
This is recommended in [Jozefowicz et al., 2015](
|
||
|
http://www.jmlr.org/proceedings/papers/v37/jozefowicz15.pdf)
|
||
|
kernel_regularizer: Regularizer function applied to
|
||
|
the `kernel` weights matrix.
|
||
|
recurrent_regularizer: Regularizer function applied to
|
||
|
the `recurrent_kernel` weights matrix.
|
||
|
bias_regularizer: Regularizer function applied to the bias vector.
|
||
|
kernel_constraint: Constraint function applied to
|
||
|
the `kernel` weights matrix.
|
||
|
recurrent_constraint: Constraint function applied to
|
||
|
the `recurrent_kernel` weights matrix.
|
||
|
bias_constraint: Constraint function applied to the bias vector.
|
||
|
dropout: Float between 0 and 1.
|
||
|
Fraction of the units to drop for
|
||
|
the linear transformation of the inputs.
|
||
|
recurrent_dropout: Float between 0 and 1.
|
||
|
Fraction of the units to drop for
|
||
|
the linear transformation of the recurrent state.
|
||
|
|
||
|
Call arguments:
|
||
|
inputs: A 2D tensor.
|
||
|
states: List of state tensors corresponding to the previous timestep.
|
||
|
training: Python boolean indicating whether the layer should behave in
|
||
|
training mode or in inference mode. Only relevant when `dropout` or
|
||
|
`recurrent_dropout` is used.
|
||
|
"""
|
||
|
|
||
|
def __init__(
|
||
|
self,
|
||
|
units,
|
||
|
activation="tanh",
|
||
|
recurrent_activation="hard_sigmoid",
|
||
|
use_bias=True,
|
||
|
kernel_initializer="glorot_uniform",
|
||
|
recurrent_initializer="orthogonal",
|
||
|
bias_initializer="zeros",
|
||
|
unit_forget_bias=True,
|
||
|
kernel_regularizer=None,
|
||
|
recurrent_regularizer=None,
|
||
|
bias_regularizer=None,
|
||
|
kernel_constraint=None,
|
||
|
recurrent_constraint=None,
|
||
|
bias_constraint=None,
|
||
|
dropout=0.0,
|
||
|
recurrent_dropout=0.0,
|
||
|
**kwargs
|
||
|
):
|
||
|
super().__init__(
|
||
|
units,
|
||
|
activation=activation,
|
||
|
recurrent_activation=recurrent_activation,
|
||
|
use_bias=use_bias,
|
||
|
kernel_initializer=kernel_initializer,
|
||
|
recurrent_initializer=recurrent_initializer,
|
||
|
bias_initializer=bias_initializer,
|
||
|
unit_forget_bias=unit_forget_bias,
|
||
|
kernel_regularizer=kernel_regularizer,
|
||
|
recurrent_regularizer=recurrent_regularizer,
|
||
|
bias_regularizer=bias_regularizer,
|
||
|
kernel_constraint=kernel_constraint,
|
||
|
recurrent_constraint=recurrent_constraint,
|
||
|
bias_constraint=bias_constraint,
|
||
|
dropout=dropout,
|
||
|
recurrent_dropout=recurrent_dropout,
|
||
|
implementation=kwargs.pop("implementation", 1),
|
||
|
**kwargs
|
||
|
)
|
||
|
|
||
|
|
||
|
@keras_export(v1=["keras.layers.LSTM"])
|
||
|
class LSTM(RNN):
|
||
|
"""Long Short-Term Memory layer - Hochreiter 1997.
|
||
|
|
||
|
Note that this cell is not optimized for performance on GPU. Please use
|
||
|
`tf.compat.v1.keras.layers.CuDNNLSTM` for better performance on GPU.
|
||
|
|
||
|
Args:
|
||
|
units: Positive integer, dimensionality of the output space.
|
||
|
activation: Activation function to use.
|
||
|
Default: hyperbolic tangent (`tanh`).
|
||
|
If you pass `None`, no activation is applied
|
||
|
(ie. "linear" activation: `a(x) = x`).
|
||
|
recurrent_activation: Activation function to use
|
||
|
for the recurrent step.
|
||
|
Default: hard sigmoid (`hard_sigmoid`).
|
||
|
If you pass `None`, no activation is applied
|
||
|
(ie. "linear" activation: `a(x) = x`).
|
||
|
use_bias: Boolean, whether the layer uses a bias vector.
|
||
|
kernel_initializer: Initializer for the `kernel` weights matrix,
|
||
|
used for the linear transformation of the inputs..
|
||
|
recurrent_initializer: Initializer for the `recurrent_kernel`
|
||
|
weights matrix,
|
||
|
used for the linear transformation of the recurrent state.
|
||
|
bias_initializer: Initializer for the bias vector.
|
||
|
unit_forget_bias: Boolean.
|
||
|
If True, add 1 to the bias of the forget gate at initialization.
|
||
|
Setting it to true will also force `bias_initializer="zeros"`.
|
||
|
This is recommended in [Jozefowicz et al., 2015](
|
||
|
http://www.jmlr.org/proceedings/papers/v37/jozefowicz15.pdf).
|
||
|
kernel_regularizer: Regularizer function applied to
|
||
|
the `kernel` weights matrix.
|
||
|
recurrent_regularizer: Regularizer function applied to
|
||
|
the `recurrent_kernel` weights matrix.
|
||
|
bias_regularizer: Regularizer function applied to the bias vector.
|
||
|
activity_regularizer: Regularizer function applied to
|
||
|
the output of the layer (its "activation").
|
||
|
kernel_constraint: Constraint function applied to
|
||
|
the `kernel` weights matrix.
|
||
|
recurrent_constraint: Constraint function applied to
|
||
|
the `recurrent_kernel` weights matrix.
|
||
|
bias_constraint: Constraint function applied to the bias vector.
|
||
|
dropout: Float between 0 and 1.
|
||
|
Fraction of the units to drop for
|
||
|
the linear transformation of the inputs.
|
||
|
recurrent_dropout: Float between 0 and 1.
|
||
|
Fraction of the units to drop for
|
||
|
the linear transformation of the recurrent state.
|
||
|
return_sequences: Boolean. Whether to return the last output
|
||
|
in the output sequence, or the full sequence.
|
||
|
return_state: Boolean. Whether to return the last state
|
||
|
in addition to the output.
|
||
|
go_backwards: Boolean (default False).
|
||
|
If True, process the input sequence backwards and return the
|
||
|
reversed sequence.
|
||
|
stateful: Boolean (default False). If True, the last state
|
||
|
for each sample at index i in a batch will be used as initial
|
||
|
state for the sample of index i in the following batch.
|
||
|
unroll: Boolean (default False).
|
||
|
If True, the network will be unrolled,
|
||
|
else a symbolic loop will be used.
|
||
|
Unrolling can speed-up a RNN,
|
||
|
although it tends to be more memory-intensive.
|
||
|
Unrolling is only suitable for short sequences.
|
||
|
time_major: The shape format of the `inputs` and `outputs` tensors.
|
||
|
If True, the inputs and outputs will be in shape
|
||
|
`(timesteps, batch, ...)`, whereas in the False case, it will be
|
||
|
`(batch, timesteps, ...)`. Using `time_major = True` is a bit more
|
||
|
efficient because it avoids transposes at the beginning and end of the
|
||
|
RNN calculation. However, most TensorFlow data is batch-major, so by
|
||
|
default this function accepts input and emits output in batch-major
|
||
|
form.
|
||
|
|
||
|
Call arguments:
|
||
|
inputs: A 3D tensor.
|
||
|
mask: Binary tensor of shape `(samples, timesteps)` indicating whether
|
||
|
a given timestep should be masked. An individual `True` entry indicates
|
||
|
that the corresponding timestep should be utilized, while a `False`
|
||
|
entry indicates that the corresponding timestep should be ignored.
|
||
|
training: Python boolean indicating whether the layer should behave in
|
||
|
training mode or in inference mode. This argument is passed to the cell
|
||
|
when calling it. This is only relevant if `dropout` or
|
||
|
`recurrent_dropout` is used.
|
||
|
initial_state: List of initial state tensors to be passed to the first
|
||
|
call of the cell.
|
||
|
"""
|
||
|
|
||
|
def __init__(
|
||
|
self,
|
||
|
units,
|
||
|
activation="tanh",
|
||
|
recurrent_activation="hard_sigmoid",
|
||
|
use_bias=True,
|
||
|
kernel_initializer="glorot_uniform",
|
||
|
recurrent_initializer="orthogonal",
|
||
|
bias_initializer="zeros",
|
||
|
unit_forget_bias=True,
|
||
|
kernel_regularizer=None,
|
||
|
recurrent_regularizer=None,
|
||
|
bias_regularizer=None,
|
||
|
activity_regularizer=None,
|
||
|
kernel_constraint=None,
|
||
|
recurrent_constraint=None,
|
||
|
bias_constraint=None,
|
||
|
dropout=0.0,
|
||
|
recurrent_dropout=0.0,
|
||
|
return_sequences=False,
|
||
|
return_state=False,
|
||
|
go_backwards=False,
|
||
|
stateful=False,
|
||
|
unroll=False,
|
||
|
**kwargs
|
||
|
):
|
||
|
implementation = kwargs.pop("implementation", 1)
|
||
|
if implementation == 0:
|
||
|
logging.warning(
|
||
|
"`implementation=0` has been deprecated, "
|
||
|
"and now defaults to `implementation=1`."
|
||
|
"Please update your layer call."
|
||
|
)
|
||
|
if "enable_caching_device" in kwargs:
|
||
|
cell_kwargs = {
|
||
|
"enable_caching_device": kwargs.pop("enable_caching_device")
|
||
|
}
|
||
|
else:
|
||
|
cell_kwargs = {}
|
||
|
cell = LSTMCell(
|
||
|
units,
|
||
|
activation=activation,
|
||
|
recurrent_activation=recurrent_activation,
|
||
|
use_bias=use_bias,
|
||
|
kernel_initializer=kernel_initializer,
|
||
|
recurrent_initializer=recurrent_initializer,
|
||
|
unit_forget_bias=unit_forget_bias,
|
||
|
bias_initializer=bias_initializer,
|
||
|
kernel_regularizer=kernel_regularizer,
|
||
|
recurrent_regularizer=recurrent_regularizer,
|
||
|
bias_regularizer=bias_regularizer,
|
||
|
kernel_constraint=kernel_constraint,
|
||
|
recurrent_constraint=recurrent_constraint,
|
||
|
bias_constraint=bias_constraint,
|
||
|
dropout=dropout,
|
||
|
recurrent_dropout=recurrent_dropout,
|
||
|
implementation=implementation,
|
||
|
dtype=kwargs.get("dtype"),
|
||
|
trainable=kwargs.get("trainable", True),
|
||
|
**cell_kwargs
|
||
|
)
|
||
|
super().__init__(
|
||
|
cell,
|
||
|
return_sequences=return_sequences,
|
||
|
return_state=return_state,
|
||
|
go_backwards=go_backwards,
|
||
|
stateful=stateful,
|
||
|
unroll=unroll,
|
||
|
**kwargs
|
||
|
)
|
||
|
self.activity_regularizer = regularizers.get(activity_regularizer)
|
||
|
self.input_spec = [InputSpec(ndim=3)]
|
||
|
|
||
|
def call(self, inputs, mask=None, training=None, initial_state=None):
|
||
|
return super().call(
|
||
|
inputs, mask=mask, training=training, initial_state=initial_state
|
||
|
)
|
||
|
|
||
|
@property
|
||
|
def units(self):
|
||
|
return self.cell.units
|
||
|
|
||
|
@property
|
||
|
def activation(self):
|
||
|
return self.cell.activation
|
||
|
|
||
|
@property
|
||
|
def recurrent_activation(self):
|
||
|
return self.cell.recurrent_activation
|
||
|
|
||
|
@property
|
||
|
def use_bias(self):
|
||
|
return self.cell.use_bias
|
||
|
|
||
|
@property
|
||
|
def kernel_initializer(self):
|
||
|
return self.cell.kernel_initializer
|
||
|
|
||
|
@property
|
||
|
def recurrent_initializer(self):
|
||
|
return self.cell.recurrent_initializer
|
||
|
|
||
|
@property
|
||
|
def bias_initializer(self):
|
||
|
return self.cell.bias_initializer
|
||
|
|
||
|
@property
|
||
|
def unit_forget_bias(self):
|
||
|
return self.cell.unit_forget_bias
|
||
|
|
||
|
@property
|
||
|
def kernel_regularizer(self):
|
||
|
return self.cell.kernel_regularizer
|
||
|
|
||
|
@property
|
||
|
def recurrent_regularizer(self):
|
||
|
return self.cell.recurrent_regularizer
|
||
|
|
||
|
@property
|
||
|
def bias_regularizer(self):
|
||
|
return self.cell.bias_regularizer
|
||
|
|
||
|
@property
|
||
|
def kernel_constraint(self):
|
||
|
return self.cell.kernel_constraint
|
||
|
|
||
|
@property
|
||
|
def recurrent_constraint(self):
|
||
|
return self.cell.recurrent_constraint
|
||
|
|
||
|
@property
|
||
|
def bias_constraint(self):
|
||
|
return self.cell.bias_constraint
|
||
|
|
||
|
@property
|
||
|
def dropout(self):
|
||
|
return self.cell.dropout
|
||
|
|
||
|
@property
|
||
|
def recurrent_dropout(self):
|
||
|
return self.cell.recurrent_dropout
|
||
|
|
||
|
@property
|
||
|
def implementation(self):
|
||
|
return self.cell.implementation
|
||
|
|
||
|
def get_config(self):
|
||
|
config = {
|
||
|
"units": self.units,
|
||
|
"activation": activations.serialize(self.activation),
|
||
|
"recurrent_activation": activations.serialize(
|
||
|
self.recurrent_activation
|
||
|
),
|
||
|
"use_bias": self.use_bias,
|
||
|
"kernel_initializer": initializers.serialize(
|
||
|
self.kernel_initializer
|
||
|
),
|
||
|
"recurrent_initializer": initializers.serialize(
|
||
|
self.recurrent_initializer
|
||
|
),
|
||
|
"bias_initializer": initializers.serialize(self.bias_initializer),
|
||
|
"unit_forget_bias": self.unit_forget_bias,
|
||
|
"kernel_regularizer": regularizers.serialize(
|
||
|
self.kernel_regularizer
|
||
|
),
|
||
|
"recurrent_regularizer": regularizers.serialize(
|
||
|
self.recurrent_regularizer
|
||
|
),
|
||
|
"bias_regularizer": regularizers.serialize(self.bias_regularizer),
|
||
|
"activity_regularizer": regularizers.serialize(
|
||
|
self.activity_regularizer
|
||
|
),
|
||
|
"kernel_constraint": constraints.serialize(self.kernel_constraint),
|
||
|
"recurrent_constraint": constraints.serialize(
|
||
|
self.recurrent_constraint
|
||
|
),
|
||
|
"bias_constraint": constraints.serialize(self.bias_constraint),
|
||
|
"dropout": self.dropout,
|
||
|
"recurrent_dropout": self.recurrent_dropout,
|
||
|
"implementation": self.implementation,
|
||
|
}
|
||
|
config.update(rnn_utils.config_for_enable_caching_device(self.cell))
|
||
|
base_config = super().get_config()
|
||
|
del base_config["cell"]
|
||
|
return dict(list(base_config.items()) + list(config.items()))
|
||
|
|
||
|
@classmethod
|
||
|
def from_config(cls, config):
|
||
|
if "implementation" in config and config["implementation"] == 0:
|
||
|
config["implementation"] = 1
|
||
|
return cls(**config)
|