Keras 2 API 文档 / 层 API / 循环层 / 基础 RNN 层

基础 RNN 层

[源代码]

RNN

tf_keras.layers.RNN(
    cell,
    return_sequences=False,
    return_state=False,
    go_backwards=False,
    stateful=False,
    unroll=False,
    time_major=False,
    **kwargs
)

循环层的基类。

有关 RNN API 用法的详细信息,请参阅TF-Keras RNN API 指南

参数

  • cell:RNN 单元实例或 RNN 单元实例列表。RNN 单元是一个具有以下特性的类:
    • 一个 call(input_at_t, states_at_t) 方法,返回 (output_at_t, states_at_t_plus_1)。单元的 call 方法还可以接受可选参数 constants,详见下文“关于传递外部常量的说明”部分。
    • 一个 state_size 属性。它可以是一个单独的整数(单个状态),表示循环状态的大小。它也可以是一个整数列表/元组(每个状态一个大小)。state_size 还可以是 TensorShape 或 TensorShape 的元组/列表,用于表示高维状态。
    • 一个 output_size 属性。它可以是一个单独的整数或 TensorShape,表示输出的形状。出于向后兼容性原因,如果单元没有此属性,其值将从 state_size 的第一个元素推断。
    • 一个 get_initial_state(inputs=None, batch_size=None, dtype=None) 方法,如果用户没有通过其他方式指定任何初始状态,则此方法创建一个张量,用作 call() 的初始状态。返回的初始状态的形状应为 [batch_size, cell.state_size]。单元可以选择创建全零张量,或根据单元实现创建其他值填充的张量。inputs 是 RNN 层的输入张量,其 shape[0] 应包含 batch 大小,并且还包含 dtype。请注意,在图构建期间 shape[0] 可能为 None。提供了 inputsbatch_sizedtype 对。batch_size 是一个标量张量,表示输入的 batch 大小。dtypetf.DType,表示输入的数据类型。为了向后兼容,如果单元未实现此方法,RNN 层将创建一个大小为 [batch_size, cell.state_size] 的全零张量。如果 cell 是 RNN 单元实例的列表,则这些单元将在 RNN 中彼此堆叠,从而形成高效的堆叠 RNN。
  • return_sequences:布尔值 (默认 False)。是返回输出序列中的最后一个输出,还是返回完整序列。
  • return_state:布尔值 (默认 False)。除了输出之外,是否返回最后一个状态。
  • go_backwards:布尔值 (默认 False)。如果为 True,则反向处理输入序列并返回反转的序列。
  • stateful:布尔值 (默认 False)。如果为 True,则 batch 中索引 i 处每个样本的最后一个状态将用作下一个 batch 中索引 i 处样本的初始状态。
  • unroll:布尔值 (默认 False)。如果为 True,则网络将展开,否则将使用符号循环。展开可以加快 RNN 的速度,但往往会占用更多内存。展开仅适用于短序列。
  • time_majorinputsoutputs 张量的形状格式。如果为 True,则输入和输出的形状为 (timesteps, batch, ...),否则为 (batch, timesteps, ...)。使用 time_major = True 效率略高,因为它避免了 RNN 计算开始和结束时的转置。然而,大多数 TensorFlow 数据是 batch-major 形式,因此默认情况下,此函数接受 batch-major 形式的输入并发出 batch-major 形式的输出。
  • zero_output_for_mask:布尔值 (默认 False)。是否应在被遮罩的时间步使用零作为输出。请注意,此字段仅在 return_sequences 为 True 并提供遮罩时使用。如果您想在不干扰被遮罩时间步的情况下重用 RNN 的原始输出序列(例如,合并双向 RNN),此字段非常有用。

调用参数

  • inputs:输入张量。
  • mask:形状为 [batch_size, timesteps] 的二进制张量,指示是否应对给定的时间步进行遮罩。单个 True 条目表示应使用相应的时间步,而 False 条目表示应忽略相应的时间步。
  • training:Python 布尔值,指示层应在训练模式还是推理模式下运行。调用单元时,此参数会传递给单元。这适用于使用 dropout 的单元。
  • initial_state:初始状态张量列表,将传递给单元的第一次调用。
  • constants:常量张量列表,将在每个时间步传递给单元。

输入形状

N-D 张量,形状为 [batch_size, timesteps, ...];当 time_major 为 True 时,形状为 [timesteps, batch_size, ...]

输出形状

  • 如果 return_state 为 True:一个张量列表。第一个张量是输出。其余张量是最后一个状态,每个张量的形状为 [batch_size, state_size],其中 state_size 可以是高维张量形状。
  • 如果 return_sequences 为 True:N-D 张量,形状为 [batch_size, timesteps, output_size](其中 output_size 可以是高维张量形状);当 time_major 为 True 时,形状为 [timesteps, batch_size, output_size]
  • 否则,N-D 张量,形状为 [batch_size, output_size],其中 output_size 可以是高维张量形状。

遮罩:此层支持对具有可变时间步数的输入数据进行遮罩。要将遮罩引入数据,请使用 mask_zero 参数设置为 True 的 [tf.keras.layers.Embedding] 层。

关于在 RNN 中使用有状态的说明:可以将 RNN 层设置为“有状态”,这意味着在一个 batch 中为样本计算的状态将作为下一个 batch 中样本的初始状态重复使用。这假设不同连续 batch 中的样本之间存在一对一的映射。

要启用有状态性: - 在层构造函数中指定 stateful=True。 - 通过以下方式为模型指定固定的 batch size:如果是序贯模型:将 batch_input_shape=(...) 传递给模型的第一个层。对于具有 1 个或多个 Input 层的函数式模型:将 batch_shape=(...) 传递给模型的所有第一个层。这是输入(包括 batch size)的预期形状。它应该是一个整数元组,例如 (32, 10, 100)。 - 调用 fit() 时指定 shuffle=False

要重置模型的状态,请在特定层或整个模型上调用 .reset_states()

关于指定 RNN 初始状态的说明:您可以通过在调用 RNN 层时使用关键字参数 initial_state 来符号化地指定其初始状态。initial_state 的值应为一个张量或张量列表,表示 RNN 层的初始状态。

您可以通过调用 reset_states 并使用关键字参数 states 来数值化地指定 RNN 层的初始状态。states 的值应为一个 numpy 数组或 numpy 数组列表,表示 RNN 层的初始状态。

关于将外部常量传递给 RNN 的说明:您可以使用 RNN.__call__(以及 RNN.call)方法的 constants 关键字参数将“外部”常量传递给单元。这要求 cell.call 方法接受相同的关键字参数 constants。此类常量可用于根据额外的静态输入(不随时间变化)调整单元的变换,也称为注意力机制。

示例

from tf_keras.src.layers import RNN
from tf_keras.src import backend

# First, let's define a RNN Cell, as a layer subclass.
class MinimalRNNCell(keras.layers.Layer):

    def __init__(self, units, **kwargs):
        self.units = units
        self.state_size = units
        super(MinimalRNNCell, self).__init__(**kwargs)

    def build(self, input_shape):
        self.kernel = self.add_weight(shape=(input_shape[-1], self.units),
                                      initializer='uniform',
                                      name='kernel')
        self.recurrent_kernel = self.add_weight(
            shape=(self.units, self.units),
            initializer='uniform',
            name='recurrent_kernel')
        super().build(input_shape)

    def call(self, inputs, states):
        prev_output = states[0]
        h = backend.dot(inputs, self.kernel)
        output = h + backend.dot(prev_output, self.recurrent_kernel)
        return output, [output]

# Let's use this cell in a RNN layer:

cell = MinimalRNNCell(32)
x = keras.Input((None, 5))
layer = RNN(cell)
y = layer(x)

# Here's how to use the cell to build a stacked RNN:

cells = [MinimalRNNCell(32), MinimalRNNCell(64)]
x = keras.Input((None, 5))
layer = RNN(cells)
y = layer(x)