TensorFlow 2.0如何从tf.keras.layers层获取可训练变量,例如Conv2D或Dense

时间:2019-12-10 13:54:54

标签: python tensorflow keras tensorflow2.0 tf.keras

我一直在尝试从我的图层中获取可训练的变量,但无法找到一种使它起作用的方法。所以这是我尝试过的:

我尝试直接访问Dense或Conv2D对象的内核和bias属性,但无济于事。我得到的结果类型是“密集对象没有属性'kernel'”。

DATE()

类似地,我尝试通过以下方式使用属性“ trainable_variables”:

TIME()

据我所知,这应该返回两个变量的列表,即权重和偏差变量。但是,我得到的是一个空列表。

关于如何从TensorFlow 2.0中的标签获取变量的任何想法?我希望以后能够以类似于以下方式将这些变量提供给优化器:

SELECT o1.theatreNo as roomNo,
       DATE(o1.startDateTime) as startDateTime, 
       TIME(o1.startDateTime) as firstOp, 
       TIME(o2.startDateTime) as secondOp
FROM operation o1
JOIN operation o2 ON o1.theatreNo = o2.theatreNo
WHERE o1.startDateTime < ADDTIME(o2.startDateTime,o2.duration)
AND ADDTIME(o1.startDateTime,o1.duration) > o2.startDateTime
AND o1.startDateTime < o2.startDateTime;

编辑: 这是我当前代码的一部分,用作示例并帮助回答问题(希望它是可读的)

trainable_variables.append(conv_layer.kernel)
trainable_variables.append(conv_layer.bias)

如您所见,我正在尝试将我所有的可训练变量收集到一个名为trainable_variables的列表属性中。但是,正如我提到的那样,此代码不起作用,因为在尝试获取这些层对象的内核和偏向属性时遇到错误。

2 个答案:

答案 0 :(得分:1)

让我以一个简单的模型为例开始,以使其更易于解释和理解。

model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(1, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Conv2D(1, (3, 3), activation='relu'))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(10, activation='relu'))
model.add(tf.keras.layers.Dense(10, activation='relu'))
model.add(tf.keras.layers.Dense(3, activation='softmax'))

使用渐变色带时,您传递model.trainable_weights,它返回整个模型的权重和偏差,并使用优化器来应用渐变。

如果打印model.trainable_weights的输出,则会得到此输出。 我删除了可读性的实际权重和偏见。

[<tf.Variable 'conv2d/kernel:0' shape=(3, 3, 3, 1) dtype=float32, numpy=array([...], dtype=float32)>,
 <tf.Variable 'conv2d/bias:0' shape=(1,) dtype=float32, numpy=array([...], dtype=float32)>,
 <tf.Variable 'conv2d_1/kernel:0' shape=(3, 3, 1, 1) dtype=float32, numpy=array([...], dtype=float32)>,
 <tf.Variable 'conv2d_1/bias:0' shape=(1,) dtype=float32, numpy=array([...], dtype=float32)>,
 <tf.Variable 'dense/kernel:0' shape=(169, 10) dtype=float32, numpy=array([...], dtype=float32)>,
 <tf.Variable 'dense/bias:0' shape=(10,) dtype=float32, numpy=array([...], dtype=float32)>,
 <tf.Variable 'dense_1/kernel:0' shape=(10, 10) dtype=float32, numpy=array([...], dtype=float32)>,
 <tf.Variable 'dense_1/bias:0' shape=(10,) dtype=float32, numpy=array([...], dtype=float32)>,
 <tf.Variable 'dense_2/kernel:0' shape=(10, 3) dtype=float32, numpy=array([...], dtype=float32)>,
 <tf.Variable 'dense_2/bias:0' shape=(3,) dtype=float32, numpy=array([...], dtype=float32)>]

如您所见,每个层的内核和偏差都作为列表输出。这是传递给渐变磁带的相同输出。如果您只想传递特定的图层,则可以对列表进行切片,并获得要训练的所需权重。

model.trainable_weights[0:2] # Get the first conv layer weights at index 0 and bias at index 1.

仅输出第一个转化层权重和偏差。

[<tf.Variable 'conv2d/kernel:0' shape=(3, 3, 3, 1) dtype=float32, numpy=array([...], dtype=float32)>,
 <tf.Variable 'conv2d/bias:0' shape=(1,) dtype=float32, numpy=array([...], dtype=float32)>]

答案 1 :(得分:0)

好的,我想我找到了问题。

在使用给定的图层对象之前,可训练变量不可用。运行前进通道后,我可以检索tf.keras.layers.Layer对象的属性,例如trainable_variables和weights。

但是,在前进通过之前,我收到了一个空白清单。为了使事情更加清楚:

with tf.GradientTape() as tape:
    print(dense_layers[0].trainable_variables)
    self.forward_pass(X)
    self.compute_loss()
    print(dense_layers[0].trainable_variables)

在上面的代码中,trainable_variables属性在执行self.forward_pass之前为空列表。但是,在此之后,我可以检索内核并偏向numpy数组。