使用model.evaluate()与model.predict()时准确率不一致的问题
问题原因及解决方法
核心原因:样本顺序不匹配
你的代码直接用testing_generator.classes作为真实标签,但如果testing_generator开启了shuffle=True,生成测试样本时会打乱原始顺序。model.evaluate()内部会自动对应每个batch的输入和真实标签,所以结果正确;但手动取classes得到的是未打乱的原始标签顺序,和model.predict()输出的预测结果顺序完全不对应,导致计算出的准确率接近4分类随机猜测的概率(约25%)。
此外还可能存在次要原因:
model.predict()的steps参数未正确设置,导致预测样本数和真实样本数不一致- 测试集generator的类别索引和模型训练时的类别索引不匹配(不过这种情况
evaluate()结果也会错误,概率较低)
解决方法
方法1:关闭测试集的shuffle
修改testing_generator的创建代码,设置shuffle=False,让样本顺序和classes保持一致,再运行手动计算准确率的代码即可得到正确结果:
# 创建testing_generator时添加shuffle=False testing_generator = ImageDataGenerator(...).flow_from_directory( ..., shuffle=False # 关键:测试集不打乱顺序 ) # 再执行原手动计算代码 y_true = testing_generator.classes y_pred_probs = model.predict(testing_generator) y_pred = np.argmax(y_pred_probs, axis=1) accuracy = accuracy_score(y_true, y_pred)
方法2:从generator中按顺序收集真实标签
如果需要保留shuffle=True,可以遍历generator收集每个batch的真实标签,保证和预测结果顺序一致:
y_true = [] # 遍历generator的所有batch for _, batch_y in testing_generator: # 若标签是one-hot编码,转成类别索引 y_true.extend(np.argmax(batch_y, axis=1)) # 若标签本身就是类别索引,直接用y_true.extend(batch_y) # 收集到足够样本后终止循环 if len(y_true) == testing_generator.samples: break y_pred_probs = model.predict(testing_generator) y_pred = np.argmax(y_pred_probs, axis=1) accuracy = accuracy_score(y_true, y_pred)
方法3:直接使用evaluate返回的结果
如果仅需获取测试准确率,直接使用model.evaluate()返回的test_accuracy即可,无需手动计算,避免顺序匹配问题。
内容的提问来源于stack exchange,提问作者Dwi Duta Mahardewantoro
相关产品推荐
相关产品推荐

