分类问题(二)分类器的性能衡量

性能衡量

评估一个分类器的性能一般比评估一个回归器(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,也就是说有些类别的占比远大于其他类别)时。

接下来我们会介绍其他几种更好的衡量分类器的方法。

 

posted @ 2020-02-17 20:01  ZacksTang  阅读(900)  评论(0编辑  收藏  举报