You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keras二分类模型结合Scaler与特征选择时在线预测结果异常

问题:实时预测结果异常(Keras二分类模型)

我搭建了一个可定时(每小时/每日)用新数据训练Keras二分类(0或1)模型的应用,训练和测试环节表现都符合预期。训练时会测试不同特征,并用MinMaxScaler对数据做缩放(部分数值为负)。

但用单条实时数据预测时,结果极不真实——大多在0.9987到1之间,和实际情况不符。这个预测结果代表样本接近"1"的程度,持续高数值会触发告警。

在线预测代码

current_df是包含1行实时数据及列名的pandas DataFrame,需选择对应特征(训练时采用动态特征选择,每次训练的模型对应特征可能不同,特征列表从数据库加载):

# Convert literal str to list
features = ast.literal_eval(features) 

然后在DataFrame中筛选所需特征:

# Select the features
selected_df = current_df[features]

提取数据为列表:

# Get the values of the df
 current_list = selected_df.values.tolist()[0]

进行第一次重塑:

# Reshape to allow scaling and predicting
 current_list = np.reshape(current_list, (-1, 1))

若此处调用transform而非fit_transform,会报错:This MinMaxScaler instance is not fitted yet. Call 'fit' with appropriate arguments before using this estimator.

再次重塑:

# Reshape to be able to scale
current_list = np.reshape(current_list, (1, -1))

加载Keras模型并预测:

# Loads the model from the local folder
reconstructed_model = keras.models.load_model(model_location)

prediction = reconstructed_model.predict(current_list)
prediction = prediction.flat[0]

补充信息

训练时的数据缩放采用fit_transform和transform(使用MinMaxScaler,也可替换为Standard Scaler):

X_train = pd.DataFrame(scaler.fit_transform(X_train), columns=X_train.columns, index=X_train.index)
X_test = pd.DataFrame(scaler.transform(X_test), columns=X_test.columns, index=X_test.index)

训练流程如下(模型结构未展示):

# Compile the model
model.compile(optimizer=optimizer, 
                loss=loss, 
                metrics=['binary_accuracy'])

# build the model
model.fit(X_train, y_train, epochs=epochs, verbose=0)

# Evaluate using Keras built-in function
scores = model.evaluate(X_test, y_test, verbose=0)
testing_accuracy = scores[1]

# create model with sklearn KerasClassifier for evaluation
eval_model = KerasClassifier(model=model, epochs=epochs, batch_size=10, verbose=0)

# Evaluate model using RepeatedStratifiedKFold
accuracy = ML.evaluate_model_KFold(eval_model, X_test, y_test)

# Predict testing data
pred_test= model.predict(X_test, verbose=0)
pred_test = pred_test.flatten()

# extract the predicted class labels
y_predicted_test = np.where(pred_test > 0.5, 1, 0)

特征选择方面,每次训练的特征不固定——我会使用SelectKBest(选10或15个特征)或RFECV,选择准确率最高的训练模型,因此不同模型对应的特征可能不同。


问题分析与修正方案

1. 核心错误:未复用训练阶段的预处理组件

预测时你完全没有使用训练时拟合好的Scaler,也没有保存/加载特征选择器,直接用原始数据喂给模型,而模型是基于缩放后的数据训练的,这必然导致预测结果异常。报错提示Scaler未拟合,是因为你用了全新的Scaler实例,而非训练时保存的那个。

2. 关键流程错误:特征选择与缩放的顺序

训练时必须严格遵循:原始数据 → 特征选择(fit+transform)→ Scaler拟合+缩放 → 模型训练。如果先缩放再做特征选择,会导致Scaler的拟合范围包含被丢弃的特征,后续预测时的缩放逻辑和训练阶段不一致。

同时,每次训练后必须把特征列表、特征选择器、Scaler、模型作为一个整体保存,因为不同模型对应不同的特征集合和缩放参数,不能只保存模型。

3. 修正后的代码示例

训练阶段:保存所有必要组件

import joblib

# 假设训练时的特征选择器为selector,Scaler为scaler,模型为model
# 保存特征选择器
joblib.dump(selector, f"{model_location}_selector.pkl")
# 保存Scaler
joblib.dump(scaler, f"{model_location}_scaler.pkl")
# 保存模型
model.save(model_location)
# 同时将本次训练的特征列表存入数据库

预测阶段:复用训练时的预处理逻辑

import ast
import pandas as pd
import joblib
import keras

# 加载特征列表、特征选择器、Scaler、模型
features = ast.literal_eval(features)
selector = joblib.load(f"{model_location}_selector.pkl")
scaler = joblib.load(f"{model_location}_scaler.pkl")
reconstructed_model = keras.models.load_model(model_location)

# 筛选特征
selected_df = current_df[features]

# 执行特征选择转换(和训练顺序一致)
selected_data = selector.transform(selected_df)

# 用训练好的Scaler做缩放(只能用transform,绝对不能fit)
scaled_data = scaler.transform(selected_data)

# 预测
prediction = reconstructed_model.predict(scaled_data, verbose=0)
prediction = prediction.flat[0]

额外注意事项

  • 绝对不能在预测阶段对新数据执行fit或fit_transform,必须复用训练时拟合好的特征选择器和Scaler
  • 每次训练的特征集合、预处理组件、模型必须一一对应,避免出现"用A模型的特征喂给B模型"的情况

内容的提问来源于stack exchange,提问作者galgo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 10:40:18