cell class for the convlstm layer args rank integer rank of the convolution e g 2 for 2d convolutions filters integer the dimensionality of the output space i e the number of output filters in the convolution kernelsize an integer or tuplelist of n integers specifying the dimensions of the convolution window strides an integer or tuplelist of n integers specifying the strides of the convolution specifying any stride value 1 is incompatible with specifying any dilationrate value 1 padding one of valid or same caseinsensitive valid means no padding same results in padding evenly to the leftright or updown of the input such that output has the same heightwidth dimension as the input dataformat a string one of channelslast default or channelsfirst when unspecified uses imagedataformat value found in your keras config file at keraskeras json if exists else channelslast defaults to channelslast dilationrate an integer or tuplelist of n integers specifying the dilation rate to use for dilated convolution currently specifying any dilationrate value 1 is incompatible with specifying any strides value 1 activation activation function if none no activation is applied recurrentactivation activation function to use for the recurrent step usebias boolean default true whether the layer should use a bias vector kernelinitializer initializer for the kernel weights matrix used for the linear transformation of the inputs default glorotuniform recurrentinitializer initializer for the recurrentkernel weights matrix used for the linear transformation of the recurrent state default orthogonal biasinitializer initializer for the bias vector default zeros unitforgetbias boolean default true if true add 1 to the bias of the forget gate at initialization setting it to true will also force biasinitializerzeros this is recommended in jozefowicz et al https github commlresearchv37blobghpagesjozefowicz15 pdf kernelregularizer regularizer function applied to the kernel weights matrix default none recurrentregularizer regularizer function applied to the recurrentkernel weights matrix default none biasregularizer regularizer function applied to the bias vector default none activityregularizer regularizer function applied to the output of the layer its activation default none kernelconstraint constraint function applied to the kernel weights matrix default none recurrentconstraint constraint function applied to the recurrentkernel weights matrix default none biasconstraint constraint function applied to the bias vector default none dropout float between 0 and 1 fraction of the units to drop for the linear transformation of the inputs default 0 recurrentdropout float between 0 and 1 fraction of the units to drop for the linear transformation of the recurrent state default 0 seed random seed for dropout call arguments inputs a 2 rankd 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 recurrentdropout is used dpmask self getdropoutmaskinputs recdpmask self getrecurrentdropoutmaskhtm1 if training and 0 0 self dropout 1 0 inputs dpmask if training and 0 0 self recurrentdropout 1 0 htm1 recdpmask abstract nd convolutional lstm layer used as implementation base similar to an lstm layer but the input transformations and recurrent transformations are both convolutional args rank integer rank of the convolution e g 2 for 2d convolutions filters integer the dimensionality of the output space i e the number of output filters in the convolution kernelsize an integer or tuplelist of n integers specifying the dimensions of the convolution window strides an integer or tuplelist of n integers specifying the strides of the convolution specifying any stride value 1 is incompatible with specifying any dilationrate value 1 padding one of valid or same caseinsensitive valid means no padding same results in padding evenly to the leftright or updown of the input such that output has the same heightwidth dimension as the input dataformat a string one of channelslast default or channelsfirst the ordering of the dimensions in the inputs channelslast corresponds to inputs with shape batch time channels while channelsfirst corresponds to inputs with shape batch time channels when unspecified uses imagedataformat value found in your keras config file at keraskeras json if exists else channelslast defaults to channelslast dilationrate an integer or tuplelist of n integers specifying the dilation rate to use for dilated convolution currently specifying any dilationrate value 1 is incompatible with specifying any strides value 1 activation activation function to use by default hyperbolic tangent activation function is applied tanhx recurrentactivation activation function to use for the recurrent step usebias boolean whether the layer uses a bias vector kernelinitializer initializer for the kernel weights matrix used for the linear transformation of the inputs recurrentinitializer initializer for the recurrentkernel weights matrix used for the linear transformation of the recurrent state biasinitializer initializer for the bias vector unitforgetbias boolean if true add 1 to the bias of the forget gate at initialization use in combination with biasinitializerzeros this is recommended in jozefowicz et al 2015 http www jmlr orgproceedingspapersv37jozefowicz15 pdf kernelregularizer regularizer function applied to the kernel weights matrix recurrentregularizer regularizer function applied to the recurrentkernel weights matrix biasregularizer regularizer function applied to the bias vector activityregularizer regularizer function applied to kernelconstraint constraint function applied to the kernel weights matrix recurrentconstraint constraint function applied to the recurrentkernel weights matrix biasconstraint 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 recurrentdropout float between 0 and 1 fraction of the units to drop for the linear transformation of the recurrent state seed random seed for dropout returnsequences boolean whether to return the last output in the output sequence or the full sequence default false returnstate boolean whether to return the last state in addition to the output default false gobackwards boolean default false if true process the input sequence backwards 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 cell class for the convlstm layer args rank integer rank of the convolution e g 2 for 2d convolutions filters integer the dimensionality of the output space i e the number of output filters in the convolution kernel_size an integer or tuple list of n integers specifying the dimensions of the convolution window strides an integer or tuple list of n integers specifying the strides of the convolution specifying any stride value 1 is incompatible with specifying any dilation_rate value 1 padding one of valid or same case insensitive valid means no padding same results in padding evenly to the left right or up down of the input such that output has the same height width dimension as the input data_format a string one of channels_last default or channels_first when unspecified uses image_data_format value found in your keras config file at keras keras json if exists else channels_last defaults to channels_last dilation_rate an integer or tuple list of n integers specifying the dilation rate to use for dilated convolution currently specifying any dilation_rate value 1 is incompatible with specifying any strides value 1 activation activation function if none no activation is applied recurrent_activation activation function to use for the recurrent step use_bias boolean default true whether the layer should use a bias vector kernel_initializer initializer for the kernel weights matrix used for the linear transformation of the inputs default glorot_uniform recurrent_initializer initializer for the recurrent_kernel weights matrix used for the linear transformation of the recurrent state default orthogonal bias_initializer initializer for the bias vector default zeros unit_forget_bias boolean default true 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 https github com mlresearch v37 blob gh pages jozefowicz15 pdf kernel_regularizer regularizer function applied to the kernel weights matrix default none recurrent_regularizer regularizer function applied to the recurrent_kernel weights matrix default none bias_regularizer regularizer function applied to the bias vector default none activity_regularizer regularizer function applied to the output of the layer its activation default none kernel_constraint constraint function applied to the kernel weights matrix default none recurrent_constraint constraint function applied to the recurrent_kernel weights matrix default none bias_constraint constraint function applied to the bias vector default none dropout float between 0 and 1 fraction of the units to drop for the linear transformation of the inputs default 0 recurrent_dropout float between 0 and 1 fraction of the units to drop for the linear transformation of the recurrent state default 0 seed random seed for dropout call arguments inputs a 2 rank d 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 custom defined in methods previous memory state previous carry state dp_mask self get_dropout_mask inputs rec_dp_mask self get_recurrent_dropout_mask h_tm1 if training and 0 0 self dropout 1 0 inputs dp_mask if training and 0 0 self recurrent_dropout 1 0 h_tm1 rec_dp_mask abstract n d convolutional lstm layer used as implementation base similar to an lstm layer but the input transformations and recurrent transformations are both convolutional args rank integer rank of the convolution e g 2 for 2d convolutions filters integer the dimensionality of the output space i e the number of output filters in the convolution kernel_size an integer or tuple list of n integers specifying the dimensions of the convolution window strides an integer or tuple list of n integers specifying the strides of the convolution specifying any stride value 1 is incompatible with specifying any dilation_rate value 1 padding one of valid or same case insensitive valid means no padding same results in padding evenly to the left right or up down of the input such that output has the same height width dimension as the input data_format a string one of channels_last default or channels_first the ordering of the dimensions in the inputs channels_last corresponds to inputs with shape batch time channels while channels_first corresponds to inputs with shape batch time channels when unspecified uses image_data_format value found in your keras config file at keras keras json if exists else channels_last defaults to channels_last dilation_rate an integer or tuple list of n integers specifying the dilation rate to use for dilated convolution currently specifying any dilation_rate value 1 is incompatible with specifying any strides value 1 activation activation function to use by default hyperbolic tangent activation function is applied tanh x recurrent_activation activation function to use for the recurrent step 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 use in combination with 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 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 seed random seed for dropout return_sequences boolean whether to return the last output in the output sequence or the full sequence default false return_state boolean whether to return the last state in addition to the output default false go_backwards boolean default false if true process the input sequence backwards 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
import tree

from keras import activations
from keras import backend
from keras import constraints
from keras import initializers
from keras import ops
from keras import regularizers
from keras.layers.input_spec import InputSpec
from keras.layers.layer import Layer
from keras.layers.rnn.dropout_rnn_cell import DropoutRNNCell
from keras.layers.rnn.rnn import RNN
from keras.ops import operation_utils
from keras.utils import argument_validation


class ConvLSTMCell(Layer, DropoutRNNCell):
    

    def __init__(
        self,
        rank,
        filters,
        kernel_size,
        strides=1,
        padding="valid",
        data_format=None,
        dilation_rate=1,
        activation="tanh",
        recurrent_activation="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,
        seed=None,
        **kwargs,
    ):
        super().__init__(**kwargs)
        self.seed = seed
        self.seed_generator = backend.random.SeedGenerator(seed=seed)
        self.rank = rank
        if self.rank > 3:
            raise ValueError(
                f"Rank {rank} convolutions are not currently "
                f"implemented. Received: rank={rank}"
            )
        self.filters = filters
        self.kernel_size = argument_validation.standardize_tuple(
            kernel_size, self.rank, "kernel_size"
        )
        self.strides = argument_validation.standardize_tuple(
            strides, self.rank, "strides", allow_zero=True
        )
        self.padding = argument_validation.standardize_padding(padding)
        self.data_format = backend.standardize_data_format(data_format)
        self.dilation_rate = argument_validation.standardize_tuple(
            dilation_rate, self.rank, "dilation_rate"
        )
        self.activation = activations.get(activation)
        self.recurrent_activation = activations.get(recurrent_activation)
        self.use_bias = use_bias

        self.kernel_initializer = initializers.get(kernel_initializer)
        self.recurrent_initializer = initializers.get(recurrent_initializer)
        self.bias_initializer = initializers.get(bias_initializer)
        self.unit_forget_bias = unit_forget_bias

        self.kernel_regularizer = regularizers.get(kernel_regularizer)
        self.recurrent_regularizer = regularizers.get(recurrent_regularizer)
        self.bias_regularizer = regularizers.get(bias_regularizer)

        self.kernel_constraint = constraints.get(kernel_constraint)
        self.recurrent_constraint = constraints.get(recurrent_constraint)
        self.bias_constraint = constraints.get(bias_constraint)

        self.dropout = min(1.0, max(0.0, dropout))
        self.recurrent_dropout = min(1.0, max(0.0, recurrent_dropout))
        self.input_spec = InputSpec(ndim=rank + 2)
        self.state_size = -1  

    def build(self, inputs_shape, states_shape=None):
        if self.data_format == "channels_first":
            channel_axis = 1
            self.spatial_dims = inputs_shape[2:]
        else:
            channel_axis = -1
            self.spatial_dims = inputs_shape[1:-1]
        if None in self.spatial_dims:
            raise ValueError(
                "ConvLSTM layers only support static "
                "input shapes for the spatial dimension. "
                f"Received invalid input shape: input_shape={inputs_shape}"
            )
        if inputs_shape[channel_axis] is None:
            raise ValueError(
                "The channel dimension of the inputs (last axis) should be "
                "defined. Found None. Full input shape received: "
                f"input_shape={inputs_shape}"
            )
        self.input_spec = InputSpec(
            ndim=self.rank + 3, shape=(None,) + inputs_shape[1:]
        )

        input_dim = inputs_shape[channel_axis]
        self.input_dim = input_dim
        self.kernel_shape = self.kernel_size + (input_dim, self.filters * 4)
        recurrent_kernel_shape = self.kernel_size + (
            self.filters,
            self.filters * 4,
        )

        self.kernel = self.add_weight(
            shape=self.kernel_shape,
            initializer=self.kernel_initializer,
            name="kernel",
            regularizer=self.kernel_regularizer,
            constraint=self.kernel_constraint,
        )
        self.recurrent_kernel = self.add_weight(
            shape=recurrent_kernel_shape,
            initializer=self.recurrent_initializer,
            name="recurrent_kernel",
            regularizer=self.recurrent_regularizer,
            constraint=self.recurrent_constraint,
        )

        if self.use_bias:
            if self.unit_forget_bias:

                def bias_initializer(_, *args, **kwargs):
                    return ops.concatenate(
                        [
                            self.bias_initializer(
                                (self.filters,), *args, **kwargs
                            ),
                            initializers.get("ones")(
                                (self.filters,), *args, **kwargs
                            ),
                            self.bias_initializer(
                                (self.filters * 2,), *args, **kwargs
                            ),
                        ]
                    )

            else:
                bias_initializer = self.bias_initializer
            self.bias = self.add_weight(
                shape=(self.filters * 4,),
                name="bias",
                initializer=bias_initializer,
                regularizer=self.bias_regularizer,
                constraint=self.bias_constraint,
            )
        else:
            self.bias = None
        self.built = True

    def call(self, inputs, states, training=False):
        h_tm1 = states[0]  
        c_tm1 = states[1]  

        
        

        
        
        
        

        inputs_i = inputs
        inputs_f = inputs
        inputs_c = inputs
        inputs_o = inputs

        h_tm1_i = h_tm1
        h_tm1_f = h_tm1
        h_tm1_c = h_tm1
        h_tm1_o = h_tm1

        (kernel_i, kernel_f, kernel_c, kernel_o) = ops.split(
            self.kernel, 4, axis=self.rank + 1
        )
        (
            recurrent_kernel_i,
            recurrent_kernel_f,
            recurrent_kernel_c,
            recurrent_kernel_o,
        ) = ops.split(self.recurrent_kernel, 4, axis=self.rank + 1)

        if self.use_bias:
            bias_i, bias_f, bias_c, bias_o = ops.split(self.bias, 4)
        else:
            bias_i, bias_f, bias_c, bias_o = None, None, None, None

        x_i = self.input_conv(inputs_i, kernel_i, bias_i, padding=self.padding)
        x_f = self.input_conv(inputs_f, kernel_f, bias_f, padding=self.padding)
        x_c = self.input_conv(inputs_c, kernel_c, bias_c, padding=self.padding)
        x_o = self.input_conv(inputs_o, kernel_o, bias_o, padding=self.padding)

        h_i = self.recurrent_conv(h_tm1_i, recurrent_kernel_i)
        h_f = self.recurrent_conv(h_tm1_f, recurrent_kernel_f)
        h_c = self.recurrent_conv(h_tm1_c, recurrent_kernel_c)
        h_o = self.recurrent_conv(h_tm1_o, recurrent_kernel_o)

        i = self.recurrent_activation(x_i + h_i)
        f = self.recurrent_activation(x_f + h_f)
        c = f * c_tm1 + i * self.activation(x_c + h_c)
        o = self.recurrent_activation(x_o + h_o)
        h = o * self.activation(c)
        return h, [h, c]

    def compute_output_shape(self, inputs_shape, states_shape=None):
        conv_output_shape = operation_utils.compute_conv_output_shape(
            inputs_shape,
            self.filters,
            self.kernel_size,
            strides=self.strides,
            padding=self.padding,
            data_format=self.data_format,
            dilation_rate=self.dilation_rate,
        )
        return conv_output_shape, [conv_output_shape, conv_output_shape]

    def get_initial_state(self, batch_size=None):
        if self.data_format == "channels_last":
            input_shape = (batch_size,) + self.spatial_dims + (self.input_dim,)
        else:
            input_shape = (batch_size, self.input_dim) + self.spatial_dims
        state_shape = self.compute_output_shape(input_shape)[0]
        return [
            ops.zeros(state_shape, dtype=self.compute_dtype),
            ops.zeros(state_shape, dtype=self.compute_dtype),
        ]

    def input_conv(self, x, w, b=None, padding="valid"):
        conv_out = ops.conv(
            x,
            w,
            strides=self.strides,
            padding=padding,
            data_format=self.data_format,
            dilation_rate=self.dilation_rate,
        )
        if b is not None:
            if self.data_format == "channels_last":
                bias_shape = (1,) * (self.rank + 1) + (self.filters,)
            else:
                bias_shape = (1, self.filters) + (1,) * self.rank
            bias = ops.reshape(b, bias_shape)
            conv_out += bias
        return conv_out

    def recurrent_conv(self, x, w):
        strides = argument_validation.standardize_tuple(
            1, self.rank, "strides", allow_zero=True
        )
        conv_out = ops.conv(
            x, w, strides=strides, padding="same", data_format=self.data_format
        )
        return conv_out

    def get_config(self):
        config = {
            "filters": self.filters,
            "kernel_size": self.kernel_size,
            "strides": self.strides,
            "padding": self.padding,
            "data_format": self.data_format,
            "dilation_rate": self.dilation_rate,
            "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),
            "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,
            "seed": self.seed,
        }
        base_config = super().get_config()
        return {**base_config, **config}


class ConvLSTM(RNN):
    

    def __init__(
        self,
        rank,
        filters,
        kernel_size,
        strides=1,
        padding="valid",
        data_format=None,
        dilation_rate=1,
        activation="tanh",
        recurrent_activation="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,
        seed=None,
        return_sequences=False,
        return_state=False,
        go_backwards=False,
        stateful=False,
        **kwargs,
    ):
        cell = ConvLSTMCell(
            rank=rank,
            filters=filters,
            kernel_size=kernel_size,
            strides=strides,
            padding=padding,
            data_format=data_format,
            dilation_rate=dilation_rate,
            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,
            seed=seed,
            name="conv_lstm_cell",
            dtype=kwargs.get("dtype"),
        )
        super().__init__(
            cell,
            return_sequences=return_sequences,
            return_state=return_state,
            go_backwards=go_backwards,
            stateful=stateful,
            **kwargs,
        )
        self.input_spec = InputSpec(ndim=rank + 3)

    def call(self, sequences, initial_state=None, mask=None, training=False):
        return super().call(
            sequences, initial_state=initial_state, mask=mask, training=training
        )

    def compute_output_shape(self, sequences_shape, initial_state_shape=None):
        batch_size = sequences_shape[0]
        steps = sequences_shape[1]
        step_shape = (batch_size,) + sequences_shape[2:]
        state_shape = self.cell.compute_output_shape(step_shape)[0][1:]

        if self.return_sequences:
            output_shape = (
                batch_size,
                steps,
            ) + state_shape
        else:
            output_shape = (batch_size,) + state_shape

        if self.return_state:
            batched_state_shape = (batch_size,) + state_shape
            return output_shape, batched_state_shape, batched_state_shape
        return output_shape

    def compute_mask(self, _, mask):
        mask = tree.flatten(mask)[0]
        output_mask = mask if self.return_sequences else None
        if self.return_state:
            state_mask = [None, None]
            return [output_mask] + state_mask
        else:
            return output_mask

    @property
    def filters(self):
        return self.cell.filters

    @property
    def kernel_size(self):
        return self.cell.kernel_size

    @property
    def strides(self):
        return self.cell.strides

    @property
    def padding(self):
        return self.cell.padding

    @property
    def data_format(self):
        return self.cell.data_format

    @property
    def dilation_rate(self):
        return self.cell.dilation_rate

    @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

    def get_config(self):
        config = {
            "filters": self.filters,
            "kernel_size": self.kernel_size,
            "strides": self.strides,
            "padding": self.padding,
            "data_format": self.data_format,
            "dilation_rate": self.dilation_rate,
            "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,
            "seed": self.cell.seed,
        }
        base_config = super().get_config()
        del base_config["cell"]
        return {**base_config, **config}

    @classmethod
    def from_config(cls, config):
        return cls(**config)