我需要明确地获得(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
循环);简单的索引就可以了。
此外,我们通常从不计算&报告训练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的随机性,细节会有所不同):
[3.5294117647058827,
3.3039603960396042,
3.5306930693069307,
2.6910891089108913,
3.0663366336633664]
当然,所有这些明确的东西并不是真正必要的;使用CCD_ 3可以更简单地完成这项工作。不过有一个小问题:
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
手动执行此操作。所以我们的最终代码应该是:
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
。。。