Keras evaluate_generator与sklearn accuracy_score结果不一致问题排查
你这里的核心问题是把shuffle参数写成了字符串'False',而不是布尔值False,这直接导致了验证集数据被意外打乱,让y_pred和y_test的样本顺序完全不匹配,才出现了模型评估精度正常,但手动计算精度极低的矛盾结果。
为什么会这样?
在Python中,非空字符串都会被视为True,所以Keras的flow_from_directory会把shuffle='False'当成shuffle=True来处理——你的验证集其实一直在被随机打乱。而你获取y_test时用的是validation_generator2.classes[validation_generator2.index_array],这里的index_array是打乱后的索引,但模型预测的y_pred是另一个打乱后的批次顺序,两者根本对应不上。
具体修复步骤
1. 修正shuffle参数为布尔值
把所有出现shuffle='False'的地方改成shuffle=False,这是最关键的一步。
2. 复用同一个验证集生成器,避免重复创建
不需要创建两个validation_generator,复用同一个即可,同时要注意在evaluate_generator之后重置生成器指针——因为evaluate_generator会遍历完整个验证集,生成器的指针会停在末尾,如果直接调用predict_generator,会从指针位置开始(也就是没有数据可预测),所以必须用reset()让指针回到开头。
3. 简化y_test的获取
当shuffle=False时,validation_generator.classes本身就是按原始顺序排列的真实标签,不需要额外用index_array索引。
修正后的关键代码示例
# 验证集生成器:修正shuffle为布尔值False validation_generator = train_datagen.flow_from_directory( train_data_dir, target_size=(img_height, img_width), batch_size=batch_size, class_mode='categorical', subset='validation', shuffle=False) # 先评估模型 loss, acc = model.evaluate_generator(validation_generator, steps=math.ceil(validation_generator.samples / batch_size), verbose=0, workers=1) # 重置生成器指针,确保predict从开头开始 validation_generator.reset() # 再做预测 y_pred = model.predict_generator(validation_generator, steps=math.ceil(validation_generator.samples / batch_size), verbose=0, workers=1) y_pred = np.argmax(y_pred, axis=-1) # 获取正确顺序的真实标签 y_test = validation_generator.classes
额外建议
训练代码里的validation_generator也建议把shuffle改成False——虽然这不会影响训练结果,但能保证训练过程中验证集的评估顺序和后续手动验证的顺序一致,减少混乱。
修改后再运行accuracy_score(y_test, y_pred),应该就能得到和模型评估一致的精度结果,混淆矩阵也会恢复正常了。
内容的提问来源于stack exchange,提问作者Kasra

