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

基础 Layer 类

[源代码]

Layer

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

这是所有层继承的基类。

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

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

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

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

参数

  • trainable: 布尔值,表示该层的变量是否应该可训练。
  • name: 层的字符串名称。
  • dtype: 层计算和权重的 dtype。也可以是 tf.keras.mixed_precision.Policy,它允许计算和权重 dtype 不同。默认值为 None,表示使用 tf.keras.mixed_precision.global_policy(),除非设置为不同的值,否则它是一个 float32 策略。
  • dynamic: 如果你的层应该只在急切模式下运行,并且不应该用于生成静态计算图,则将其设置为 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 且同步设置为 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 的正确配置。如果初始化参数是基本类型,则默认配置将返回初始化参数的配置字典。在子类模型需要自定义 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 方法也可以在构建期间直接在函数式模型上调用。在这种情况下,传递给此模型的任何损失张量都必须是符号的,并且能够追溯到模型的 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 添加的损失列表。

当访问此属性时,会创建变量正则化张量,因此它是即时安全的:在 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>]

返回

张量列表。