在数据抽样部分我们已经讨论过如何抽样来进行训练和验证.但这往往不够完全的评估一个模型的性能.
当评价估计器需要设置超参时,由于在训练集上,通过调整参数设置使估计器的性能达到了最佳状态;但在测试集上可能会出现过拟合的情况.此时,测试集上的信息反馈足以颠覆训练好的模型,评估的指标不再有效反映出模型的泛化性能.为了解决此类问题,因此还应该准备另一部分验证集,模型训练完成以后在验证集上对模型进行评估.当验证集上的评估实验比较成功时,在测试集上进行最后的评估.
然而,通过将原始数据分为3个数据集合,我们就大大减少了可用于模型学习的样本数量,并且得到的结果依赖于集合对(训练,验证)的随机选择.这个问题可以通过 交叉验证来解决.交叉验证仍需要测试集做最后的模型评估,但不再需要验证集.
最基本的方法被称之为k-折交叉验证.k-折交叉验证将训练集划分为k个较小的集合,其验证流程是:
将k-1份训练集子集作为训练集训练模型
将剩余的1份训练集子集作为验证集用于模型验证获得一份验证集上的评分(也就是利用该数据集计算模型的性能指标,例如准确率)
k-折交叉验证得出的性能指标是循环计算中每个值的平均值.该方法虽然计算代价很高,但是它不会浪费太多的数据(如固定任意测试集的情况一样),在处理样本数据集较少的问题时比较有优势.一般来书说k会选择10
重复K-Fold n次.在每次重复中产生不同的分割.
LeaveOneOut是一个简单的交叉验证.每个学习集都是通过除了一个样本以外的所有样本创建的,测试集是被留下的样本.因此,对于 n 个样本,我们有 n 个不同的训练集和 n 个不同的测试集.这种交叉验证程序不会浪费太多数据,因为只有一个样本是从训练集中删除掉的.
LOO潜在的用户选择模型应该权衡一些已知的警告.当与 k 折交叉验证进行比较时,可以从 n 样本中构建 n 模型,而不是 k 模型,其中$n>k$.此外,每个在$n-1$个样本而不是在$(k-1)n/k$ 上进行训练.在两种方式中,假设 k 不是太大,并且$k<n$,LOO 比 k 折交叉验证计算开销更加昂贵.
就精度而言,LOO经常导致较高的方差作为测试误差的估计器.直观地说,因为n个样本中的n - 1被用来构建每个模型,折叠构建的模型实际上是相同的,并且是从整个训练集建立的模型.
但是,如果学习曲线对于所讨论的训练大小是陡峭的,那么 5- 或 10- 折交叉验证可以泛化误差增高.
作为一般规则,大多数作者和经验证据表明, 5- 或者 10- 交叉验证应该优于 LOO.
与交叉验证相关的接口包括:
model_selection.GroupKFold([n_splits])|分组K-叠交叉验证model_selection.GroupShuffleSplit([…])|分组随机排列交叉验证迭代器model_selection.KFold([n_splits, shuffle, …])|K叠交叉验证model_selection.LeaveOneGroupOut()|分组Leave One交叉验证model_selection.LeavePGroupsOut(n_groups)|分组Leave P交叉验证model_selection.LeaveOneOut()|Leave-One-Out交叉验证model_selection.LeavePOut(p)|Leave-P-Out交叉验证model_selection.PredefinedSplit(test_fold)|预定义交叉验证model_selection.RepeatedKFold([n_splits, …])|重复K叠交叉验证model_selection.RepeatedStratifiedKFold([…])|重复分层K折叠交叉验证model_selection.ShuffleSplit([n_splits, …])|随机排列交叉验证model_selection.StratifiedKFold([n_splits, …])|分层K折交叉验证model_selection.StratifiedShuffleSplit([…])|分层随机排列交叉验证model_selection.TimeSeriesSplit([n_splits, …])|时间序列交叉验证model_selection.cross_validate(estimator, X)|通过交叉验证来评估度量,并记录适合度/评分时间model_selection.cross_val_predict(estimator, X)|为每个输入数据点生成交叉验证估计model_selection.cross_val_score(estimator, X)|通过交叉验证评估分数model_selection.learning_curve(estimator, X, y)|学习曲线model_selection.permutation_test_score(…)|用排列评估交叉验证得分的重要性model_selection.validation_curve(estimator, …)|验证曲线
In [15]:
import numpy as np
from sklearn import datasets
from sklearn import svm
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import cross_val_predict
from sklearn import metrics
In [10]:
iris = datasets.load_iris()
In [11]:
clf = svm.SVC(kernel='linear', C=1)
scores = cross_val_score(clf, iris.data, iris.target, cv=5)
scores
Out[11]:
In [12]:
print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
In [14]:
predicted = cross_val_predict(clf, iris.data, iris.target, cv=10)
In [16]:
metrics.accuracy_score(iris.target, predicted)
Out[16]:
In [17]:
from sklearn.model_selection import KFold
In [21]:
kf = KFold(n_splits=20)
In [22]:
scores = cross_val_score(clf, iris.data, iris.target, cv=kf)
In [23]:
scores
Out[23]: