KERAS模型在训练时恢复高验证精度,但是评估时准确性很低

发布于 2025-02-10 18:31:17 字数 3212 浏览 2 评论 0原文

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

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个时期训练的网络的输出:

6/6 [=================================================== binary_accuracy:0.8461

但是,当我使用model.save()tf.keras.models.save_model()> tf.keras.models()时,我将模型保存并加载模型时。输出成为这样的事情:

6/6 [====================================================== binary_accuracy:0.5028 [0.6935192346572876,0.5027709603309631]

model.dredict.predict(validation_generator) is的输出

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


我到目前为止尝试过的

  1. 全球张量子和Numpy种子。
  2. 在另一个 so so post 中,发现了类似的问题。并减少动量 Mobilenet batchnoralization层的参数一一。
for layer in model.layers[0].layers:
    if type(layer) is tf.keras.layers.BatchNormalization:
        layer.momentum = 0.9

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

I am trying to train a simple MobileNetV3Small under keras.applications as shown below

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)

When I train the model I got validation accuracy around 0.94. But when I call model.evaluate on the exact same validation data, the accuracy becomes 0.48. When I call model.predict with any data it outputs constant value 0.51...

There is nothing wrong with learning rate, optimizer or metrics. What could be wrong here?


EDIT:

After training when I run

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

it gives me the output for 1 epoch trained network:

6/6 [==============================] - 1s 100ms/step - loss: 0.6935 -
binary_accuracy: 0.8461

However, when I save and load the model with either model.save() or tf.keras.models.save_model(). The output becomes something like this:

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

and output of the model.predict(validation_generator) is:

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


What I've tried so far:

  1. Used tf.keras.utils.image_dataset_from_directory() instead of ImageDataGenerator
  2. Fixed tensorflow and numpy seeds globally.
  3. Found similar problem in another SO post, and decreased momentum parameter of MobileNet BatchNormalization layers one by one.
for layer in model.layers[0].layers:
    if type(layer) is tf.keras.layers.BatchNormalization:
        layer.momentum = 0.9

First two moves do not have an effect, the after applying the third step, I get no longer same predictions for any input. However, evaluate() and predict() still have different accuracy values.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

芯好空 2025-02-17 18:31:17

您是否尝试过设置shuffle = false in validation_datagen.flow_from_directory()?这有点具有误导性,但是.flow_from_directory()方法默认情况下会随机混乱,在生成验证数据集时,这是有问题的。当您尝试调用.predict时,这将使您的验证数据改组。尽管在您的培训循环中,.fit方法隐含地不会使验证集进行洗牌。

我之所以认为这是问题,是因为您在验证集网络上呼叫.predict()二进制交叉熵损失),如果您(错误地)将验证数据改组,这是非常有意义的。平衡数据集上未经训练的二进制分类器通常会达到50%的精度约为50%(0.5 f in 0,为1),因为这只是在猜测这一点。

Source :我以前构建并培训了许多图像分类模型,这发生在我身上。

Have you tried setting shuffle = False in validation_datagen.flow_from_directory()? It's a little misleading but the .flow_from_directory() method shuffles by default, which is problematic when generating your validation dataset. This is shuffling your validation data when you try to call .predict. Whereas in your training loop, the .fit method implicitly DOESN'T shuffle the validation set.

The reason I think this is the issue, is because you state that calling .predict() on the validation set nets you ~.5 accuracy, and you're also running a binary classification (sigmoid output with binary cross entropy loss), which makes perfect sense IF you're (mistakenly) shuffling your validation data. Untrained binary classifiers on balanced datasets will usually do around 50% accuracy (.5 for 0, .5 for 1) since it's just guessing at that point.

Source: I've built and trained a lot of image classification models before, and this happened to me a lot.

月下客 2025-02-17 18:31:17

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

It might be worth trying model.save_weights('directory') and then rebuilding your model (i think here that is re-running the base_model = ... code) through model.load_weights('directory'). That is what i do in my own models, and when i then do that, the accuracy/loss stay the exact same before and after saving and loading.

折戟 2025-02-17 18:31:17

如果您运行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)

If you run pred_results = model.evaluate(validation_generator)
after you fit the model, the loaded weights at this moment are the ones updated on last training epoch.
What you have to do is after model.fit is loading the weights saved from
model_checkpoint_callback with something like

model = model.load_weights(SAVE_DIR)` # and then .evaluate
pred_results = model.evaluate(validation_generator)
print(pred_results)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文