在Gridsearchcv sklearn中使用不同的评分指标时出现问题

问题描述

我正在做弹性网回归,并尝试使用gridsearchcv估计最佳超周边。但是,当我将gridsearchcv中的评分从认值r2更改为mean_squared_error时,gridsearchcv将每个要素的要素系数设为0。我不知道为什么会这样。

这是代码

param={
'elastic__alpha':np.linspace(.1,1,15),'elastic__l1_ratio':np.linspace(0,30)
}
pipe=Pipeline([('scalar',StandardScaler()),('elastic',ElasticNet(max_iter=10000))])
search=gridsearchcv(pipe,param_grid=param,cv=4,scoring=make_scorer(mean_squared_error))
search.fit(train_x,train_y)

解决方法

这个问题是由于函数 make_scorer 的错误使用而导致的。默认情况下,它假设得分越高越好,如果您查看参数 greater_is_better 下的 help page :

greater_is_better bool,default=True score_func 是否为分数 函数(默认),表示高是好的,或损失函数,表示 低是好的。在后一种情况下,scorer 对象将标志翻转 score_func 的结果。

如果您使用的是 r2,则默认有效。如果你使用均方误差,你想最小化误差,你需要设置greater_is_better = False

我们可以使用一个示例数据集来证明这一点:

from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.linear_model import ElasticNet
from sklearn.model_selection import GridSearchCV,train_test_split
from sklearn.metrics import make_scorer,mean_squared_error
from sklearn import datasets

data = datasets.load_boston()
X = data['data']
y = data['target']

然后设置一些简单的参数:

param={
'elastic__alpha':np.linspace(0.2,0.8,2),'elastic__l1_ratio':np.linspace(0.2,2)
}

pipe=Pipeline([('scalar',StandardScaler()),('elastic',ElasticNet(max_iter=10000))])
search=GridSearchCV(pipe,param_grid=param,cv=4,scoring="r2")
search.fit(X_train,y_train)

search.best_params_
{'elastic__alpha': 0.2,'elastic__l1_ratio': 0.2}

运行您的函数:

pipe=Pipeline([('scalar',scoring=make_scorer(mean_squared_error))
search.fit(X_train,y_train)

search.best_params_
{'elastic__alpha': 0.8,'elastic__l1_ratio': 0.2}

最佳参数不同,可以看到选择了均方误差最大的参数:

res = pd.DataFrame(search.cv_results_['params'])
res['score'] = search.cv_results_['mean_test_score']
res.sort_values('score',ascending=False)

elastic__alpha  elastic__l1_ratio   score
2   0.8 0.2 30.348081
3   0.8 0.8 29.191112
1   0.2 0.8 25.891039
0   0.2 0.2 25.733661

如果我们执行 greater_is_better=False,结果是有意义的:

pipe=Pipeline([('scalar',scoring=make_scorer(mean_squared_error,greater_is_better=False))
search.fit(X_train,y_train)

search.best_params_

{'elastic__alpha': 0.2,'elastic__l1_ratio': 0.2}

res = pd.DataFrame(search.cv_results_['params'])
res['score'] = search.cv_results_['mean_test_score']
res.sort_values('score',ascending=False)

    elastic__alpha  elastic__l1_ratio   score
0   0.2 0.2 -25.733661
1   0.2 0.8 -25.891039
3   0.8 0.8 -29.191112
2   0.8 0.2 -30.348081

因此,他们提供一个名为“neg_mean_squared_error”的选项是有充分理由的,如果我们使用它,您会看到您得到相同的结果。