我需要为(X_test,y_test)数据的每个拆分显式获取交叉验证统计信息。
因此,我尝试这样做:
kf = KFold(n_splits=n_splits) X_train_tmp = [] y_train_tmp = [] X_test_tmp = [] y_test_tmp = [] mae_train_cv_list = [] mae_test_cv_list = [] for train_index, test_index in kf.split(X_train): for i in range(len(train_index)): X_train_tmp.append(X_train[train_index[i]]) y_train_tmp.append(y_train[train_index[i]]) for i in range(len(test_index)): X_test_tmp.append(X_train[test_index[i]]) y_test_tmp.append(y_train[test_index[i]]) model.fit(X_train_tmp, y_train_tmp) # FIT the model = SVR, NN, etc. mae_train_cv_list.append( mean_absolute_error(y_train_tmp, model.predict(X_train_tmp)) # MAE of the train part of the KFold. mae_test_cv_list.append( mean_absolute_error(y_test_tmp, model.predict(X_test_tmp)) ) # MAE of the test part of the KFold. X_train_tmp = [] y_train_tmp = [] X_test_tmp = [] y_test_tmp = []
是否是通过使用例如KFold来获得每个交叉验证拆分的平均绝对误差(MAE)的正确方法?
您的方法存在一些问题。
首先,您当然不必在培训和验证列表(即您的2个内部循环)中 一个接一个地手动 添加数据for。简单的索引就可以完成工作。
for
此外,我们通常从不计算和报告训练CV折叠的错误-仅验证折叠的错误。
请记住这些,并将术语切换为“验证”而不是“测试”,这是一个使用波士顿数据的可复制示例,应直接进行调整以适应您的情况:
from sklearn.model_selection import KFold from sklearn.datasets import load_boston from sklearn.metrics import mean_absolute_error from sklearn.tree import DecisionTreeRegressor X, y = load_boston(return_X_y=True) n_splits = 5 kf = KFold(n_splits=n_splits, shuffle=True) model = DecisionTreeRegressor(criterion='mae') cv_mae = [] for train_index, val_index in kf.split(X): model.fit(X[train_index], y[train_index]) pred = model.predict(X[val_index]) err = mean_absolute_error(y[val_index], pred) cv_mae.append(err)
之后,您cv_mae应该是这样的(由于简历的随机性质,细节会有所不同):
cv_mae
[3.5294117647058827, 3.3039603960396042, 3.5306930693069307, 2.6910891089108913, 3.0663366336633664]
当然,所有这些显式的东西并不是真正必需的。您可以使用轻松得多cross_val_score。不过有一个小问题:
cross_val_score
from sklearn.model_selection import cross_val_score cv_mae2 =cross_val_score(model, X, y, cv=n_splits, scoring="neg_mean_absolute_error") cv_mae2 # result array([-2.94019608, -3.71980198, -4.92673267, -4.5990099 , -4.22574257])
除了不是真正的问题的负号之外,您还会注意到结果的方差看起来比cv_mae上面的要大得多;原因是我们没有对数据进行 洗牌 。不幸的是,cross_val_score没有提供改组选项,因此我们必须使用手动进行shuffle。因此,我们的最终代码应为:
shuffle
from sklearn.model_selection import cross_val_score from sklearn.utils import shuffle X_s, y_s =shuffle(X, y) cv_mae3 =cross_val_score(model, X_s, y_s, cv=n_splits, scoring="neg_mean_absolute_error") cv_mae3 # result: array([-3.24117647, -3.57029703, -3.10891089, -3.45940594, -2.78316832])
褶皱之间的差异明显较小,并且更接近我们的初始cv_mae…