我一直在尝试弄清楚GridSearchCV和cross_val_score是如何工作的。
我进行了一系列验证实验来寻找可能的结果,但仍然不明白自己哪里做错了。
为了简化,我以最简单的方式使用GridSearchCV,并尝试验证和理解发生了什么:
具体如下:
import pandas as pdimport numpy as npfrom sklearn.preprocessing import StandardScaler, RobustScaler, QuantileTransformerfrom sklearn.feature_selection import SelectKBest, f_regression, RFECVfrom sklearn.decomposition import PCAfrom sklearn.linear_model import RidgeCV,Ridge, LinearRegressionfrom sklearn.pipeline import Pipeline, make_pipelinefrom sklearn.model_selection import GridSearchCV,KFold,TimeSeriesSplit,PredefinedSplit,cross_val_scorefrom sklearn.metrics import mean_squared_error,make_scorer,r2_score,mean_absolute_error,mean_squared_errorfrom math import sqrt
我创建了一个交叉验证对象(用于GridSearchCV和cross_val_score),以及用于管道和简单线性回归的训练/测试数据集。我已经检查过这两个数据集是相同的:
train_indices = np.full((15,), -1, dtype=int)test_indices = np.full((6,), 0, dtype=int)test_fold = np.append(train_indices, test_indices)kf = PredefinedSplit(test_fold)for train_index, test_index in kf.split(X): print('TRAIN:', train_index, 'TEST:', test_index) X_train_kf = X[train_index] X_test_kf = X[test_index]train_data = list(range(0,15))test_data = list(range(15,21))X_train, y_train=X[train_data,:],y[train_data]X_test, y_test=X[test_data,:],y[test_data]
这是我所做的:
实例化一个简单的线性模型,并使用手动设置的数据集:
lr=LinearRegression()lm=lr.fit(X,y)lmscore_train=lm.score(X_train,y_train)
结果:
r2=0.4686662249071524
lmscore_test=lm.score(X_test,y_test)
结果:
r2 0.6264021467338086
现在我尝试使用管道做同样的事情:
pipe_steps = ([('est', LinearRegression())])pipe=Pipeline(pipe_steps)p=pipe.fit(X,y)pscore_train=p.score(X_train,y_train)
结果:
r2=0.4686662249071524
pscore_test=p.score(X_test,y_test)
结果:
r2 0.6264021467338086
线性回归和管道的结果完全匹配
现在我尝试使用预定义的分割kf来使用cross_val_score做同样的事情
cv_scores = cross_val_score(lm, X, y, cv=kf)
结果:
r2 = -1.234474757883921470e+01 # ?!?! (这应该是测试分数)
现在让我们尝试GridSearchCV
scoring = {'r_squared':'r2'}grid_parameters = [{}] gridsearch=GridSearchCV(p, grid_parameters, verbose=3,cv=kf,scoring=scoring,return_train_score='true',refit='r_squared')gs=gridsearch.fit(X,y)results=gs.cv_results_
从cv_results_中我再次得到
mean_test_r_squared# resultr2 -1.234474757883921292e+01
所以cross_val_score和GridSearchCV最终是匹配的,但分数完全不对,与预期的不同。
请问您能帮我解开这个谜团吗?
回答:
cross_val_score和GridSearchCV首先会分割数据,仅在训练数据上训练模型,然后在测试数据上评分。
您是在完整数据上训练,然后在测试数据上评分。因此,您的结果与cross_val_score
不匹配。
不要这样做:
lm=lr.fit(X,y)
试试这样:
lm=lr.fit(X_train, y_train)
管道也是如此:
不要这样做p=pipe.fit(X,y)
,而是这样做:
p=pipe.fit(X_train, y_train)
您可以查看我的回答以获取更多描述: