Layer
类tf_keras.layers.Layer(trainable=True, name=None, dtype=None, dynamic=False, **kwargs)
这是所有层继承的基类。
一个层是一个可调用对象,它接受一个或多个张量作为输入,并输出一个或多个张量。它涉及在 call()
方法中定义的计算和状态(权重变量)。状态可以在各种地方创建,方便子类实现者:
__init__()
中;build()
方法中,该方法由层的第一次 __call__()
调用,并提供输入形状,这些形状在初始化时可能未知;call()
时,有一些下面讨论的注意事项。层是可递归组合的:如果将一个 Layer 实例作为另一个 Layer 的属性赋值,则外部层将开始跟踪内部层创建的权重。嵌套层应在 __init__()
方法中实例化。
用户只需实例化一个层,然后将其视为可调用对象。
参数
tf.keras.mixed_precision.Policy
,它允许计算和权重 dtype 不同。默认值为 None
,表示使用 tf.keras.mixed_precision.global_policy()
,除非设置为不同的值,否则它是一个 float32 策略。True
。例如,对于 Tree-RNN 或递归网络,或者通常对于任何使用 Python 控制流操作张量的层,都会出现这种情况。如果为 False
,我们假设该层可以安全地用于生成静态计算图。属性
dtype
的别名。tf.keras.mixed_precision.Policy
一起使用时,这会与 variable_dtype
不同。tf.keras.mixed_precision.Policy
文档。layer.trainable_weights
的一部分返回。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)
,如果层需要,用户可以选择添加 training
和 mask
。 *args
和 **kwargs
仅在计划添加更多输入参数时对未来扩展有用。get_config(self)
: 返回一个包含用于初始化此层的配置的字典。如果键与 __init__
中的参数不同,则也覆盖 from_config(self)
。此方法在保存层或包含此层的模型时使用。示例
这是一个基本示例:一个具有两个变量 w
和 b
的层,返回 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
)
向层添加一个新变量。
参数
self.dtype
。synchronization
设置为 ON_READ
,则 trainable
不能为 True
。ResourceVariable
。有关更多信息,请参阅 本指南。tf.VariableSynchronization
中定义的常量。默认情况下,同步设置为 AUTO
,当前 DistributionStrategy
选择何时同步。如果将 synchronization
设置为 ON_READ
,则不能将 trainable
设置为 True
。tf.VariableAggregation
中定义的常量。getter
、collections
、autocast
、experimental_autocast
和 caching_device
。返回
创建的变量。
引发
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)]
参数
get_weights
的输出相匹配)。引发
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)
添加损失张量,可能依赖于层输入。
一些损失(例如,活动正则化损失)可能依赖于调用层时传递的输入。因此,当在不同的输入 a
和 b
上重用同一层时,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
属性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>]
返回
张量列表。