使用Tensorflow 2的Keras Functional API时传递`training = true`

在TF1中以图形模式运行时,我相信当我使用函数式API时,需要通过feeddict连接training=Truetraining=False。在TF2中执行此操作的正确方法是什么?

我相信使用tf.keras.Sequential时会自动处理。例如,在以下示例中,我不需要从docs指定training

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))

在使用功能性API进行训练时,我还可以假设keras会自动处理吗?这是使用函数api重写的相同模型:

inputs = tf.keras.Input(shape=((28,name="input_image")
hid = tf.keras.layers.Conv2D(32,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',metrics=['accuracy'])

model_fn.fit(train_data,acc = model_fn.evaluate(test_data)
print("Loss {:0.4f},acc))

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

可以找到这些模型的合作实验室here

masycq 回答:使用Tensorflow 2的Keras Functional API时传递`training = true`

我意识到BatchNormalization文档[1]中存在一个错误,其中{{TRAINABLE_ATTRIBUTE_NOTE}}实际上并未被预期的注释[2]取代:

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

但是,对于BatchNormalization层,设置   图层上的trainable = False表示该图层将   随后以推断模式运行(表示它将使用   移动均值和移动方差以标准化当前批次,   而不是使用当前批次的均值和方差)。   按顺序在TensorFlow 2.0中引入了此行为   使layer.trainable = False能够产生最常见的   在convnet微调用例中的预期行为。   请注意:

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

[1] https://www.tensorflow.org/api_docs/python/tf/keras/layers/BatchNormalization?version=stable

[2] https://github.com/tensorflow/tensorflow/blob/r2.0/tensorflow/python/keras/layers/normalization_v2.py#L26-L65

,

关于最初的更广泛的问题,即使用Keras Functional API时是否必须手动传递training标志,来自official docs的此示例建议您不应

# ...

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)
,

批处理归一化应用了一种转换,可将平均输出保持在接近0且输出标准偏差保持在1附近。重要的是,批处理归一化在训练和推理期间的工作原理不同。根据喀拉拉邦documentation

在训练期间(即,在使用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) 因此,该层仅在对统计数据与推断数据相似的数据进行训练后,才能在推断期间对其输入进行归一化。
本文链接:https://www.f2er.com/3153076.html

大家都在问