Keras 2 API 文档 / 层 API / 基础 Layer 类

基础 Layer 类

[源代码]

Layer

tf_keras.layers.Layer(trainable=True, name=None, dtype=None, dynamic=False, **kwargs)

这是所有层继承自的类。

层是一个可调用对象,它接受一个或多个张量作为输入,并输出一个或多个张量。它涉及计算,在call()方法中定义,以及状态(权重变量)。状态可以在各种地方创建,方便子类实现者

  • __init__()中;
  • 在可选的build()方法中,该方法在首次调用层时被调用,并提供输入的形状,这些形状可能在初始化时未知;
  • 在首次调用call()时,有一些注意事项将在下面讨论。

层是递归可组合的:如果您将一个Layer实例作为另一个Layer的属性,那么外部层将开始跟踪内部层创建的权重。嵌套层应该在__init__()方法中实例化。

用户只需实例化一个层,然后将其视为一个可调用对象。

参数

  • trainable: 布尔值,表示层的变量是否可训练。
  • name: 层的字符串名称。
  • dtype: 层计算和权重的dtype。也可以是 tf.keras.mixed_precision.Policy,它允许计算和权重dtype不同。默认值None表示使用tf.keras.mixed_precision.global_policy(),这是一个float32策略,除非设置为其他值。
  • dynamic: 如果您的层应该只以 Eager 模式运行,并且不应用于生成静态计算图,请将其设置为True。例如,对于 Tree-RNN或递归网络,或者任何使用Python控制流操作张层的层,都会是这种情况。如果为False,我们假设该层可以安全地用于生成静态计算图。

属性

  • name:层的名称(字符串)。
  • dtype: 层的权重的dtype。
  • variable_dtype: dtype的别名。
  • compute_dtype: 层的计算dtype。层会自动将输入转换为此dtype,这将导致计算和输出也为此dtype。当与 tf.keras.mixed_precision.Policy 结合使用混合精度时,此值将与variable_dtype不同。
  • dtype_policy: 层的dtype策略。有关详细信息,请参阅 tf.keras.mixed_precision.Policy 文档。
  • trainable_weights: 要包含在反向传播中的变量列表。
  • non_trainable_weights: 不应包含在反向传播中的变量列表。
  • weights: trainable_weights和non_trainable_weights列表的连接(按此顺序)。
  • trainable: 层是否应该被训练(布尔值),即其潜在可训练的权重是否应作为layer.trainable_weights的一部分返回。
  • input_spec: 可选的(列表)InputSpec对象,指定层可以接受的输入的约束。

我们建议Layer的子类实现以下方法:

  • __init__(): 定义自定义层属性,并创建不依赖于输入形状的层权重,使用add_weight()或其他状态。
  • build(self, input_shape): 此方法可用于创建依赖于输入形状的权重,使用add_weight()或其他状态。__call__()将自动构建层(如果尚未构建)通过调用build()
  • call(self, inputs, *args, **kwargs): 在确保build()已被调用后,在__call__中调用。call()执行将层应用于inputs的逻辑。第一次调用可能还会创建无法在build()中方便创建的状态;有关详细信息,请参阅其文档字符串。您可以在call()中选择使用的两个保留关键字参数是: - training(布尔值,调用是在推理模式还是训练模式)。有关更多详细信息,请参阅 层/模型子类化指南 - mask(布尔张量,编码输入中的屏蔽时间步,在RNN层中使用)。有关更多详细信息,请参阅 层/模型子类化指南 此方法的一个典型签名是call(self, inputs),用户可以根据需要选择添加trainingmask*args**kwargs仅在计划添加更多输入参数时用于未来扩展。
  • get_config(self): 返回一个包含用于初始化此层的配置的字典。如果键与__init__中的参数不同,则还应覆盖from_config(self)。此方法在保存层或包含该层的模型时使用。

示例

这是一个基本示例:一个具有两个变量wb的层,它返回y = w . x + b。它展示了如何实现build()call()。设置为层属性的变量被跟踪为层的权重(在layer.weights中)。

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

请注意,add_weight()方法提供了一个创建权重的快捷方式。

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

除了在训练期间通过反向传播更新的可训练权重外,层还可以具有不可训练的权重。这些权重旨在在call()期间手动更新。这是一个计算输入运行总和的示例层:

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 == []

有关创建层的更多信息,请参阅指南 通过子类化创建新层和模型


weights 属性

tf_keras.layers.Layer.weights

返回所有层变量/权重的列表。

返回

变量列表。


trainable_weights 属性

tf_keras.layers.Layer.trainable_weights

此层跟踪的所有可训练权重的列表。

可训练权重在训练期间通过梯度下降进行更新。

返回

可训练变量列表。


non_trainable_weights 属性

tf_keras.layers.Layer.non_trainable_weights

此层跟踪的所有不可训练权重的列表。

不可训练权重在训练期间*不会*更新。它们应在call()中手动更新。

返回

不可训练变量列表。


[源代码]

add_weight 方法

Layer.add_weight(
    name=None,
    shape=None,
    dtype=None,
    initializer=None,
    regularizer=None,
    trainable=None,
    constraint=None,
    use_resource=None,
    synchronization=tf.VariableSynchronization.AUTO,
    aggregation=tf.VariableSynchronization.NONE,
    **kwargs
)

向层添加一个新变量。

参数

  • name: 变量名称。
  • shape: 变量形状。如果未指定,则默认为标量。
  • dtype: 变量的类型。默认为self.dtype
  • initializer: 初始化器实例(可调用)。
  • regularizer: 正则化器实例(可调用)。
  • trainable: 布尔值,表示变量是否应作为层“trainable_variables”(例如,变量、偏置)或“non_trainable_variables”(例如,BatchNorm的均值和方差)的一部分。注意,如果synchronization设置为ON_READ,则trainable不能为True
  • constraint: 约束实例(可调用)。
  • use_resource: 是否使用ResourceVariable。有关更多信息,请参阅 此指南
  • synchronization: 指示分布式变量何时将被聚合。可接受的值是类 tf.VariableSynchronization 中定义的常量。默认情况下,同步设置为AUTO,当前的DistributionStrategy会选择何时同步。如果synchronization设置为ON_READ,则trainable不能设置为True
  • aggregation: 指示分布式变量将如何聚合。可接受的值是类 tf.VariableAggregation 中定义的常量。
  • **kwargs: 其他关键字参数。可接受的值包括gettercollectionsautocastexperimental_autocastcaching_device

返回

创建的变量。

引发

  • ValueError: 当提供不支持的dtype且未提供初始化器时,或当trainable被设置为True且synchronization被设置为ON_READ时。

trainable 属性

tf_keras.layers.Layer.trainable

[源代码]

get_weights 方法

Layer.get_weights()

以NumPy数组的形式返回层的当前权重。

层的权重代表了层的状态。此函数以NumPy数组列表的形式返回可训练和不可训练权重值,这些值又可以用于将状态加载到具有类似参数的层中。

例如,一个Dense层返回一个包含两个值的列表:核矩阵和偏置向量。这些可用于设置另一个Dense层的权重:

>>> layer_a = tf.keras.layers.Dense(1,
...   kernel_initializer=tf.constant_initializer(1.))
>>> a_out = layer_a(tf.convert_to_tensor([[1., 2., 3.]]))
>>> layer_a.get_weights()
[array([[1.],
       [1.],
       [1.]], dtype=float32), array([0.], dtype=float32)]
>>> layer_b = tf.keras.layers.Dense(1,
...   kernel_initializer=tf.constant_initializer(2.))
>>> b_out = layer_b(tf.convert_to_tensor([[10., 20., 30.]]))
>>> layer_b.get_weights()
[array([[2.],
       [2.],
       [2.]], dtype=float32), array([0.], dtype=float32)]
>>> layer_b.set_weights(layer_a.get_weights())
>>> layer_b.get_weights()
[array([[1.],
       [1.],
       [1.]], dtype=float32), array([0.], dtype=float32)]

返回

权重值作为NumPy数组列表。


[源代码]

set_weights 方法

Layer.set_weights(weights)

使用NumPy数组设置层的权重。

层的权重代表了层的状态。此函数从NumPy数组设置权重值。权重值应按层创建的顺序传递。请注意,必须在调用此函数之前通过调用层来实例化层的权重。

例如,一个Dense层返回一个包含两个值的列表:核矩阵和偏置向量。这些可用于设置另一个Dense层的权重:

>>> layer_a = tf.keras.layers.Dense(1,
...   kernel_initializer=tf.constant_initializer(1.))
>>> a_out = layer_a(tf.convert_to_tensor([[1., 2., 3.]]))
>>> layer_a.get_weights()
[array([[1.],
       [1.],
       [1.]], dtype=float32), array([0.], dtype=float32)]
>>> layer_b = tf.keras.layers.Dense(1,
...   kernel_initializer=tf.constant_initializer(2.))
>>> b_out = layer_b(tf.convert_to_tensor([[10., 20., 30.]]))
>>> layer_b.get_weights()
[array([[2.],
       [2.],
       [2.]], dtype=float32), array([0.], dtype=float32)]
>>> layer_b.set_weights(layer_a.get_weights())
>>> layer_b.get_weights()
[array([[1.],
       [1.],
       [1.]], dtype=float32), array([0.], dtype=float32)]

参数

  • weights: NumPy数组列表。数组的数量和形状必须与层权重的维度数量匹配(即,它应该与get_weights的输出匹配)。

引发

  • ValueError: 如果提供的权重列表与层的规范不匹配。

[源代码]

get_config 方法

Model.get_config()

返回Model的配置。

配置是一个Python字典(可序列化),包含对象的配置,在本例中是Model。这允许Model稍后(不带其训练的权重)从该配置中重新实例化。

请注意,get_config()不保证每次调用都返回字典的副本。如果调用者想修改返回的字典,则应进行复制。

建议子类化Model的开发者覆盖此方法,并继续从super(MyModel, self).get_config()更新字典,以提供此Model的正确配置。默认配置将为init参数返回配置字典,如果它们是基本类型。当需要自定义get_config()实现来子类化模型时,将引发NotImplementedError

返回

包含此Model配置的Python字典。


[源代码]

add_loss 方法

Layer.add_loss(losses, **kwargs)

添加损失张量,可能依赖于层输入。

一些损失(例如,活动正则化损失)可能依赖于调用层时传入的输入。因此,当在不同的输入ab上重用同一层时,layer.losses中的某些条目可能依赖于a,而另一些则依赖于b。此方法会自动跟踪依赖项。

此方法可以在子类化层或模型的call函数内部使用,在这种情况下,losses应该是张量或张量列表。

示例

class MyLayer(tf.keras.layers.Layer):
  def call(self, inputs):
    self.add_loss(tf.abs(tf.reduce_mean(inputs)))
    return inputs

相同的代码在分布式训练中也能正常工作:传递给add_loss()的输入被视为正则化损失,并在训练循环(内置Model.fit()和兼容的自定义训练循环)中跨副本平均。

add_loss 方法也可以在构建期间直接在Functional Model上调用。在这种情况下,传递给该模型的任何损失张量都必须是符号化的,并且能够追溯到模型的Input。这些损失成为模型拓扑的一部分,并在get_config中跟踪。

示例

inputs = tf.keras.Input(shape=(10,))
x = tf.keras.layers.Dense(10)(inputs)
outputs = tf.keras.layers.Dense(1)(x)
model = tf.keras.Model(inputs, outputs)
# Activity regularization.
model.add_loss(tf.abs(tf.reduce_mean(x)))

如果您的损失不是这种情况(例如,如果您的损失引用了模型层之一的Variable),您可以将损失包装在一个零参数的lambda函数中。这些损失不被跟踪为模型拓扑的一部分,因为它们无法序列化。

示例

inputs = tf.keras.Input(shape=(10,))
d = tf.keras.layers.Dense(10)
x = d(inputs)
outputs = tf.keras.layers.Dense(1)(x)
model = tf.keras.Model(inputs, outputs)
# Weight regularization.
model.add_loss(lambda: tf.reduce_mean(d.kernel))

参数

  • losses: 损失张量,或张量列表/元组。而不是张量,损失也可以是零参数可调用对象,这些对象会创建一个损失张量。
  • **kwargs: 仅用于向后兼容。

losses 属性

tf_keras.layers.Layer.losses

使用add_loss() API添加的损失列表。

在访问此属性时会创建变量正则化张量,因此它是 Eager 安全的:在 tf.GradientTape 下访问losses会将梯度反向传播到相应的变量。

示例

>>> class MyLayer(tf.keras.layers.Layer):
...   def call(self, inputs):
...     self.add_loss(tf.abs(tf.reduce_mean(inputs)))
...     return inputs
>>> l = MyLayer()
>>> l(np.ones((10, 1)))
>>> l.losses
[1.0]
>>> inputs = tf.keras.Input(shape=(10,))
>>> x = tf.keras.layers.Dense(10)(inputs)
>>> outputs = tf.keras.layers.Dense(1)(x)
>>> model = tf.keras.Model(inputs, outputs)
>>> # Activity regularization.
>>> len(model.losses)
0
>>> model.add_loss(tf.abs(tf.reduce_mean(x)))
>>> len(model.losses)
1
>>> inputs = tf.keras.Input(shape=(10,))
>>> d = tf.keras.layers.Dense(10, kernel_initializer='ones')
>>> x = d(inputs)
>>> outputs = tf.keras.layers.Dense(1)(x)
>>> model = tf.keras.Model(inputs, outputs)
>>> # Weight regularization.
>>> model.add_loss(lambda: tf.reduce_mean(d.kernel))
>>> model.losses
[<tf.Tensor: shape=(), dtype=float32, numpy=1.0>]

返回

张量列表。