【发布时间】:2021-02-11 00:29:24
【问题描述】:
我想创建一个包含可训练和不可训练权重的层(使用 tensorflow.keras)。我尝试通过子类化 keras.layers.Layer 来做到这一点,如下例所示:
class MySum(keras.layers.Layer):
def __init__(self, units=32, **kwargs):
super(MySum, self).__init__(**kwargs)
self.units = units
def build(self, input_shape):
n_input = input_shape[-1] # nb of input elements
n_output = self.units # nb of layer neurons
n_input_div_2 = input_shape[-1] // 2
# 1. add the trainable weights
self.w = self.add_weight(shape=(n_input_div_2, self.units),
initializer=tf.ones_initializer(),
trainable=True)
# 2. add the non trainable weights
self.w = self.add_weight(shape=(input_shape[-1]-n_input_div_2, self.units),
initializer=tf.keras.initializers.Constant(value=3),
trainable=False)
def call(self, inputs):
return tf.matmul(inputs, self.w)
不幸的是,这样做所有的权重都是不可训练的。如果我首先添加不可训练的权重,那么所有权重都是可训练的(似乎可训练标志是根据最后添加的权重设置的)。 我在这里错过了什么?
编辑: 我尝试在构建函数中使用 Snoopy 博士建议的不同名称:
# 1. add the trainable weights
w1 = self.add_weight(shape=(n_input_div_2, self.units),
initializer=tf.ones_initializer(),
trainable=True)
# 2. add the non trainable weights
w2 = self.add_weight(shape=(input_shape[-1]-n_input_div_2, self.units),
initializer=tf.keras.initializers.Constant(value=3),
trainable=False)
self.w = tf.concat([w1, w2], 0)
但是,当我尝试像这样使用我的图层时:
custom = customLayer.MySum(1, name='somme')
my_input = keras.Input(shape=(2,), name="input")
my_output = custom(my_input)
print(custom.get_weights())
我通过 get_weights() 函数获得:
tf.Tensor(
[[1.]
[3.]], shape=(2, 1), dtype=float32)
[array([[1.],
[1.]], dtype=float32), array([[1.]], dtype=float32), array([[3.]], dtype=float32)]
-
[[1.],[1.]] 数组从何而来? (我希望只有 [[1.][3.]] 数组)
-
在训练我的模型时,我有很多警告:"WARNING:tensorflow:Gradients do not exist for variables ['somme/Variable:0', 'somme/Variable:0'] when minimum the损失。” keras 如何将我自己的权重 (self.w) 与 get_weights() 返回的权重联系起来?
注意:当我创建自定义层而不混合可训练和不可训练权重时,我没有这些问题。
【问题讨论】:
-
你在两个权重中使用相同的变量,这会覆盖之前定义的权重,只是使用不同的变量名
标签: tensorflow keras