2017-07-24 31 views
1

我使用的是sklearn.model_selection.GridSearchCVsklearn.model_selection.cross_val_score,同時這樣做時我遇到了意想不到的結果。交叉驗證與Scikit中的網格搜索學習

在我的例子中,我使用下面的進口:

from sklearn.datasets import make_classification 
from sklearn.pipeline import Pipeline 
from sklearn.preprocessing import StandardScaler 
from sklearn.svm import LinearSVC 
from sklearn.model_selection import cross_val_score 
from sklearn.metrics import make_scorer 
from sklearn.metrics import recall_score 
from sklearn.model_selection import GridSearchCV 
import numpy as np 

首先,我創建一個隨機的數據集:

X, y = make_classification(n_samples=1000, n_features=20, random_state=42) 

接下來,我定義管道 「發電機」:

def my_pipeline(C=None): 
    if C is None: 
     return Pipeline(
      [ 
       ('step1', StandardScaler()), 
       ('clf', LinearSVC(random_state=42)) 
      ]) 
    else: 
     return Pipeline(
      [ 
       ('step1', StandardScaler()), 
       ('clf', LinearSVC(C=C, random_state=42)) 
      ])   

接下來,我設置了幾個C的待測:

Cs = [0.01, 0.1, 1, 2, 5, 10, 50, 100] 

最後,我想檢查什麼是可以獲得的最大recall_score。有一次,我使用cross_val_score並且直接使用GridSearchCV

np.max(
    [ 
     np.mean(
      cross_val_score(my_pipeline(C=c), X, y, 
          cv=3, 
          scoring=make_scorer(recall_score) 
    )) for c in Cs]) 

和:

GridSearchCV(
    my_pipeline(), 
    { 
     'clf__C': Cs 
    }, 
    scoring=make_scorer(recall_score), 
    cv=3 
).fit(X, y).best_score_) 

在我的例子,前者產量0.85997883750571147,後者0.85999999999999999。我期待的價值是一樣的。我錯過了什麼?

我把它全部放在gist之內。

編輯:修復cv。我用StratifiedKFold(n_splits=3, random_state=42)替換cv=3,結果沒有改變。事實上,似乎cv不影響結果。

+0

這裏的一個非常快速的第一個猜測是,它與數據被分割爲摺疊進行交叉驗證時的隨機數生成器的狀態有關。如果你在'GridSearchCV'和'cross_val_score'中修改'random_state',會發生什麼? –

+0

好猜,但是......錯。 @AngusWilliams檢查更新。 – Dror

回答

1

對我來說,它看起來像一個精確的問題。如果你看一下成績的完整列表,然後cross_val_score你會得到如下:

[0.85193468484717316, 
0.85394271697568724, 
0.85995478921674717, 
0.85995478921674717, 
0.8579467570882332, 
0.86195079720077905, 
0.81404660558401265, 
0.82201861337565829] 

GridSearchCV您會收到以下

[mean: 0.85200, std: 0.02736, params: {'clf__C': 0.01}, 
mean: 0.85400, std: 0.02249, params: {'clf__C': 0.1}, 
mean: 0.86000, std: 0.01759, params: {'clf__C': 1}, 
mean: 0.86000, std: 0.01759, params: {'clf__C': 2}, 
mean: 0.85800, std: 0.02020, params: {'clf__C': 5}, 
mean: 0.86200, std: 0.02275, params: {'clf__C': 10}, 
mean: 0.81400, std: 0.01916, params: {'clf__C': 50}, 
mean: 0.82200, std: 0.02296, params: {'clf__C': 100}] 

所以每對相應的分數是besically幾乎相同,精度差異很小(看起來像GridSearchCV中的分數是四捨五入的)。

+0

事實上,似乎有一些四捨五入的原因。我無法在[代碼]中找到它的記錄(https://github.com/scikit-learn/scikit-learn/blob/75d6005feacfedad33df8bed31e34f7bec51f62d/sklearn/model_selection/_search.py​​)。 – Dror

相關問題