评估分类器比评估回归器要困难得多,因此,本章将用很多篇幅来讨论这个主题,同时会涉及许多性能考核的方法。
3.3.1 使用交叉验证测试准确率
正如第二章所述,交叉验证是一个评估模型的好方法。
-实现交叉验证
相比于Scikit-Learn提供cross_val_score()这类交叉验证的函数,有时你可能希望自己能够控制的多一些。在这种情况下,你可以自行实现交叉验证,操作也简单明了。下面这段代码与前面的cross_val_score()大致相同,并打印出相同的结果:
from sklearn.model_selection import StratifiedKFoldfrom sklearn.base import cloneskfolds = StratifiedKFold(n_splits=3,shuffle=True,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_folds = X_train[test_index]y_test_folds = y_train_5[test_index]clone_clf.fit(X_train_folds,y_train_folds)y_pred = clone_clf.predict(X_test_folds)n_correct = sum(y_pred == y_test_folds)print(n_correct/len(y_pred))#输出0.950350.960350.9604
每个折叠有StratifiedKFold执行分层抽样(参见第二章)产生,其所包含的各个类的比例符合整体比例。每个迭代会创建一个分类器的副本,用训练集对这个副本进行训练,然后用测试集进行预测。最后计算正确预测的次数,输出正确预测的比率。
现在,用cross_val_score()函数来评估SGDClassifier模型,采用K-折交叉验证法(3个折叠)。记住,K-折交叉验证的意思是将训练集分解成K个折叠(在本例中,为3折),然后每次留其中1个折叠进行预测,剩余的折叠用来训练。
>>> 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 ])
所有折叠交叉验证的准确率(正确预测的比率)超过93%?看起来挺神奇的,是吗?不过你在开始激动之前,我们先来看一个蠢笨的分类器,它将每张图都分类成“非5”:
from sklearn.base import BaseEstimatorclass Never5Classifier(BaseEstimator):def fit(self,X,y=None):return selfdef 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%的概率你都是正确的,简直超越了大预言家! 这说明准确率通常无法成为分类器的首要性能指标,特别是当你处理有偏数据集时(即某些类比其他类更为频繁)。
3.3.2 混淆矩阵
评估分类器性能的更好方法是混淆矩阵,其总体思路就是统计A类别实例被分成为B类别的次数。例如,要想知道分类器将数字3和数字5 混淆多少次,只需要通过混淆矩阵的第5行第3列来查看。 要计算混淆矩阵,需要先有一组预测才能将其与实际目标进行比 较。当然,可以通过测试集来进行预测,但是现在先不要动它(测试集最好留到项目的最后,准备启动分类器时再使用)。作为替代,可以使 用cross_val_predict()函数:
