Keras中model.evaluate_generator与实际准确率偏差过大问题咨询
这种准确率跳崖式的差异我碰到过好多次,大概率是几个细节没处理到位,咱们一步步拆解排查:
最可能的原因:生成器的状态没重置
Keras的flow_from_directory生成的是有状态的迭代器,每次调用evaluate_generator或者predict之后,它的指针会停在最后一个处理的batch位置。如果你在调用predict_classes前没有重置生成器,它会从上次中断的地方继续处理,导致你只统计了测试集的一部分样本,准确率自然就错得离谱。
解决方法:在每次使用生成器前,一定要调用reset():
test_generator.reset() # 重置到测试集开头 eval_loss, eval_acc = model.evaluate_generator(test_generator, steps=np.ceil(test_generator.samples / test_generator.batch_size)) test_generator.reset() # 再次重置,确保predict从开头开始 preds = model.predict_classes(test_generator, steps=np.ceil(test_generator.samples / test_generator.batch_size))
第二个坑:predict时没处理完所有样本
如果你的测试集样本数不能被batch_size整除,生成器最后一个batch的样本数会小于batch_size。如果调用predict_classes时没有指定steps参数,Keras可能只会处理整数个batch,漏掉最后几个样本,导致统计的样本数不对。
正确做法:用np.ceil(test_generator.samples / test_generator.batch_size)来计算需要处理的steps,确保覆盖所有样本:
import numpy as np steps = np.ceil(test_generator.samples / test_generator.batch_size) preds = model.predict_classes(test_generator, steps=steps)
第三个可能:标签对应关系搞反了
flow_from_directory会按文件夹的字母顺序给类别分配编码(比如文件夹cat对应0,dog对应1),你可以通过test_generator.class_indices查看这个映射关系。如果手动统计时把真实标签和预测标签的对应关系搞反了,比如把真实的cat当成1,预测的0当成错误,那准确率肯定不对。
正确的统计方式:直接用生成器自带的classes属性获取所有真实标签,然后和预测结果对比:
true_labels = test_generator.classes predict_acc = np.mean(preds == true_labels) print(f"手动统计准确率:{predict_acc}")
额外提醒:TensorFlow 2.x的兼容问题
如果用的是TF2.x,predict_classes已经被弃用了,官方推荐用predict后取argmax来得到类别:
test_generator.reset() pred_probs = model.predict(test_generator, steps=steps) preds = np.argmax(pred_probs, axis=1) # 多分类场景
最后验证:检查预处理是否一致
确保你手动预测时的图片预处理和test_datagen的设置完全一致,比如rescale=1./255、归一化、裁剪等操作。如果手动加载图片时没做同样的预处理,模型的预测结果会失真,准确率自然不匹配。
内容的提问来源于stack exchange,提问作者Sugrue

