计算交叉验证的指标
使用交叉验证最简单的方法是在估计器和数据集上调用 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
默认使用 KFold
或 StratifiedKFold
策略,后者会在估计器派生自 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
比较适合做下列事儿:
- 从不同模型获得的预测结果的可视化。
- 模型混合: 在集成方法中,当一个有监督估计量的预测被用来训练另一个估计量时
可用的交叉验证迭代器在下面的章节将提到。
示例