首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Tensorflow 2的Keras传递`training=true`

使用Tensorflow 2的Keras传递`training=true`
EN

Stack Overflow用户
提问于 2019-11-06 10:32:34
回答 3查看 6K关注 0票数 8

在TF1中以图形模式操作时,我认为在使用函数式API时,需要通过馈线将training=Truetraining=False连接起来。在TF2中做这件事的正确方法是什么?

我相信这是在使用tf.keras.Sequential时自动处理的。例如,我不需要在下面的示例中从training中指定文档

代码语言:javascript
复制
model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(32, 3, activation='relu',
                           kernel_regularizer=tf.keras.regularizers.l2(0.02),
                           input_shape=(28, 28, 1)),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dropout(0.1),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Dense(10, activation='softmax')
])

# Model is the full model w/o custom layers
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(train_data, epochs=NUM_EPOCHS)
loss, acc = model.evaluate(test_data)
print("Loss {:0.4f}, Accuracy {:0.4f}".format(loss, acc))

我还可以假设keras在使用functional进行培训时会自动处理这个问题吗?下面是使用函数api重写的相同模型:

代码语言:javascript
复制
inputs = tf.keras.Input(shape=((28,28,1)), name="input_image")
hid = tf.keras.layers.Conv2D(32, 3, activation='relu',
                           kernel_regularizer=tf.keras.regularizers.l2(0.02),
                           input_shape=(28, 28, 1))(inputs)
hid = tf.keras.layers.MaxPooling2D()(hid)
hid = tf.keras.layers.Flatten()(hid)
hid = tf.keras.layers.Dropout(0.1)(hid)
hid = tf.keras.layers.Dense(64, activation='relu')(hid)
hid = tf.keras.layers.BatchNormalization()(hid)
outputs = tf.keras.layers.Dense(10, activation='softmax')(hid)
model_fn = tf.keras.Model(inputs=inputs, outputs=outputs)

# Model is the full model w/o custom layers
model_fn.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model_fn.fit(train_data, epochs=NUM_EPOCHS)
loss, acc = model_fn.evaluate(test_data)
print("Loss {:0.4f}, Accuracy {:0.4f}".format(loss, acc))

我不确定hid = tf.keras.layers.BatchNormalization()(hid)是否需要成为hid = tf.keras.layers.BatchNormalization()(hid, training)

这些模型的colab可以找到这里

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-12-30 05:04:12

我意识到BatchNormalization文档1中存在一个错误,其中{{TRAINABLE_ATTRIBUTE_NOTE}}实际上没有被预期的注释2所取代。

关于将layer.trainable = False 设置在 BatchNormalization 层上的:设置layer.trainable = False的意思是冻结该层,即它的内部状态在训练过程中不会改变:它的可训练权重在fit()train_on_batch()期间不会更新,其状态更新也不会运行。通常,这并不一定意味着该层以推理模式运行(通常由调用层时可以传递的training参数控制)。“冻结状态”和“推理模式”是两个独立的概念。

但是,对于trainable = False层,在该层上设置意味着该层随后将以推理模式运行(这意味着它将使用移动均值和移动方差来规范当前批处理,而不是使用当前批处理的均值和方差)。这种行为已经在TensorFlow 2.0中引入,以使layer.trainable = False能够在convnet微调用例中产生最常见的行为。请注意:

  • 此行为仅在TensorFlow 2.0时发生。在1.*中,设置layer.trainable = False将冻结该层,但不会将其切换到推断模式。
  • 在包含其他层的模型上设置trainable将递归地设置所有内部层的trainable值。
  • 如果在调用模型上的trainable属性后更改了compile()属性的值,则在再次调用compile()之前,新值不会对该模型生效。

1

2

票数 6
EN

Stack Overflow用户

发布于 2020-09-30 19:36:06

至于在使用Keras时是否必须手动传递training标志这一更广泛的问题,官方文件中的这个示例建议您的不应该使用

代码语言:javascript
复制
# ...

x = Dropout(0.5)(x)
outputs = Linear(10)(x)
model = tf.keras.Model(inputs, outputs)

# ...

# You can pass a `training` argument in `__call__`
# (it will get passed down to the Dropout layer).
y = model(tf.ones((2, 16)), training=True)
票数 4
EN

Stack Overflow用户

发布于 2020-11-08 04:17:24

批归一化应用了一种转换,使平均输出接近0,输出标准差接近1。更重要的是,在训练和推理过程中,批归一化的工作方式不同。根据角星文档的说法

在训练期间(即当使用fit()或使用参数training=True调用层/模型时),该层使用当前一批输入的均值和标准差来规范其输出。也就是说,对于被标准化的每个通道,该层返回(batch - mean(batch)) / (var(batch) + epsilon) * gamma + beta,其中:

  • epsilon是一个小常数(可配置为构造函数参数的一部分)
  • gamma是一个学习的缩放因子(初始化为1),它可以通过将scale=False传递给构造函数来禁用。
  • beta是一个学习的偏移因子(初始化为0),它可以通过将center=False传递给构造函数来禁用。

在推理过程中(即当使用evaluate()predict()或使用参数training=False调用层/模型(这是默认的)时,该层使用它在训练期间看到的批的均值和标准差的移动平均值来规范其输出。也就是说,它返回(batch - self.moving_mean) / (self.moving_var + epsilon) * gamma + beta

self.moving_meanself.moving_var是不可训练的变量,每次以训练模式调用层时都会更新它们,如下所示:

  • moving_mean = moving_mean * momentum + mean(batch) * (1 - momentum)
  • moving_var = moving_var * momentum + var(batch) * (1 - momentum)本身,该层只有在对具有与推理数据具有相似统计信息的数据进行训练之后,才能在推理期间对其输入进行规范化。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58728086

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档