如何正确加载StandardScaler至TensorFlow Keras模型
问题描述
加载已保存的StandardScaler与TensorFlow训练模型后,使用完全相同的测试集评估,结果和训练结束后即时评估结果存在显著偏差。
加载StandardScaler的代码:
scaler_load = pickle.load(open(path + save_dir +'std_scaler_1.pkl', 'rb')) X_test_load = scaler_load.transform(X_test_fs) X_test_load
加载模型、编译、评估的代码:
load_model = tf.keras.models.load_model(path + save_dir + 'mlp_model_fs_25_1.h5') load_model.compile(loss=[tf.keras.losses.CategoricalCrossentropy(), tf.keras.losses.MeanSquaredError()], optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001), metrics=['accuracy', tf.keras.metrics.MeanSquaredError()]) load_model.evaluate(X_test_load, y_test)
两次评估结果对比如下:
训练后即时评估结果
54/54 [==============================] - 0s 2ms/step - loss: 0.1129 - accuracy: 0.9662 - mean_squared_error: 0.0294 [0.11291049420833588, 0.9661807417869568, 0.02943398430943489]
重新加载scaler与模型后的评估结果
54/54 [==============================] - 0s 1ms/step - loss: 0.4714 - accuracy: 0.8583 - mean_squared_error: 0.1088 [0.47135162353515625, 0.8583090305328369, 0.10878879576921463]
排查思路
- 校验StandardScaler参数一致性:直接对比训练时拟合完成的scaler的
mean_、var_、scale_、n_features_in_属性,和加载得到的scaler_load对应属性是否完全一致,排除保存了训练中途未拟合完成的scaler、加载错scaler文件的问题;同时确认测试集X_test_fs的特征顺序、维度和训练时送入scaler的特征完全匹配,没有出现特征列错位。 - 校验模型加载逻辑:如果模型包含BatchNormalization、Dropout层,加载后手动调用
compile()会重置这类层的推理状态,丢失训练过程中统计得到的滑动均值、滑动方差参数,直接导致推理精度下降。 - 校验数据一致性:确认两次评估使用的测试集没有经过随机预处理逻辑,测试集数据dtype和训练时送入模型的dtype一致(通常训练时默认使用float32,若自动转为float64可能引发精度偏差)。
- 校验环境版本一致性:确认保存scaler、模型时使用的scikit-learn、TensorFlow版本,和当前加载环境的版本完全匹配,跨大版本加载pickle序列化文件、h5格式模型容易出现参数解析错误。
正确加载实现参考
import pickle import tensorflow as tf import numpy as np # 加载scaler后做参数校验 with open(path + save_dir +'std_scaler_1.pkl', 'rb') as f: scaler_load = pickle.load(f) # 校验特征维度匹配 assert X_test_fs.shape[1] == scaler_load.n_features_in_, "输入特征维度与scaler不匹配" # 转换数据,统一为训练时使用的float32类型 X_test_load = scaler_load.transform(X_test_fs).astype(np.float32) # 加载模型,非必要不手动调用compile load_model = tf.keras.models.load_model(path + save_dir + 'mlp_model_fs_25_1.h5') # 若必须重新编译,先冻结所有层避免BN、Dropout层状态被重置 # load_model.trainable = False # load_model.compile(loss=[tf.keras.losses.CategoricalCrossentropy(), tf.keras.losses.MeanSquaredError()], # optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001), # metrics=['accuracy', tf.keras.metrics.MeanSquaredError()]) # 评估前关闭训练模式,保证BN、Dropout走推理逻辑 load_model.trainable = False eval_results = load_model.evaluate(X_test_load, y_test, verbose=1)
内容的提问来源于stack exchange,提问作者M Muqiit Faturrahman
相关产品推荐
相关产品推荐

