二分类图像模型accuracy指标远高于实际表现的原因排查
可能的核心原因:
标签格式与类别索引不匹配
你使用categorical_crossentropy作为损失函数,说明模型期望输入独热编码(one-hot)格式的标签。但test_set.labels大概率是整数格式的标签(如0/1)。model.evaluate会自动适配数据集的标签格式(比如用flow_from_directory且class_mode='categorical'时,数据集会自动生成独热标签),但手动对比时,若直接将模型输出argmax()得到的整数标签,与test_set.labels的整数标签对比,可能出现类别顺序完全错位的情况——比如模型输出的argmax()结果中0对应类别A,而test_set.labels中0对应类别B,此时计算的准确率会直接跌到随机水平。测试集顺序不匹配
如果构建test_set时开启了shuffle=True,model.evaluate会按shuffle后的批次计算准确率,但test_set.labels保存的是原始顺序的标签。手动调用model.predict(test_set)时,预测结果的顺序是shuffle后的图像顺序,和test_set.labels的原始顺序完全对应不上,对比后的准确率自然是随机水平。数据集类别映射错误
若用ImageDataGenerator的flow_from_directory构建测试集,class_indices的实际顺序可能和你预期的不一致。比如你默认类别A对应索引0,但实际class_indices中类别A对应索引1,模型输出的argmax()结果会和你手动对比的test_set.labels(按你的预期索引)完全错位,导致准确率骤降。推理层状态异常(可能性低)
Keras默认在evaluate和predict时会关闭Dropout/SpatialDropout层(设置training=False),但如果模型包含自定义层,或手动修改过层的训练状态,可能导致evaluate和predict时模型行为不一致,进而出现准确率差异。不过这种情况在标准Keras层中极少出现。
快速验证步骤
- 检查标签格式:打印
test_set.labels的前5个值,再打印next(iter(test_set))[1](测试集一个batch的标签),确认标签是否为独热编码格式。 - 关闭测试集shuffle:将
test_set的shuffle设为False,重新运行evaluate和手动对比,查看准确率是否一致。 - 核对类别映射:若用
flow_from_directory生成数据集,打印test_set.class_indices,确认模型输出的argmax()结果对应的类别是否与标签匹配。 - 统一计算逻辑:用
np.mean(np.argmax(model.predict(test_set), axis=1) == np.argmax(test_set.labels, axis=1))(标签为独热时)或np.mean(np.argmax(model.predict(test_set), axis=1) == test_set.labels)(标签为整数且顺序正确时)计算准确率,对比与model.evaluate的结果是否一致。
内容的提问来源于stack exchange,提问作者eduard

