使用相同Keras模型和相同输入预测得到不同结果的原因是什么?
问题描述
我在网上没有找到同类问题,因此选择在此发帖求助。我训练了一个用于将嵌入向量分类到对应类别的模型,结构为简单的三层Dense全连接神经网络。
目前我需要调用训练好的模型执行实时预测,却发现如下异常:将完整的测试dataframe输入模型得到的第i个元素预测结果,与单独将测试集第i个元素输入模型得到的预测结果不一致。为便于理解问题,相关代码如下:
i = 522 y_pred = model.predict(X_test) y_pred_2 = model.predict(X_test.iloc[[i]]) print (f'{np.argmax(y_pred[i])} {np.argmax(y_pred_2)}') # 输出: 8 5
可见模型批量处理整个测试集和单次处理单条样本时的输出存在差异,我使用pandas处理输入数据。
补充信息:y_pred和y_pred_2的输出形状分别为(603, 10)和(1, 10),其中10为本次分类任务的类别总数。
任意选取i对应的两组预测值示例如下:
y_pred[i]: array([1.3353945e-02, 2.8374636e-09, 1.4435661e-08, 3.4135045e-18, 7.7986561e-02, 3.7737598e-03, 2.0284578e-10, 2.7154891e-03, 9.0203673e-01, 1.3346069e-04], dtype=float32) y_pred_2 = array([[1.1702824e-16, 1.6781385e-37, 2.5281618e-33, 0.0000000e+00, 2.3075200e-09, 1.0000000e+00, 9.9125501e-35, 6.2606384e-22, 5.8689110e-14, 2.3486194e-24]], dtype=float32)
解决方案
该问题是深度学习预测场景的高频问题,可按以下优先级排查解决:
- 检查模型推理状态是否正确设置
90%以上的同类问题都是因为Batch Normalization、Dropout这类具备训练/推理双状态的层没有切换到推理模式导致:- 如果你使用TensorFlow/Keras框架,
predict方法默认会切换推理模式,如果你用到了自定义层或者自定义训练循环,需在预测前手动执行model.trainable = False锁定权重和层状态。 - 如果你使用PyTorch框架,必须在预测前执行
model.eval(),否则BatchNorm层会用当前输入批量的均值方差做归一化,全量测试集批量和单条样本的统计值差异极大,直接导致预测结果完全不同。
- 如果你使用TensorFlow/Keras框架,
- 验证输入数据一致性
确认你单独提取的单条样本和全量测试集里的对应样本数值完全一致:- 执行
print(X_test.iloc[i].equals(X_test.iloc[[i]].iloc[0]))验证数值一致性,排除pandas索引错位、数据类型隐式转换的问题。 - 检查预处理逻辑:如果你的标准化/归一化操作是基于输入批量的统计值计算,单条输入时不要用单条数据的统计值做归一化,必须用训练集的全局均值、方差做统一预处理。
- 执行
- 快速定位验证方法
把目标单条样本复制成和测试集相同长度的批量,再执行预测对比结果:import numpy as np # 复制单条样本拼成和X_test形状完全一致的批量 X_repeat = np.repeat(X_test.iloc[[i]].values, repeats=X_test.shape[0], axis=0) y_pred_repeat = model.predict(X_repeat) print(np.argmax(y_pred_repeat[0]))- 如果输出为
5:说明是模型状态问题,按第一条的方法调整推理模式即可。 - 如果输出为
8:说明单条样本提取或者预处理逻辑有问题,按第二条的方法排查输入即可。
- 如果输出为
你当前的预测结果差异达到了数量级差距,可以直接排除浮点计算误差的可能性,按上述步骤排查即可解决问题。
内容的提问来源于stack exchange,提问作者Ramiro
相关产品推荐
相关产品推荐

