我正在构建一个用于二进制图像分类的简单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。