如何使用sklearn.preprocessing对river流对象做分位数变换与归一化
修复方案
报错根源
- 类型不兼容:
river的iter_pandas迭代返回的单条样本是字典格式,而 Sklearn 的QuantileTransformer要求输入为二维数值类数组结构,直接传入字典会触发类型转换失败。 - 特征类型错误:样本中的
course_no是字符串类型的分类特征,分位数变换仅支持数值特征输入,未预处理直接传入会报错。 - 逻辑错误:
- 循环内每次调用
fit_transform相当于用单样本重新拟合变换器,会完全丢失历史流数据的统计信息,不符合流式处理逻辑。 - 变换后的新特征没有传入模型,原代码仍使用原始未变换特征训练预测。
- 循环内每次调用
修复步骤
- 先对分类特征做数值编码,转换为模型和预处理工具支持的数值格式。
- 固定特征顺序,保证字典转数组的过程中特征顺序一致,避免特征错位。
- 使用 Sklearn 预处理接口的
partial_fit方法做增量拟合,适配流式数据的处理需求。 - 将变换后的数组转回字典格式,适配
river模型的输入要求。 - 把变换后的新特征传入模型做预测和训练。
完整可运行代码
import pandas as pd import numpy as np from river.stream import iter_pandas from river import metrics from river import ensemble from sklearn.preprocessing import QuantileTransformer # 构造数据集 students=pd.DataFrame() students['r_no']=[1,2,3,4,5] students['course_no']=['CS_123','CS_456','CS_890','CS_678','CS_123'] students['pass']=[1,1,0,0,1] x_students=students.drop(['pass'],axis=1) # 对分类特征做独热编码,转成数值特征 x_students = pd.get_dummies(x_students, columns=['course_no']) y_students=students['pass'] # 固定特征顺序,保证后续字典转数组的一致性 feature_order = x_students.columns.tolist() c1 = ensemble.AdaptiveRandomForestClassifier(split_confidence=0.01,tie_threshold=0.07, seed=123) c2 = ensemble.AdaptiveRandomForestClassifier(split_confidence=0.01,tie_threshold=0.07, seed=123) trans_st1 = QuantileTransformer(n_quantiles=3, random_state=123) trans_st2 = QuantileTransformer(n_quantiles=3, output_distribution='normal', random_state=456) strm_st1=iter_pandas(X=x_students,y=y_students) strm_st2=iter_pandas(X=x_students,y=y_students) metric1 = metrics.Accuracy() metric2 = metrics.Accuracy() y_preds_st1 = [] y_preds_st2 = [] for ((xi1, yi1),(xi2, yi2)) in zip(strm_st1,strm_st2): # 字典转二维数组,适配sklearn预处理接口 arr_xi1 = np.array([[xi1[feat] for feat in feature_order]]) arr_xi2 = np.array([[xi2[feat] for feat in feature_order]]) # 增量拟合+变换,保留历史统计信息 trans_st1.partial_fit(arr_xi1) new_arr_xi1 = trans_st1.transform(arr_xi1) trans_st2.partial_fit(arr_xi2) new_arr_xi2 = trans_st2.transform(arr_xi2) # 数组转回字典,适配river模型输入 new_xi1 = dict(zip(feature_order, new_arr_xi1[0])) new_xi2 = dict(zip(feature_order, new_arr_xi2[0])) # 使用变换后的特征做预测和训练 y_pred1 = c1.predict_one(new_xi1) y_pred2 = c2.predict_one(new_xi2) c1.learn_one(new_xi1, yi1) c2.learn_one(new_xi2, yi2) metric1.update(y_pred=y_pred1, y_true=yi1) metric2.update(y_pred=y_pred2, y_true=yi2) y_preds_st1.append(y_pred1) y_preds_st2.append(y_pred2) print(f"Accuracy for c1: {metric1.get():.4f}") print(f"Accuracy for c2: {metric2.get():.4f}")
内容的提问来源于stack exchange,提问作者Medha Chippa
相关产品推荐
相关产品推荐

