在k折交叉验证中,我们不重复地随机将训练数据集划分为k个,其中k-1个用于模型的训练,剩余的1个用于测试。重复此过程k次,我们就得到了k个模型及对模型性能的评价。
读者可能对有放回抽样和无放回抽样不太熟悉,我们在此简单做个介绍。假设我们在玩彩票游戏,游戏的规则是从一个盒子中随机抽取数字。盒子中包含5个数字0、1、2、3和4,每轮我们都只抽取出其中的一个。在第一轮中,我们抽到某个特定数字的概率为1/5。现在我们采用无放回抽样,也就是完成数字的抽取后,不再将其放回盒子。这时,抽到某个特定数字的概率依赖于上一轮的抽取结果。例如,如果盒子中剩余的数字为0、1、2和4,则下一轮抽取中得到数字0的概率应为1/4。
不过,在有放回随机抽样中,我们会将抽取到的数字再放回到盒子中,这样每一轮中抽取到某个特定数字的概率不发生改变,同时我们也可以多次抽取到同一个数字。换句话说,在有放回抽样中,样本(数字)是相互独立的,它们的协方差为0。例如,5次随机抽样的结果可能如下:
·无放回随机抽样:2,1,3,4,0
·有放回随机抽样:1,3,3,4,1
基于这些独立且不同的数据子集上得到的模型性能评价结果,我们可以计算出其平均性能,与holdout方法相比,这样得到的结果对数据划分方法的敏感性相对较低。通常情况下,我们将k折交叉验证用于模型的调优,也就是找到使得模型泛化性能最优的超参值。一旦找到了满意的超参值,我们就可以在全部的训练数据上重新训练模型,并使用独立的测试数据集对模型性能做出最终评价。
由于k折交叉验证使用了无重复抽样技术,该方法的优势在于(每次迭代过程中)每个样本点只有一次被划入训练数据集或测试数据集的机会,与holdout方法相比,这将使得模型性能的评估具有较小的方差。下图总结了k折交叉验证的相关概念,其中k=10。训练数据集被划分为10块,在10次迭代中,每次迭代都将9块用于训练,剩余的1块作为测试集用于模型的评估。此外,每次迭代中得到的性能评价指标Ei(例如,分类的准确性或者误差)可用来计算模型的估计平均性能E:
k折交叉验证中k的标准值为10,这对大多数应用来说都是合理的。但是,如果训练数据集相对较小,那就有必要加大k的值。如果我们增大k的值,在每次迭代中将会有更多的数据用于模型的训练,这样通过计算各性能评估结果的平均值对模型的泛化性能进行评价时,可以得到较小的偏差。但是,k值的增加将导致交叉验证算法运行时间延长,而且由于各训练块间高度相似,也会导致评价结果方差较高。另一方面,如果数据集较大,则可以选择较小的k值,如k=5,这不光能够降低模型在不同数据块上进行重复拟合和性能评估的计算成本,还可以在平均性能的基础上获得对模型的准确评估。
k折交叉验证的一个特例就是留一(leave-ont-out,LOO)交叉验证法。在LOO中,我们将数据子集划分的数量等同于样本数(k=n),这样每次只有一个样本用于测试。当数据集非常小时,建议使用此方法进行验证。
分层k折交叉验证对标准k折交叉验证做了稍许改进,它可以获得偏差和方差都较低的评估结果,特别是类别比例相差较大时,详见R.Kohavi等人的研究[1]。在分层交叉验证中,类别比例在每个分块中得以保持,这使得每个分块中的类别比例与训练数据集的整体比例一致,下面通过scikit-learn中的StratifiedKFold迭代器来演示:
首先,我们用训练集中的类标y_train来初始化sklearn.cross_validation模块下的Stratified-Kfold迭代器,并通过n_folds参数来设置块的数量。当我们使用kfold迭代器在k个块中进行循环时,使用train中返回的索引去拟合本章开始时所构建的逻辑斯谛回归流水线。通过pile_lr流水线,我们可以保证每次迭代中样本都得到适当的缩放(如标准化)。然后使用test索引计算模型的准确率,将其存储在score列表中,用于计算平均准确率以及性能评估标准差。
尽管之前的代码清楚地介绍了k折交叉验证的工作方式,scikit-learn中同样也实现了k折交叉验证评分的计算,这使得我们可以更加高效地使用分层k折交叉验证对模型进行评估:
cross_val_score方法具备一个极为有用的特点,它可以将不同分块的性能评估分布到多个CPU上进行处理。如果将n_jobs参数的值设为1,则与例子中使用的StratifiedKFold类似,只使用一个CPU对性能进行评估。如果设定n_jobs=2,我们可以将10轮的交叉验证分布到两块CPU(如果使用的计算机支持)上进行,如果设置n_jobs=-1,则可利用计算机所有的CPU并行地进行计算。
关于交叉验证中泛化性能方差的估计已经超出了本书的讨论范围,不过读者可以参阅M.Markaou等人的论文[2],该文章对上述问题做了精彩的描述。
同时,读者也可以了解其他的交叉验证技术,如.632 Bootstrap交叉验证(.632 Bootstrap cross-validation)方法[3]。
[1] R.Konavi et al.A Study of Cross-validation and Bootstrap for Accuracy Estimation and Model Selection.In Ijcai,volume 14,pages 1137-1145,1995.
[2] M. Markatou, H. Tian, S. Biswas, and G. M. Hripcsak. Analysis of Variance of Cross-validation Estimators of the Generalization Error. Journal of Machine Learning Research, 6:1127–1168, 2005.
[3] B. Efron and R. Tibshirani. Improvements on Cross-validation :The 632+ Bootstrap Method. Journal of the American Statistical Association,92(438):548—560,1997.