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

如何获取5折交叉验证中经KNNImputer填充后的数据集?

问题:获取KNNImputer结合5折交叉验证后的填充数据集

你现在的情况是手里有个165条样本、49个特征的二分类数据集,存在缺失值,原本用KNNImputer配合5折交叉验证做填充,但不需要模型的准确率,而是要拿到每折填充后的数据集,用来做后续的特征选择和分类任务对吧?

cross_val_score这个工具确实只返回评估指标,不会给你填充后的数据。要拿到每折的填充结果,你需要手动遍历交叉验证的每一轮拆分,自己完成Imputer的拟合和数据转换,这样既能保持交叉验证中“训练集拟合、测试集转换”的无偏逻辑,又能拿到你需要的填充后数据。

下面是具体的实现代码:

import numpy as np
import pandas as pd
from sklearn.impute import KNNImputer
from sklearn.model_selection import RepeatedStratifiedKFold

# 1. 加载并预处理数据
df = pd.read_csv('data.csv', header=None, na_values='?')
data = df.values
# 分离特征和标签(标签在第49列,索引从0开始)
ix = [i for i in range(data.shape[1]) if i != 49]
X, y = data[:, ix], data[:, 49]

# 2. 设置交叉验证拆分器(和你之前用的一致)
cv = RepeatedStratifiedKFold(n_splits=5, n_repeats=1, random_state=1)

# 3. 遍历每折,完成填充并保存结果
fold_filled_data = []
for fold_num, (train_idx, test_idx) in enumerate(cv.split(X, y), start=1):
    # 拆分当前折的训练和测试数据
    X_train, X_test = X[train_idx], X[test_idx]
    y_train, y_test = y[train_idx], y[test_idx]
    
    # 仅在训练集上拟合Imputer(避免数据泄露)
    imputer = KNNImputer(n_neighbors=5, weights='uniform', metric='nan_euclidean')
    imputer.fit(X_train)
    
    # 用拟合好的Imputer填充训练集和测试集
    X_train_filled = imputer.transform(X_train)
    X_test_filled = imputer.transform(X_test)
    
    # 把填充后的特征和标签合并成完整数据集
    train_full = pd.DataFrame(np.hstack((X_train_filled, y_train.reshape(-1, 1))))
    test_full = pd.DataFrame(np.hstack((X_test_filled, y_test.reshape(-1, 1))))
    full_fold = pd.concat([train_full, test_full], axis=0)
    
    # 存储当前折的数据,或者直接保存到文件
    fold_filled_data.append((f"第{fold_num}折", full_fold))
    full_fold.to_csv(f"filled_data_fold_{fold_num}.csv", index=False, header=False)

# 之后你就可以从fold_filled_data里取出每折的数据,进行特征选择了

额外说明

  • 这里严格遵循了交叉验证的原则:只在训练数据上拟合Imputer,再用它填充测试数据,避免了数据泄露(如果直接用全量数据拟合Imputer再填充,会导致测试集的信息提前泄露给模型,影响后续任务的可靠性)。
  • 如果你后续的流程是“填充→特征选择→分类”,其实更推荐把特征选择也加入到Pipeline中,让整个流程在交叉验证里自动运行,这样能彻底避免数据泄露。比如:
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.ensemble import RandomForestClassifier
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score

# 定义完整流程的Pipeline
pipeline = Pipeline(steps=[
    ('imputer', KNNImputer(n_neighbors=5)),
    ('feature_selection', SelectKBest(f_classif, k=20)),  # 选择top20特征
    ('classifier', RandomForestClassifier())
])

# 评估整个流程的准确率
scores = cross_val_score(pipeline, X, y, scoring='accuracy', cv=cv, n_jobs=-1)

但如果确实需要单独拿到填充后的数据来做特征选择,前面的手动循环方法就完全适用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 16:47:53