我正试图使用监督机器学习,根据作物(如土豆(的长度和宽度测量值来预测作物的重量。在拟合特定模型(例如线性回归(之前,我想根据数据集中特定作物品种的频率对我的特征进行分层采样。例如,如果我将数据划分为5个分区(即,我使用交叉验证(,并且变量1占我观察值的50%,那么每个分区训练集中50%的观察值应该对应于变量1。这是我在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
这对我来说有点奇怪,因为根据sklearn的文档,我们可以在cross_val_express的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_prdict来使代码更加紧凑。有可能吗?
尝试使用StratifiedKFold
而不是StratifiedShuffleSplit
。
不同的是,StratifiedKFold只进行一次洗牌和拆分,因此测试集不会重叠,而StratifiedShuffleSplit在拆分之前每次都进行洗牌,并且它会拆分n_split次,测试集可能重叠,一些数据分区从来都不是测试数据集的一部分,这意味着没有对它们的预测。
您可以在Catbuilts的解释上阅读更多信息