1. 程式人生 > 其它 >機器學習sklearn(二十二): 模型評估(二)交叉驗證:評估估算器的表現(二)計算交叉驗證的指標

機器學習sklearn(二十二): 模型評估(二)交叉驗證:評估估算器的表現(二)計算交叉驗證的指標

計算交叉驗證的指標

使用交叉驗證最簡單的方法是在估計器和資料集上呼叫cross_val_score輔助函式。

下面的示例展示瞭如何通過分割資料,擬合模型和計算連續 5 次的分數(每次不同分割)來估計 linear kernel 支援向量機在 iris 資料集上的精度:

>>> from sklearn.model_selection import cross_val_score
>>> clf = svm.SVC(kernel='linear', C=1)
>>> scores = cross_val_score(clf, iris.data, iris.target, cv=5)
>>> scores array([0.96..., 1. ..., 0.96..., 0.96..., 1. ])

評分估計的平均得分和 95% 置信區間由此給出:

>>> print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
Accuracy: 0.98 (+/- 0.03)

預設情況下,每個 CV 迭代計算的分數是估計器的score方法。可以通過使用 scoring 引數來改變計算方式如下:

>>> from sklearn import metrics
>>> scores = cross_val_score(
...     clf, iris.data, iris.target, cv=5, scoring='f1_macro')
>>> scores                                              
array([0.96..., 1.  ..., 0.96..., 0.96..., 1.        ])

詳情請參閱scoring 引數: 定義模型評估規則。 在 Iris 資料集的情形下,樣本在各個目標類別之間是平衡的,因此準確度和 F1-score 幾乎相等。

cv引數是一個整數時,cross_val_score預設使用KFoldStratifiedKFold策略,後者會在估計器派生自ClassifierMixin時使用。

也可以通過傳入一個交叉驗證迭代器來使用其他交叉驗證策略,比如:

>>> from sklearn.model_selection import ShuffleSplit
>>> n_samples = iris.data.shape[0]
>>> cv = ShuffleSplit(n_splits=5, test_size=0.3, random_state=0)
>>> cross_val_score(clf, iris.data, iris.target, cv=cv)  
array([0.977..., 0.977..., 1.  ..., 0.955..., 1.        ])

另外一種可選方案是使用一個可迭代生成器作為索引陣列產生(train, test) 劃分,比如:

>>> def custom_cv_2folds(X):
...     n = X.shape[0]
...     i = 1
...     while i <= 2:
...         idx = np.arange(n * (i - 1) / 2, n * i / 2, dtype=int)
...         yield idx, idx
...         i += 1
...
>>> custom_cv = custom_cv_2folds(iris.data)
>>> cross_val_score(clf, iris.data, iris.target, cv=custom_cv)
array([1.        , 0.973...])

保留資料的資料轉換

正如在訓練集中保留的資料上測試一個 predictor (預測器)是很重要的一樣,預處理(如標準化,特徵選擇等)和

類似的data transformations也應該從訓練集中學習,並應用於預測資料以進行預測:

>> from sklearn import preprocessing
>> X_train, X_test, y_train, y_test = train_test_split(
  ...     iris.data, iris.target, test_size=0.4, random_state=0)
>> scaler = preprocessing.StandardScaler().fit(X_train)
>> X_train_transformed = scaler.transform(X_train)
>> clf = svm.SVC(C=1).fit(X_train_transformed, y_train)
>> X_test_transformed = scaler.transform(X_test)
>> clf.score(X_test_transformed, y_test)  
  0.9333...

Pipeline可以更容易地組合估計器,在交叉驗證下使用如下:

>> from sklearn.pipeline import make_pipeline
>> clf = make_pipeline(preprocessing.StandardScaler(), svm.SVC(C=1))
>> cross_val_score(clf, iris.data, iris.target, cv=cv)
  ...                                                 
  array([ 0.97...,  0.93...,  0.95...])

1. cross_validate 函式和多度量評估

cross_validate函式與cross_val_score在下面的兩個方面有些不同 -

  • 它允許指定多個指標進行評估.
  • 除了測試得分之外,它還會返回一個包含訓練得分,擬合次數, score-times (得分次數)的一個字典。 It returns a dict containing training scores, fit-times and score-times in addition to the test score.

對於單個度量評估,其中 scoring 引數是一個字串,可以呼叫或 None , keys 將是 -['test_score', 'fit_time', 'score_time']

而對於多度量評估,返回值是一個帶有以下的 keys 的字典 -['test_<scorer1_name>', 'test_<scorer2_name>', 'test_<scorer...>', 'fit_time', 'score_time']

return_train_score預設設定為True。 它增加了所有 scorers(得分器) 的訓練得分 keys 。如果不需要訓練 scores ,則應將其明確設定為False

你還可以通過設定return_estimator=True來保留在所有訓練集上擬合好的估計器。

可以將多個測度指標指定為list,tuple或者是預定義評分器(predefined scorer)的名字的集合

>>> from sklearn.model_selection import cross_validate
>>> from sklearn.metrics import recall_score
>>> scoring = ['precision_macro', 'recall_macro']
>>> clf = svm.SVC(kernel='linear', C=1, random_state=0)
>>> scores = cross_validate(clf, iris.data, iris.target, scoring=scoring,
...                         cv=5)
>>> sorted(scores.keys())
['fit_time', 'score_time', 'test_precision_macro', 'test_recall_macro']
>>> scores['test_recall_macro']                       
array([0.96..., 1.  ..., 0.96..., 0.96..., 1.        ])

或作為一個字典 mapping 得分器名稱預定義或自定義的得分函式:

>>> from sklearn.metrics.scorer import make_scorer
>>> scoring = {'prec_macro': 'precision_macro',
...            'rec_macro': make_scorer(recall_score, average='macro')}
>>> scores = cross_validate(clf, iris.data, iris.target, scoring=scoring,
...                         cv=5, return_train_score=True)
>>> sorted(scores.keys())                 
['fit_time', 'score_time', 'test_prec_macro', 'test_rec_macro',
 'train_prec_macro', 'train_rec_macro']
>>> scores['train_rec_macro']                         
array([0.97..., 0.97..., 0.99..., 0.98..., 0.98...])

這裡是一個使用單一指標的cross_validate的示例:

>>> scores = cross_validate(clf, iris.data, iris.target,
...                         scoring='precision_macro', cv=5,
...                         return_estimator=True)
>>> sorted(scores.keys())
['estimator', 'fit_time', 'score_time', 'test_score']

2. 通過交叉驗證獲取預測

除了返回結果不同,函式cross_val_predict具有和cross_val_score相同的介面, 對於每一個輸入的元素,如果其在測試集合中,將會得到預測結果。交叉驗證策略會將可用的元素提交到測試集合有且僅有一次(否則會丟擲一個異常)。

警告:交叉預測可能使用不當

cross_val_predict函式的結果可能會與cross_val_score函式的結果不一樣,因為在這兩種方法中元素的分組方式不一樣。函式cross_val_score在所有交叉驗證的摺子上取平均。但是,函式cross_val_predict只是簡單的返回由若干不同模型預測出的標籤或概率。因此,cross_val_predict不是一種適當的泛化錯誤的度量。

函式cross_val_predict比較適合做下列事兒:

  • 從不同模型獲得的預測結果的視覺化。
  • 模型混合: 在整合方法中,當一個有監督估計量的預測被用來訓練另一個估計量時

可用的交叉驗證迭代器在下面的章節將提到。

示例