性能衡量
評估一個分類器的性能一般比評估一個回歸器(regressor)更為復雜,所以我們會在這里大篇幅介紹分類器的性能評估,並且它也有多種評估方法。
使用CV衡量准確度
一個比較好的評估模型的辦法是使用交叉驗證。sk-learn提供了一個交叉驗證精准度的方法cross_val_score(),不過有時候若是需要實現一些自定義的目標,也可以實現一個交叉驗證的方法。例如:
from sklearn.model_selection import StratifiedKFold from sklearn.base import clone skfolds = StratifiedKFold(n_splits=3, random_state=42) for train_index, test_index in skfolds.split(X_train, y_train_5): clone_clf = clone(sgd_clf) X_train_folds = X_train[train_index] y_train_folds = y_train_5[train_index] X_test_fold = X_train[test_index] y_test_fold = y_train[test_index]
clone_clf.fit(X_train_folds, y_train_folds) y_pred = clone_clf.predict(X_test_fold) n_correct = sum(y_pred == y_test_fold) print(n_correct / len(y_pred)) >0.09925 0.09675 0.10035
這個代碼實現了 corss_val_score() 同樣的功能。StratifiedKFold類會做分層采樣,生成多個“折”。在每輪的迭代中,首先創建之前分類器的克隆,然后在每個“折”訓練集上訓練這個分類器,並在“折”測試集上進行預測,並最后計算預測的正確率。
然后我們試試直接用cross_val_score() 方法評估之前訓練好的 SGDClassifier模型,使用的也是K-折交叉驗證,指定3折。再次提醒一下大家,K-折交叉驗證是指:將訓練集分割為K個折(這里是3折),然后在每個“折”的數據上進行預測以及評估,使用非此“折”的訓練數據進行訓練。在這個例子中,訓練集是60000,分成3折是每折20000。所以訓練數據是40000,每次均在20000條驗證集上做評估。
from sklearn.model_selection import cross_val_score cross_val_score(sgd_clf, X_train, y_train_5, cv=3, scoring='accuracy') >array([0.95035, 0.96035, 0.9604 ])
從驗證集的評估來看,准確率達到了95% 以上,是一個非常高的准確率。這個結果看起來非常好,但是為什么說是“看起來非常好呢”?下面我們試試另一個非常蠢的分類器,這個分類器對每副圖片僅輸出“這個圖片不是數字5”:
from sklearn.base import BaseEstimator
class Never5Classifier(BaseEstimator): def fit(self, X, y=None): pass def predict(self, X): return np.zeros((len(X), 1), dtype=bool)
大家可以猜測一下,這個模型的准確率是多少:
never_5_clf = Never5Classifier() cross_val_score(never_5_clf, X_train, y_train_5, cv=3, scoring='accuracy') >array([0.91125, 0.90855, 0.90915])
准確率高達90%以上!為什么會這樣呢?
這是因為在所有圖片中,僅有10%的圖片是數字5。所以如果只是猜測圖片不是數字5,都有高達90%以上的正確率。
以上這個例子說明了:為什么准確率對於分類器來說,一般不是一個好的性能評估方案,特別是在處理傾斜數據集(skewed datasets,也就是說有些類別的占比遠大於其他類別)時。
接下來我們會介紹其他幾種更好的衡量分類器的方法。