zoukankan      html  css  js  c++  java
  • 模型泛化

    1.过拟合与乐观模型

          有监督学习的基本目标是准确预测,当对模型进行性能评估时,需要确定模型对新数据的性能如何。即需要一个指标来确定预测的泛化能力如何。对于回归问题来说,标准评价指标是均方误差(Mean Squared Error)。它是目标变量真实值和预测值之差的平方和的均值。参看下图(学习自  Real-World Machine Learning)的例子:

                   

    左图中随着带宽参数的增加,模型趋于欠拟合,而在最左边的图中明显是过拟合,而此时的模型MSE(均方误差)最小,但是泛化误差却可能是最大的。所以训练集误差与机器学习模型的泛化误差之间发生了分歧。这可以在上图右图中看到。看到训练集(蓝色曲线)误差最小的时候对应最小的带宽参数,这时你会误认为此时的模型最优,但是这时的模型发生了严重的过拟合使得在新数据上的误差最大!所以在模型拟合和评价中都使用训练数据会使你对模型又过于乐观的估计。总结:当带宽参数最小的时候 ,此时训练集误差最小,过拟合最严重,泛化能力最弱。随着带宽参数的增加,模型的复杂度在降低,在带宽参数达到0.12的时候,此时模型在新数据性能上最优。而随着带宽参数继续增加,模型又陷入了欠拟合。 根据蓝色曲线,我们会错误的选择0.01的带宽参数,因为训练集上的MSE只有0.08,但是新数据上的MSE高达0.50!所以我们需要有一种评价指标使得我们可以挑选出合适的带宽参数约为0.12,此时新数据上的MSE才最小为0.27。所以需要换一种模型评价方法:交叉验证。

    交叉验证

    上面看到训练集误差并不能代表模型在新数据上的误差。为了估计模型在新数据上的错误率,需要利用交叉验证(CV),严格使用训练集评估新数据的准确性。交叉验证常用的两种方法:保持法(holdout method)和K-折交叉验证(k-fold cross-validation)。

     1)保持法

           最简单的方法是用独立的训练集合测试集。集将训练集中抽取一部分用作测试集。通常会取20%-40%的数据作为测试集。还是上面的例子,看下保持法计算的评估误差和新数据误差的关系:明显看出保持法计算的评估误差接近模型的新数据误差。它们比训练集的估计误差更接近,特别是在带宽参数值较小的时候。但是问题也很明显,保持法的噪声较大,根据下图中大约带宽参数为0.15时,保持法得到的MSE标准为0.15,实际新数据的MSE为0.27.所以保持法使得我们会选择0.14的带宽参数,这与0.12的最优参数很接近了!比起训练集MSE最小化推荐给我们的参数0.01好太多。可以通过重复的训练-测试集划分,并对结果取均值来消除噪声,但是在多次循环中,每个数据点会被多次分配到测试集中,使结果有偏差。更好的方法是K-折交叉验证。

                                 

                                         采用保持法得到的评估误差                                                                        采用K-折交叉验证得到的评估误差 

     2)K-折交叉验证

            和保持法一样,k-折交叉验证依赖于训练数据隔离,但不同的是,K-折交叉验证随机的把数据分成k个互不相交的子集,称为包(fold)。k可以取5、10、20...。对于每个包只作为验证集。所以不会有相同的数据点进入测试集中。采用10折交叉验证的结果如上图,K-折交叉验证估计误差与新数据上的误差非常接近。

     2. sklearn中的  Cross-validation

     1)保持法

    >>> import numpy as np
    >>> from sklearn.model_selection import train_test_split
    >>> from sklearn import datasets
    >>> from sklearn import svm
    
    >>> iris = datasets.load_iris()
    >>> iris.data.shape, iris.target.shape
    ((150, 4), (150,))

            取iris数据集的训练样本,将其按照0.4的比例划分为训练集和测试集。采用svm进行训练,验证其在测试机上的表现。为了解决模型可能出现的过拟合问题,可以将所有样本划分为训练集、交叉验证集和测试集。即用训练样本训练,利用交叉验证集来评估,当在交叉验证集上表现较好时再用测试集进行最终验证。但这样就导致最初的样本被分为三个子集,在训练的时候就没有足够多的样本数量(本应该用所有样本来训练),结果很可能会受到某一特定验证集和测试集的影响。一种方案就是测试集仍然应该被分出来,但是交叉验证集不需单独划分,就是利用K-折交叉验证即可。这样就不会损失太多训练样本,虽然计算代价较大。

    >>> X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.4, random_state=0)
    
    >>> X_train.shape, y_train.shape
    ((90, 4), (90,))
    >>> X_test.shape, y_test.shape
    ((60, 4), (60,))
    
    >>> clf = svm.SVC(kernel='linear', C=1).fit(X_train, y_train)
    >>> clf.score(X_test, y_test)                           
    0.96...

    2)Computing cross-validated metrics

        利用sklearn中的cross_va_score函数作为数据集的评估。以下是利用5折交叉验证评估svm在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)

    3.交叉验证注意事项

              交叉验证可以帮我们选择最佳模型,但实际应用中需注意几个问题:

     1)交叉验证法假定训练数据是有代表性的。否则解决方法:保证训练数据中的所有潜在偏见都被找到并最小化。

     2)K折交叉验证中包的数量越多,估计误差越好,但也更耗时间。解决方法:可能的话至少使用10个包,对于训练和预测较快的模型,可以使用单一保留(leave-one-out)交叉验证(k=数据实例个数)。    

  • 相关阅读:
    应用C#和SQLCLR编写SQL Server用户定义函数
    警告:隐式声明与内建函数'exit'不兼容解决方案
    GDB详解
    Linux GCC常用命令
    WebBrowser处理AJAX生成的网页内容!
    IOS开发之网络编程开源类 Reachability应用
    NSString和NSMutableString常用方法+NSArray常用代码 (转)
    hosts立即生效的方法
    spring.net xml 命名空间
    c#操作access,update语句不执行的解决办法
  • 原文地址:https://www.cnblogs.com/king-lps/p/7670589.html
Copyright © 2011-2022 走看看