交叉验证是一种通过估计模型的泛化误差,从而进行模型选择的方法。没有任何假定前提,具有应用的普遍性,操作简便, 是一种行之有效的模型选择方法。
1. 交叉验证的产生
人们发现用同一数据集,既进行训练,又进行模型误差估计,对误差估计的很不准确,这就是所说的模型误差估计的乐观性。为了克服这个问题,提出了交叉验证。基本思想是将数据分为两部分,一部分数据用来模型的训练,称为训练集;另外一部分用于测试模型的误差,称为验证集。由于两部分数据不同,估计得到的泛化误差更接近真实的模型表现。数据量足够的情况下,可以很好的估计真实的泛化误差。但是实际中,往往只有有限的数据可用,需要对数据进行重用,从而对数据进行多次切分,得到好的估计。
2. 交叉验证方法
-
留一交叉验证(leave-one-out):每次从个数为N的样本集中,取出一个样本作为验证集,剩下的N-1个作为训练集,重复进行N次。最后平均N个结果作为泛化误差估计。
-
留P交叉验证(leave-P-out):与留一类似,但是每次留P个样本。每次从个数为N的样本集中,取出P个样本作为验证集,剩下的N-P个作为训练集,重复进行
次。最后平均N个结果作为泛化误差估计。
以上两种方法基于数据完全切分,重复次数多,计算量大。
因此提出几种基于数据部分切分的方法减轻计算负担。
K折交叉验证:把数据分成K份,每次拿出一份作为验证集,剩下k-1份作为训练集,重复K次。最后平均K次的结果,作为误差评估的结果。与前两种方法对比,只需要计算k次,大大减小算法复杂度,被广泛应用。
3.模型选择方法的评价
衡量一个模型评估方法的好坏,往往从偏差和方差两方面进行。
3.1偏差
交叉验证只用了一部分数据用于模型训练,相对于足够多的数据进行训练的方法来说,模型训练的不充分,导致误差估计产生偏差。
-
留一交叉验证,每次只留下一个作为验证集,其余数据进行训练,产生泛化误差估计结果相对真值偏差较小。很多文献表明留一交叉验证在回归下的泛化误差估计是渐进无偏的。
-
留P交叉验证,取决于P的大小,P较小时,等同于留一交叉验证的情况。P较大,会产生较大的偏差,不可忽略。
-
K折交叉验证,同样取决于K的大小。K较大时,类似留一交叉验证;K较小时,会产生不可忽略的偏差。
训练数据越小,偏差越大。当偏差无法忽略时,需要对偏差进行纠正。
3.2方差
对于一个模型,训练数据固定后,不同的验证集得到的泛化误差评估结果的波动,称之为误差评估的方差
影响方差变化的因素,主要有数据的切分方法,模型的稳定性等。
训练数据固定的情况下,验证集中样本数量越多,方差越小。
模型的稳定性是指模型对于数据微小变化的敏感程度。
4.针对K折交叉验证的k的选择,及偏差和方差分析
对于k的选择,实践中一般取k =10。这里有一种情况,k = N,(N为训练样本数量)。在这种情况下,k折交叉验证也称为留一交叉验证(leave-one-out cross validation)。由于在留一交叉验证中,每一次训练模型的样本几乎是一样的,这样就会造成估计的偏差很小但方差很大的情况出现,另外,需要调用N次学习算法,这在N很大的时候,对于计算量也是不小的开销。
另一方面,如果取k = 10,那么交叉验证的方差会降低,但是偏差又会成为问题,这取决于训练样本的数量。当训练样本较小时,交叉验证很容易有较高的偏差,但是随着训练样本的增加,这种情况会得到改善。
5 交叉验证的目的
交叉验证的目的:在实际训练中,模型通常对训练数据好,但是对训练数据之外的数据拟合程度差。用于评价模型的泛化能力,从而进行模型选择。
交叉验证的基本思想:把在某种意义下将原始数据(dataset)进行分组,一部分做为训练集(train set),另一部分做为验证集(validation set or test set),首先用训练集对模型进行训练,再利用验证集来测试模型的泛化误差。另外,现实中数据总是有限的,为了对数据形成重用,从而提出k-折叠交叉验证。
对于个分类或回归问题,假设可选的模型为
k-折叠交叉验证就是将训练集的1/k作为测试集,每个模型训练k次,测试k次,错误率为k次的平均,最终选择平均率最小的模型。
6 K-Fold Cross Validation(K-折叠交叉验证)
在机器学习中,将数据集A分为训练集(training set)B和测试集(test set)C,在样本量不充足的情况下,为了充分利用数据集对算法效果进行测试,将数据集A随机分为k个包,每次将其中一个包作为测试集,剩下k-1个包作为训练集进行训练。
7 K折交叉验证评估模型性能
holdout交叉验证和K折交叉验证可以得到模型的泛化误差的可靠估计(模型在新数据集是的性能表现)。
7.1 holdout交叉验证
holdout交叉验证是机器学习模型泛化性能的一个经典且常用的方法。
holdout交叉验证能将最初的数据集分为训练集和测试集
模型选择:对模型的的不同参数设置进行调优和比较的过程,也就是针对给定分类问题,调整参数以寻找最优值(超参)的过程。
使用holdout进行模型选择更好的方法:将数据划分为三个部分,训练集,测试集,验证集。
训练集:用于不同模型的拟合,模型在验证集上的性能表现作为模型选择的标准
不使用测试集用于模型训练以及模型选择的优势:评估模型应用于新数据上能够获得较小偏差
holdout过程:
holdout缺点:模型性能评估对训练集划分为训练以及验证子集的方法是敏感的,评价的结果随样本的不同而发生变化。
7.2 K折交叉验证
K折交叉验证将k个训练子集重复holdout方法k次。
K折交叉验证不重复的随机将训练集划分为k个,k-1个用于训练,剩余一个用于测试,重复该过程k次,得到k个模型对模型性能的评价。
基于评价结果可以计算平均性能。
与holdput相比,这样得到的结果对数据划分方法敏感度相对较低。
一般情况将K折交叉验证用于模型调优,找到使得模型泛化性能最优的超参值。找到后,在全部训练集上重新训练模型,并使用独立测试集对模型性能做出最终评价。
K折交叉验证使用了无重复抽样技术的好处:每次迭代过程中每个样本点只有一次被划入训练集或测试集的机会。
K折交叉验证图:
如果训练数据集相对较小,则增大k值。
增大k值,在每次迭代过程中将会有更多的数据用于模型训练,能够得到最小偏差,同时算法时间延长。且训练块间高度相似,导致评价结果方差较高。
如果训练集相对较大,则减小k值。
减小k值,降低模型在不同的数据块上进行重复拟合的性能评估的计算成本,在平均性能的基础上获得模型的准确评估。
K折交叉验证的一个特例:
留一(LOO)交叉验证法:将数据子集划分的数量等于样本数(k=n),每次只有一个样本用于测试,数据集非常小时,建议用此方法。
K折交叉验证改进成的 分层K折交叉验证:获得偏差和方差都低的评估结果,特别是类别比例相差较大时。
7.3 实现K折交叉验证:
StratifiedKFold用法类似Kfold,但是他是分层采样,确保训练集,测试集中各类别样本的比例与原始数据集中相同。
使用数据集中的类标y_train初始化sklearn.cross_validation模块下的StratifiedKFold迭代器,通过n_folds参数设置块的数量。
使用kfold在k个块中迭代时,使用train中返回的索引去拟合流水线,通过pipe_lr流水线保证样本都得到适当的缩放。
使用test索引计算模型的准确率,存在score中。
# 使用k-fold交叉验证来评估模型性能。
import numpy as np
from sklearn.model_selection import StratifiedKFold
kfold = StratifiedKFold(y=y_train,
n_folds=10,
random_state=1)
scores = []
for k, (train, test) in enumerate(kfold):
pipe_lr.fit(X_train[train], y_train[train])
score = pipe_lr.score(X_train[test], y_train[test])
scores.append(score)
print('Fold: %s, Class dist.: %s, Acc: %.3f' % (k+1, np.bincount(y_train[train]), score))
print('\nCV accuracy: %.3f +/- %.3f' % (np.mean(scores), np.std(scores)))
from sklearn.model_selection import cross_val_score
scores = cross_val_score(estimator=pipe_lr,
X=X_train,
y=y_train,
cv=10,
n_jobs=1)
print('CV accuracy scores: %s' % scores)
print('CV accuracy: %.3f +/- %.3f' % (np.mean(scores), np.std(scores)))
cross_val_score方法特点:将不同分块的性能评估分布到多个CPU上进行处理。
n_jobs:CPU个数,-1为选择全部CPU
网友评论