繁体   English   中英

Keras 模型在训练时返回很高的验证准确度,但在评估时准确度非常低

[英]Keras model returns high validation accuracy while training, but accuracy is very low while evaluating

我正在尝试在MobileNetV3Small下训练一个简单的keras.applications ,如下所示

base_model = keras.applications.MobileNetV3Small(
        input_shape= INPUT_SHAPE,
        alpha=.125,
        include_top=False,
        classes=1,
        dropout_rate = 0.2,
        weights=None)

    x = keras.layers.Flatten()(base_model.output)
    preds = keras.layers.Dense(1, activation="sigmoid")(x)
    model = keras.Model(inputs=base_model.input, outputs=preds)

 model.compile(loss="binary_crossentropy",
                optimizer='RMSprop',
                metrics=["binary_accuracy"])

train_datagen = ImageDataGenerator(
        rescale=1.0 / 255,
        rotation_range=40,
        horizontal_flip=True,
        vertical_flip=True,
    )

    train_generator = train_datagen.flow_from_directory(
        os.path.join(DATA_ROOT, 'train'),
        target_size=(56,56),
        batch_size=128,
        class_mode="binary",
    )


    validation_datagen = ImageDataGenerator(rescale=1.0 / 255)
    validation_generator = validation_datagen.flow_from_directory(
        os.path.join(DATA_ROOT, 'val'),
        target_size=(56,56),
        batch_size=128,
        class_mode="binary",
    )

    model_checkpoint_callback = keras.callbacks.ModelCheckpoint(
        filepath=SAVE_DIR,
        save_weights_only=True,
        monitor='val_binary_accuracy',
        mode='max',
        save_best_only=True)

    es_callback = keras.callbacks.EarlyStopping(patience=10)

    model.fit(train_generator,
                epochs=100,
                validation_data=validation_generator,
                callbacks=[model_checkpoint_callback, es_callback],
                shuffle=True)

当我训练模型时,我得到了大约 0.94 的验证准确度。 但是当我在完全相同的验证数据上调用model.evaluate时,准确度变为 0.48。 当我使用任何数据调用model.predict时,它会输出常数值 0.51...

学习率、优化器或指标没有任何问题。 这里有什么问题?


编辑:

训练后当我跑步

pred_results = model.evaluate(validation_generator)
print(pred_results)

它给了我 1 epoch 训练网络的输出:

6/6 [===============================] - 1s 100ms/步 - 损失:0.6935 - binary_accuracy: 0.8461

但是,当我使用model.save()tf.keras.models.save_model()保存和加载模型时。 输出变成这样:

6/6 [===============================] - 2s 100ms/step - 损失:0.6935 - binary_accuracy: 0.5028 [0.6935192346572876 , 0.5027709603309631]

model.predict(validation_generator)的输出是:

[[0.5080832] [0.5080832] [0.5080832] [0.5080832]。 . . [0.5080832] [0.5080832]]


到目前为止我已经尝试过:

  1. 使用tf.keras.utils.image_dataset_from_directory()而不是ImageDataGenerator
  2. 修复了全局的 tensorflow 和 numpy 种子。
  3. 在另一篇SO 帖子中发现了类似的问题,并且将 MobileNet BatchNormalization 层的momentum参数一一减少。
for layer in model.layers[0].layers:
    if type(layer) is tf.keras.layers.BatchNormalization:
        layer.momentum = 0.9

前两个动作没有效果,在应用第三步之后,我对任何输入都不再有相同的预测。 但是, evaluate()predict()仍然具有不同的准确度值。

可能值得尝试model.save_weights('directory') ,然后通过 model.load_weights('directory') 重建模型(我认为这里是重新运行base_model = ...代码model.load_weights('directory') 这就是我在自己的模型中所做的,然后当我这样做时,准确性/损失在保存和加载之前和之后保持完全相同。

如果您在拟合模型后运行pred_results = model.evaluate(validation_generator) ,此时加载的权重是上次训练时期更新的权重。 你必须做的是在model.fit加载从model_checkpoint_callback保存的权重之后

model = model.load_weights(SAVE_DIR)` # and then .evaluate
pred_results = model.evaluate(validation_generator)
print(pred_results)

您是否尝试在validation_datagen.flow_from_directory()中设置shuffle = False 这有点误导,但默认情况下.flow_from_directory()方法会随机播放,这在生成验证数据集时会出现问题。 当您尝试调用.predict时,这会改变您的验证数据。 而在您的训练循环中, .fit方法隐式地不会打乱验证集。

我认为这是问题的原因是因为您声明在验证集上调用.predict()可以使您获得 ~.5 的准确度,并且您还在运行二进制分类(具有二进制交叉熵损失的 sigmoid 输出),其中如果您(错误地)改组您的验证数据,则非常有意义。 平衡数据集上未经训练的二元分类器通常会达到 50% 左右的准确率(0.5 表示 0,0.5 表示 1),因为它只是在那个时候进行猜测。

资料来源:我之前已经建立并训练了很多图像分类模型,这种情况经常发生在我身上。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM