TensorFlow模型的model.evaluate和model.predict结果非常不同。

10

我正在构建一个用于二进制图像分类的简单CNN模型,从model.evaluate()获得的AUC远高于通过model.predict() + roc_auc_score()获得的AUC

整个笔记本在这里

编译模型和model.fit()的输出:

model.compile(loss='binary_crossentropy',
              optimizer=RMSprop(lr=0.001),
              metrics=['AUC'])

history = model.fit(
      train_generator,
      steps_per_epoch=8,  
      epochs=5,
      verbose=1)

第1个Epoch/共5个Epoch 8/8 [==============================] - 21秒 3秒/步 - 损失: 6.7315 - auc: 0.5143

第2个Epoch/共5个Epoch 8/8 [==============================] - 15秒 2秒/步 - 损失: 0.6626 - auc: 0.6983

第3个Epoch/共5个Epoch 8/8 [==============================] - 18秒 2秒/步 - 损失: 0.4296 - auc: 0.8777

第4个Epoch/共5个Epoch 8/8 [==============================] - 14秒 2秒/步 - 损失: 0.2330 - auc: 0.9606

第5个Epoch/共5个Epoch 8/8 [==============================] - 18秒 2秒/步 - 损失: 0.1985 - auc: 0.9767

然后model.evaluate()返回类似的结果:

model.evaluate(train_generator)

9/9 [==============================] - 10s 1s/step - 损失: 0.3056 - AUC: 0.9956

但是直接从model.predict()方法计算出的AUC值要低两倍:

from sklearn import metrics

x = model.predict(train_generator)
metrics.roc_auc_score(train_generator.labels, x)

0.5006148007590132


我读了几篇关于类似问题的帖子(比如这个这个这个,还有在github上的广泛讨论),但它们描述的原因与我的情况无关:

  • 为多类分类任务使用binary_crossenthropy(不是我的情况)
  • 由于使用批处理和整个数据集之间的差异而导致评估和预测之间的差异(不应该导致像我这样剧烈的下降)
  • 使用批量归一化和正则化(不是我的情况,并且也不应该导致如此大的下降)

非常感谢任何建议。谢谢!


编辑! 解决方案 我在这里找到了解决方案,我只需要调用

train_generator.reset()

在 model.predict 之前,还需要在 flow_from_directory() 函数中设置 shuffle = False。差异的原因是生成器从不同位置开始输出批次,因此标签和预测结果不匹配,因为它们涉及不同的对象。因此,问题不在于 evaluate 或 predict 方法,而在于生成器。


编辑2 如果使用 flow_from_directory() 创建生成器,则使用 train_generator.reset() 不方便,因为它需要在 flow_from_directory 中设置 shuffle = False,但这会在训练期间创建包含单个类别的批次,从而影响学习。因此,在运行 predict 之前我最终重新定义了 train_generator。


在评估或预测模型时,不能使用训练集。应该使用一些未用于训练的图像作为测试集。我遇到了同样的问题,在使用 evaluate() 和 predict() 函数计算时,得到的结果相差很大,其中 predict() 得到的值要低得多。 - Nguai al
你必须提供自己的解决方案来标记问题已解决。这样问题就不会保持开放状态。 - J Agustin Barrachina
1个回答

1

tensorflow.keras的AUC通过黎曼和逼近计算,这与scikit-learn的实现不同。

如果您想使用tensorflow.keras查找AUC,请尝试以下操作:

import tensorflow as tf

m = tf.keras.metrics.AUC()

m.update_state(train_generator.labels, x) # assuming both have shape (N,)

r = m.result().numpy()

print(r)

感谢您的建议!不幸的是,这并没有帮助 - 使用您的解决方案得到的结果与model.predict非常相似,并且远低于model.evaluate(请参见[此处](https://github.com/pro100olga/dlaicourse/blob/master/evaluate_predict.ipynb)文件末尾)。我还认为,在不同实现中计算的差异可能会导致细微的差异,但不会是0.9与0.5的区别。 - Olga Makarova
你能够将train_generator.labels和x的形状加起来吗?同时也能给出前几个值吗? - Zabir Al Nazi
当然,请查看这里(同样在文件末尾)。 - Olga Makarova

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接