美文网首页scikit learn
机器学习中的交叉验证

机器学习中的交叉验证

作者: 7125messi | 来源:发表于2018-06-19 19:41 被阅读48次

    交叉验证是一种通过估计模型的泛化误差,从而进行模型选择的方法。没有任何假定前提,具有应用的普遍性,操作简便, 是一种行之有效的模型选择方法。

    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

    相关文章

      网友评论

        本文标题:机器学习中的交叉验证

        本文链接:https://www.haomeiwen.com/subject/kwkaeftx.html