在 cross_val_predict 中使用 StratifiedShuffleSplit (sklearn)

use StratifiedShuffleSplit in cross_val_predict (sklearn)

我正在尝试使用受监督的机器学习来根据作物(例如土豆)各自的长度和宽度测量值来预测其重量。在拟合特定模型(例如线性回归)之前,我想根据数据集中特定作物品种的频率对我的特征进行分层抽样。例如,如果我将数据分成 5 个分区(即我使用交叉验证)并且 variety1 占我观测值的 50%,则每个分区训练集中 50% 的观测值应对应于 variety1。这是我在 Python 中使用 sklearn(版本 0.23)尝试过的代码:

import numpy as np
import pandas as pd
from sklearn.model_selection import StratifiedShuffleSplit
from sklearn.model_selection import cross_val_predict
from sklearn.linear_model import LinearRegression

# build pd.DataFrame
varieties = np.concatenate([np.repeat("variety1", 10), 
                            np.repeat("variety2", 30), 
                            np.repeat("variety3", 60)])
columns = {"variety": varieties,
           "length": np.random.randint(30, 70, size=100),
           "width": np.random.randint(40, 50, size=100),
           "weight": np.random.random(100)*100 + 50}

df = pd.DataFrame(columns)

# stratified sampling
kf = StratifiedShuffleSplit(n_splits=5, test_size=0.2)

# fit model based on a cv splitter
lm = LinearRegression()
X = df.loc[:,"length":"width"]
y = df["weight"]
y_pred = cross_val_predict(lm, X, y, cv=kf.split(X, df["variety"]))

但是,当我 运行 这段代码时,出现以下错误:

ValueError: cross_val_predict only works for partitions

这让我有点惊讶,因为根据 documentation of sklearn 我们可以在 cross_val_predict 的 cv 参数中使用拆分器。我知道我可以使用 for 循环来完成我想要的:

kf = StratifiedShuffleSplit(n_splits=5, test_size=0.2)
X = df.loc[:,"length":"width"]
y = df["weight"]
y_pred = np.zeros(y.size)
for train_idx, test_idx in kf.split(X, df["variety"]):
    #get subsets of variables from CV
    X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]
    y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]
    
    #fit model
    lm.fit(X_train, y_train)
    pred_vals = lm.predict(X_test)
    
    #store predicted values
    y_pred[test_idx] = pred_vals 

不过,我更愿意使用 cross_val_predict 来使代码更紧凑一些。可能吗?

尝试使用 StratifiedKFold 而不是 StratifiedShuffleSplit

不同的是StratifiedKFold只是shuffle和split一次,所以测试集不会重叠,而StratifiedShuffleSplit在每次shuffle之前都是shuffle,分裂了n_splits次,测试集可以重叠,部分数据分区从来都不是测试数据集的一部分,这意味着没有针对它们的预测。

您可以在

阅读更多内容