我想在调用 Keras 模型时更好地理解参数 training。
在所有教程(如here)中都解释说,当您执行自定义训练步骤时,您应该像这样调用模型(因为某些层的行为可能会有所不同,具体取决于您是否想要进行训练或推理):
pred = model(x, training=True)
当你想进行推理时,你应该将训练设置为 false:
pred = model(x, training=False)
我现在想知道的是,功能模型的创建对此有何影响。假设我有 2 个模型:model_base 和 model_head,并且我想从这两个模型中创建一个新模型,我希望 model_base 始终用
training=False
调用(因为我打算像这样冻结它)在本教程中这里):
inputs = keras.Input(shape=(150, 150, 3))
x = base_model(inputs, training=False)
outputs = head_model(x)
new_model = keras.Model(inputs, outputs)
在这种情况下,当我稍后打电话时会发生什么情况
new_model(x_new, training=True)
?使用 training=False
代替 base_model
会被否决吗?或者无论我传递给 base_model
的是什么,现在的训练是否都将 new_model
设置为 True?如果是后者,这是否也意味着,如果我设置例如outputs = head_model(inputs, training=True)
,新模型的这一部分将始终在训练模式下运行?当我像这样运行 new_model 时,如果我没有给出任何具体的训练值,结果会如何?提前致谢!
new_model(x_new)
是一个布尔参数,用于确定此
training
函数是在 训练模式还是推理模式 下运行。例如,
call
层主要用于模型训练中的正则化,随机下降权重,但在推理时间或预测时间我们不希望这种情况发生。Dropout
通过此,我们为
y = Dropout(0.5)(x, training=True)
层设置
training=True
来训练时间。当我们调用 Dropout
时,它会设置一个标志为 .fit()
,当我们使用 True
或 evaluate
时,它后面会设置一个标志为 predict
。自定义训练循环也是如此。当我们将输入张量传递到False
范围内的模型时,我们可以设置这个参数;虽然没有手动设置,但是程序会自己计算出来。推理时间也是如此。因此,如果我们希望层分别运行 GradientTape
模式或 training
模式,则将此 True
参数设置为 False
或 training
。inference
现在回答你的问题。定义模型后
# training mode
with tf.GradientTape() as tape:
logits = model(x, training=True) # forward pass
# inference mode
al_logits = model(x, training=False)
现在,如果您运行这个新模型,无论是
# Freeze the base_model
base_model.trainable = False
inputs = keras.Input(shape=(150, 150, 3))
x = base_model(inputs, training=False)
outputs = head_model(x)
new_model = keras.Model(inputs, outputs)
还是自定义训练循环,
.fit()
将始终在推理模式下运行,因为它设置了 base_model
。training=False
的优先级顺序在keras中有记录:
training
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/keras/engine/base_layer.py
# Training mode for `Layer.call` is set via (in order of priority):
# (1) The `training` argument passed to this `Layer.call`, if it is not None
# (2) The training mode of an outer `Layer.call`.
# (3) The default mode set by `tf.keras.backend.set_learning_phase` (if set)
# (4) Any non-None default value for `training` specified in the call
# signature
# (5) False (treating the layer as if it's in inference)
属于情况(1)。为了以防万一,我们可以做一个简单的测试。
training
Dropout 层的默认
import tensorflow as tf
from tensorflow.keras.layers import Dropout
dropout = Dropout(0.99999)
x = [[1.0]]
dropout(x, training=True)
#0
dropout(x)
#1
是
training
。显然,层 dropout 无法记住它的最后一个 None
参数。将其放入模型中怎么样?
training
无需手动设置
inputs = tf.keras.Input((1,))
outputs = dropout(inputs)
model = tf.keras.Model(inputs, outputs)
model(x, training=True)
#0
model(x, training=False)
#1
,dropout 的行为遵循模型的
training
。尝试在构建模型时设置 training
:training
即使模型的
outputs = dropout(inputs, training=True)
model = tf.keras.Model(inputs, outputs)
model(x, training=False)
#0
为 False,dropout 层也会在训练模式下运行。 最后,在不手动设置的情况下,该层的
training
默认值是否会影响模型的行为?让我们将 dropout 的默认值 training
更改为 True:training
我们看到模型的
class Dropout2(Dropout):
def call(self, inputs, training=True):
return super().call(inputs, training=training)
dropout = Dropout2(0.99999)
dropout(x)
#0
outputs = dropout(inputs)
model = tf.keras.Model(inputs, outputs)
model(x, training=False)
#1
覆盖了图层的
training
。所以正如官方文档所说,优先级顺序是:由功能API手动设置的层的training
>外层的
training
例如模型的 training
> 图层的默认 training
值。