如何在keras中预测时禁用dropout?

问题描述 投票:0回答:7

我在 keras 的神经网络模型中使用 dropout。一点点代码就像

model.add(Dropout(0.5))
model.add(Dense(classes))

为了测试,我正在使用

preds = model_1.predict_proba(image)

但是在测试时Dropout也参与预测分数,这是不应该发生的。我搜索了很多以禁用 dropout,但还没有得到任何提示。

有人有办法在 keras 中测试时禁用 Dropout 吗??

tensorflow machine-learning keras deep-learning neural-network
7个回答
48
投票

Keras 默认执行此操作。在 Keras 中,在测试模式下禁用 dropout。您可以查看代码here,看到它们在训练中使用丢弃的输入,在测试时使用实际输入。

据我所知,您必须从各层构建自己的训练函数,并指定训练标志以通过 dropout 进行预测(例如,不可能为预测函数指定训练标志)。如果您想要进行 GAN,由于生成的训练图像和生成的测试图像之间存在差异,GAN 会使用中间输出进行训练,并将网络作为一个整体进行训练,这是一个问题。


20
投票

如前所述,Keras 中的 dropout 仅在训练时发生(在训练期间按比例调整权重,以便在禁用 dropout 时学习到的权重适合预测)。

对于我们希望使用 dropout NNET 作为概率预测器的情况来说,这并不理想(这样当要求重复预测相同的输入时它会产生分布)。换句话说,Keras 的 Dropout 层旨在为您在训练时提供正则化,但在预测时提供学习分布的“均值函数”。

如果您想保留 dropout 进行预测,您可以轻松实现永久 dropout(“PermaDropout”)层(这是基于 F. Chollet 在 Keras 的 GitHub 讨论区 上提出的建议):

from keras.layers.core import Lambda
from keras import backend as K

def PermaDropout(rate):
    return Lambda(lambda x: K.dropout(x, level=rate))

通过用“PermaDropout”替换 Keras 模型中的任何 dropout 层,您也将获得预测中的概率行为。

# define the LSTM model
n_vocab = text_to_train.n_vocab

model = Sequential()
model.add(LSTM(n_vocab*4, 
          input_shape=input_shape, 
          return_sequences=True))
# Replace Dropout with PermaDropout
# model.add(Dropout(0.3)
model.add(PermaDropout(0.3))
model.add(LSTM(n_vocab*2))
# Replace Dropout with PermaDropout
# model.add(Dropout(0.3)
model.add(PermaDropout(0.3))
#model.add(Dense(n_vocab*2))
model.add(Dense(n_vocab, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

5
投票

要激活推理时间的 dropout,您只需在感兴趣的层中指定

training=True
(在我们的例子中为
Dropout
):

training=False

inp = Input(shape=(10,))
x = Dropout(0.3)(inp, training=False)
x = Dense(1)(x)
m = Model(inp,x)
# m.compile(...)
# m.fit(...)

X = np.random.uniform(0,1, (1,10))

output = []
for i in range(0,100):
    output.append(m.predict(X)) # always the same

training=True

inp = Input(shape=(10,))
x = Dropout(0.3)(inp, training=True)
x = Dense(1)(x)
m = Model(inp,x)
# m.compile(...)
# m.fit(...)

X = np.random.uniform(0,1, (1,10))

output = []
for i in range(0,100):
    output.append(m.predict(X)) # always different

默认情况下,训练设置为 False

这里在推理时使用 dropout 的完整示例


4
投票

Dropout 会从游戏中移除某些神经元,为了弥补这一点,我们通常采取两种方法之一。

  1. 在测试时缩放激活
  2. 在训练阶段反转dropout

keras 使用第二种校正形式,如您所见here


3
投票

由于较新的 Tensorflow 版本通常很受欢迎,您可以尝试以下操作:

train_prediction = model_or_layer(input_data_numpy, training=True)
test_prediction = model_or_layer(input_data_numpy, training=False)

这将为您提供考虑所需阶段行为的预测。 对于自定义训练循环(而不是

model.fit
,您可以自己进行急切的预测并应用梯度),使用它很重要:

#training
for batchX, batchY in data_generator:
    with with tf.GradientTape() as tape:
       train_outputs = model(batchX, training=True)
       loss = some_loss(batchY, train_outputs)
    gradients = tape.gradient(loss, model.trainable_weights)
    optimizer.apply_gradients(zip(gradients, model.trainable_weights))

#validating
for batchX, batchY in val_generator:
    val_outputs = model(batchX, training=False)
    #calculate metrics

我从未测试过以下内容,但在非急切模式下,您也可以使用现有层构建新模型,但将

training=False
传递给调用(功能 API 模型):

#if using an existing layer
output_symbolic_tensor = someExistingLayer(input_symbolic_tensor, training=True) 

#if you're creating a new layer now
output_symbolic_tensoe = SomeLayer(*layer_params)(input_symbolic_tensor, training=True)

0
投票

Dropout 层有一个名为“training”的调用参数,当您使用

model.fit
时,Keras 自动将此参数设置为
true
,当您调用模型并使用
model(input)
时,Keras 将此参数设置为
false

您可以在自定义层模型中使用此参数来手动控制Dropout。请参阅Keras 的官方文档了解更多信息。


0
投票
  1. 如果您使用 dropout 层,就会发生这种情况。

  2. 如果您在没有验证数据的情况下训练了模型,则模型不会保存在检查点位置。

3)如果 1) 和 2) 是正确的,并且如果您使用这种方法“model.save('model_name.h5')”保存模型,则在预测过程中会保留 dropout 的随机性,因此每次都会得到不同的结果。 :-)

© www.soinside.com 2019 - 2024. All rights reserved.