首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在GridSearchCV的roc_auc评分中手动复制Sklearn

在GridSearchCV的roc_auc评分中手动复制Sklearn
EN

Stack Overflow用户
提问于 2021-03-05 20:39:53
回答 2查看 382关注 0票数 2

我希望能够在使用SelectKBest时,通过自己执行网格搜索简历来再现学习GridSearchCV的结果。但是,我发现我的代码可以产生不同的结果。下面是一个可重复的例子:

代码语言:javascript
复制
import numpy as np
from sklearn.datasets import make_classification
from sklearn.feature_selection import SelectKBest
from sklearn.model_selection import GridSearchCV, StratifiedKFold
from sklearn.metrics import roc_auc_score
from sklearn.pipeline import Pipeline
from sklearn.svm import SVC
import itertools

r = 1
X, y = make_classification(n_samples = 50, n_features = 20, weights = [3/5], random_state = r)
np.random.seed(r)
X = np.random.rand(X.shape[0], X.shape[1])

K = [1,3,5]
C = [0.1,1]
cv = StratifiedKFold(n_splits = 10)
space = dict()
space['anova__k'] = K
space['svc__C'] = C    
clf = Pipeline([('anova', SelectKBest()), ('svc', SVC(probability = True, random_state = r))])
search = GridSearchCV(clf, space, scoring = 'roc_auc', cv = cv, refit = True, n_jobs = -1)
result = search.fit(X, y)

print('GridSearchCV results:')
print(result.cv_results_['mean_test_score'])

scores = []
for train_indx, test_indx in cv.split(X, y):
    X_train, y_train = X[train_indx,:], y[train_indx]
    X_test, y_test = X[test_indx,:], y[test_indx]
    scores_ = []
    for k, c in itertools.product(K, C):
        anova = SelectKBest(k = k)
        X_train_k = anova.fit_transform(X_train, y_train)
        clf = SVC(C = c, probability = True, random_state = r).fit(X_train_k, y_train)
        y_pred = clf.predict_proba(anova.transform(X_test))[:, 1]
        scores_.append(roc_auc_score(y_test, y_pred))
    scores.append(scores_)
    
print('Manual grid-search CV results:')    
print(np.mean(np.array(scores), axis = 0)) 

对我来说,这会产生以下输出:

代码语言:javascript
复制
GridSearchCV results:
[0.41666667 0.4        0.4        0.4        0.21666667 0.26666667]
Manual grid-search CV results:
[0.58333333 0.6        0.53333333 0.46666667 0.48333333 0.5       ]

直接使用make_classification数据集时,输出将匹配。另一方面,当X是基于np.random.rand计算时,分数是不同的。

下面有没有我不知道的随机过程?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-03-15 00:16:09

编辑:重组我的答案,因为你似乎在追求更多的“为什么?”还有“我该怎么做”和“我怎么能?”

问题

在GridSearchCV中使用的记分器不会像在循环版本中那样传递predict_proba的输出。它正在传递decision_function的输出。对于支持向量机,概率的论证可能与决策不同,如这里所述

Platt所涉及的交叉验证对于大型数据集来说是一项昂贵的操作。此外,概率估计可能与分数不一致:

  • 分数的“论证”可能不是概率的论证。
  • 在二进制分类中,即使predict_proba的输出小于0.5时,预测样本也可以被标记为属于正类;同样,即使predict_proba的输出大于0.5时,它也可以被标记为负值。

我会怎样修正它

在管道/GridSearchCV方法和循环中使用SVC(probability = False, ...),在循环中使用decision_function而不是predict_proba。根据上面的信息,这也将加速您的代码。

我对你问题的原原本本的回答

要使循环与GridSearchCV匹配,只需使用GridSearchCV方法:

代码语言:javascript
复制
y_pred = clf.decision_function(anova.transform(X_test)) # instead of predict_proba

要使GridSearchCV与您的循环匹配,只需保留循环代码:

代码语言:javascript
复制
from sklearn.metrics import make_scorer
roc_auc_scorer = make_scorer(roc_auc_score, greater_is_better=True, needs_proba=True)
search = GridSearchCV(clf, space, scoring = roc_auc_scorer, cv = cv, refit = True, n_jobs = -1)
票数 2
EN

Stack Overflow用户

发布于 2021-03-15 12:42:31

您的实现与GridSearchCV操作方式之间的关键区别在于

  • GridSearchCV使用decision_function方法计算roc_auc
  • 在您的实现中,使用了predict_proba

只需更改以下一行:

代码语言:javascript
复制
        y_pred = clf.decision_function(anova.transform(X_test))

在此之后,两种方法都会得到相同的结果。

代码语言:javascript
复制
GridSearchCV results:
[0.41666667 0.4        0.4        0.4        0.21666667 0.26666667]
Manual grid-search CV results:
[0.41666667 0.4        0.4        0.4        0.21666667 0.26666667]

关于GridSearchCV 这里评分的更多解释。

这种不一致性记录在SVC的概率参数中:

概率 bool,default=False 是否启用概率估计。这必须在调用fit之前启用,因为它内部使用5倍交叉验证,并且predict_proba可能与预测不一致,因此会减慢该方法的速度。在用户指南中阅读更多内容。

这可能是为什么在使用make_classification数据集时没有区别的原因。也就是说,基于cv的5倍概率估计将与predict_proba输出类似,因为Xs是从高斯分布中提取的。而在np.random.rand()中,基于5倍的估计可能给出了完全不同的估计。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66499364

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档