【问题标题】:Are Keras custom layer parameters non-trainable by default?默认情况下,Keras 自定义层参数是不可训练的吗?
【发布时间】:2020-12-28 08:58:26
【问题描述】:

我在 Keras 中构建了一个简单的自定义层,惊讶地发现参数默认没有设置为可训练。我可以通过显式设置可训练属性来使其工作。我无法通过查看文档或代码来解释为什么会这样。这是它应该是这样,还是我做错了什么,默认情况下使参数不可训练? 代码:

import tensorflow as tf


class MyDense(tf.keras.layers.Layer):
    def __init__(self, **kwargs):
        super(MyDense, self).__init__(kwargs)
        self.dense = tf.keras.layers.Dense(2, tf.keras.activations.relu)

    def call(self, inputs, training=None):
        return self.dense(inputs)


inputs = tf.keras.Input(shape=10)
outputs = MyDense()(inputs)
model = tf.keras.Model(inputs=inputs, outputs=outputs, name='test')
model.compile(loss=tf.keras.losses.MeanSquaredError())
model.summary()

输出:

Model: "test"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         [(None, 10)]              0         
_________________________________________________________________
my_dense (MyDense)           (None, 2)                 22        
=================================================================
Total params: 22
Trainable params: 0
Non-trainable params: 22
_________________________________________________________________

如果我像这样更改自定义层创建:

outputs = MyDense(trainable=True)(inputs)

输出是我所期望的(所有参数都是可训练的):

=================================================================
Total params: 22
Trainable params: 22
Non-trainable params: 0
_________________________________________________________________

然后它会按预期工作并使所有参数都可训练。我不明白为什么需要这样做。

【问题讨论】:

  • 有什么区别?设置trainable=True 不会改变我的参数数量
  • 编辑澄清。不更改参数的数量,但将参数从不可训练更改为可训练。这就是我要问的问题。

标签: python tensorflow keras


【解决方案1】:

毫无疑问,这是一个有趣的怪癖。

制作自定义层时,tf.Variable 将自动包含在trainable_variable 列表中。您没有使用tf.Variable,而是使用tf.keras.layers.Dense 对象,它不会被视为tf.Variable,并且默认情况下未设置trainable=True。但是,您使用的 Dense 对象将设置为可训练。见:

MyDense().dense.trainable
True

如果您使用tf.Variable(应该如此),默认情况下它将是可训练的。

import tensorflow as tf


class MyDense(tf.keras.layers.Layer):
    def __init__(self, units=2, input_dim=10):
        super(MyDense, self).__init__()
        w_init = tf.random_normal_initializer()
        self.w = tf.Variable(
            initial_value=w_init(shape=(input_dim, units), dtype="float32"),
            trainable=True,
        )
        b_init = tf.zeros_initializer()
        self.b = tf.Variable(
            initial_value=b_init(shape=(units,), dtype="float32"), trainable=True
        )

    def call(self, inputs, **kwargs):
        return tf.matmul(inputs, self.w) + self.b


inputs = tf.keras.Input(shape=10)
outputs = MyDense()(inputs)
model = tf.keras.Model(inputs=inputs, outputs=outputs, name='test')
model.compile(loss=tf.keras.losses.MeanSquaredError())
model.summary()
Model: "test"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_11 (InputLayer)        [(None, 10)]              0         
_________________________________________________________________
my_dense_18 (MyDense)        (None, 2)                 22        
=================================================================
Total params: 22
Trainable params: 22
Non-trainable params: 0
_________________________________________________________________

【讨论】:

  • 虽然我更愿意重用预定义的 Keras 层作为构建块,而不是使用 tf.Variable 重新实现它们,但这是有道理的。我遇到了这个相关的other question
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 2019-12-25
  • 2017-12-20
  • 1970-01-01
  • 2018-04-28
相关资源
最近更新 更多