如何创建具有共享权重的两层,其中一层是另一层的转置?
How to create two layers with shared weights, where one is the transpose of the other?
我在 Tensorflow 2.0 中使用 Keras API。
举个例子,假设我想在我的模型中有两个密集层,分别称为 layer1
和 layer2
。但我想绑定它们的权重,使得 layer1
中的权重矩阵始终等于 layer2
.
中的权重矩阵的转置
我该怎么做?
您可以为此定义一个自定义 Keras 层,您可以在其中传递引用 Dense
层。
自定义密集层:
class CustomDense(Layer):
def __init__(self, reference_layer):
super(CustomDense, self).__init__()
self.ref_layer = reference_layer
def call(self, inputs):
weights = self.ref_layer.get_weights()[0]
bias = self.ref_layer.get_weights()[1]
weights = tf.transpose(weights)
x = tf.linalg.matmul(inputs, weights) + bias
return x
现在您使用 Functional-API.
将此层添加到模型中
inp = Input(shape=(5))
dense = Dense(5)
transposed_dense = CustomDense(dense)
#model
x = dense(inp)
x = transposed_dense(x)
model = Model(inputs=inp, outputs=x)
model.summary()
'''
Model: "model_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_2 (InputLayer) [(None, 5)] 0
_________________________________________________________________
dense_1 (Dense) (None, 5) 30
_________________________________________________________________
custom_dense_1 (CustomDense) (None, 5) 30
=================================================================
Total params: 30
Trainable params: 30
Non-trainable params: 0
_________________________________________________________________
'''
如您所见,dense
和 custom_dense
共享 30 个参数。这里 custom_dense
只是使用 dense
层的转置权重进行密集操作,它没有自己的参数。
编辑 1:回答评论中的问题(子classed 层如何获取#params?):
层 class 跟踪所有传递给它的 __init__
方法的对象。
transposed_dense._layers
# [<tensorflow.python.keras.layers.core.Dense at 0x7fc3e0874f28>]
以上参数将提供正在跟踪的依赖层。
所有子属性权重可以看成:
transposed_dense._gather_children_attribute("weights")
#[<tf.Variable 'dense_9/kernel:0' shape=(10, 5) dtype=float32>,
# <tf.Variable 'dense_9/bias:0' shape=(5,) dtype=float32>]
因此,当我们调用 model.summary()
时,它会在内部为每个 Layer
调用 count_params()
,计算所有 trainable_variable,包括自身和子属性。
我在 Tensorflow 2.0 中使用 Keras API。
举个例子,假设我想在我的模型中有两个密集层,分别称为 layer1
和 layer2
。但我想绑定它们的权重,使得 layer1
中的权重矩阵始终等于 layer2
.
我该怎么做?
您可以为此定义一个自定义 Keras 层,您可以在其中传递引用 Dense
层。
自定义密集层:
class CustomDense(Layer):
def __init__(self, reference_layer):
super(CustomDense, self).__init__()
self.ref_layer = reference_layer
def call(self, inputs):
weights = self.ref_layer.get_weights()[0]
bias = self.ref_layer.get_weights()[1]
weights = tf.transpose(weights)
x = tf.linalg.matmul(inputs, weights) + bias
return x
现在您使用 Functional-API.
将此层添加到模型中inp = Input(shape=(5))
dense = Dense(5)
transposed_dense = CustomDense(dense)
#model
x = dense(inp)
x = transposed_dense(x)
model = Model(inputs=inp, outputs=x)
model.summary()
'''
Model: "model_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_2 (InputLayer) [(None, 5)] 0
_________________________________________________________________
dense_1 (Dense) (None, 5) 30
_________________________________________________________________
custom_dense_1 (CustomDense) (None, 5) 30
=================================================================
Total params: 30
Trainable params: 30
Non-trainable params: 0
_________________________________________________________________
'''
如您所见,dense
和 custom_dense
共享 30 个参数。这里 custom_dense
只是使用 dense
层的转置权重进行密集操作,它没有自己的参数。
编辑 1:回答评论中的问题(子classed 层如何获取#params?):
层 class 跟踪所有传递给它的 __init__
方法的对象。
transposed_dense._layers
# [<tensorflow.python.keras.layers.core.Dense at 0x7fc3e0874f28>]
以上参数将提供正在跟踪的依赖层。 所有子属性权重可以看成:
transposed_dense._gather_children_attribute("weights")
#[<tf.Variable 'dense_9/kernel:0' shape=(10, 5) dtype=float32>,
# <tf.Variable 'dense_9/bias:0' shape=(5,) dtype=float32>]
因此,当我们调用 model.summary()
时,它会在内部为每个 Layer
调用 count_params()
,计算所有 trainable_variable,包括自身和子属性。