• 你真的了解交叉验证和过拟合吗?


    1.过拟合的问题

    1.1 过拟合的定义

      开篇首先谈一下机器学习模型的过拟合问题。什么是过拟合?简单来讲,当 train set 误差较小,而 test set 误差较大时,我们即可认为模型过拟合。这句话表达的另一层意思是,模型评估指标的方差(variance)较大,即可认为模型过拟合。另外,无论监督学习还是非监督学习,均存在过拟合的问题。

    1.2 如何判断是否过拟合

      一般来讲,判断模型是否过拟合可采用学习曲线(learning curve),通过画学习曲线图可以直观的看出 train set 和 test set 的误差随着训练样本数量(number of training samples)的变化。在学习曲线中,如果训练准确度(training accuracy)和测试准确度(或验证准确度 validation accuracy)两条曲线相距较远,则说明模型的方差较大(一般情况下,训练精度都会高于测试精度),模型过拟合。而我们期望的理想状况是,训练集和测试集的两条精度曲线相距较近,并且随着训练样本数量的增加,越来越近,逐渐收敛。

      当然,还有最简单的判断模型是否过拟合的方法,就是通过training accuracy 和 test accuracy 数值大小,直观的判断模型是否过拟合。例如,训练集的准确率为90%,而测试集的准确率为70%,那么我们可以认为模型过拟合。不过,这种方法没有明确的判断标准,完全靠个人的主观判断——“感觉训练和测试的误差相差有点大,有可能过拟合”。还是刚才的例子,如果测试集的误差为80%,那么我们是否还能下结论模型过拟合呢?这个时候你可以说,训练和测试准确率相差10个百分点,也挺大的,还是有很大可能过拟合的。但是,也有可能,模型的平均误差率在85%左右,在95%的置信度下,模型预测准确率的置信区间恰为 [80%,90%],那么此时模型并没有过拟合。当然,后一种情况出现的概率相对较小,我只是想表达一下,这种直观的判断方法是不一定准确的,不过方便的是,我们不用画学习曲线图啊,多省事。因此,总的来讲,我们可以先通过训练集和测试集准确率的大小,直观的判断模型是否过拟合;当没有把握断定模型是否过拟合时,再借助学习曲线。

    1.3 过拟合的原因

      不知道各位有没有听过这样一种说法,就是没有任何一种算法能够完全避免过拟合。其实,我们讨论模型的过拟合,实际上是针对模型的泛化性能进行研究。首先我觉得,模型的泛化能力如何,一方面与模型自身的特性有关,另一方面与所研究的数据也有关。如果我们的数据质量较高,并且呈现出某种特有的“规律”,那么对于新数据,模型具有非常好的泛化能力,那么我们可以说模型不存在任何过拟合问题。但是,理想是饱满的,现实是骨感的。在实际生产环境中,绝对不可能出现质量很高的数据,而数据所蕴含的规律或特性也不是那么容易学习。因此,即便用再高大上的模型,再花多少时间优化模型的超参数和参数,依然很难再提高模型的泛化能力。生活中我们常说一句话:天赋决定上限,努力决定下限。我想套用这句话说:数据决定上限,模型决定下限。

      接下来,我想谈一下机器学习中的一个算法——随机森林。为什么点名道姓要聊它?原因很简单,我们在谈到不同模型的优缺点时,给随机森林贴的标签之一,就是它能有效的避免过拟合。(我看过很多人说的更激进,直接说随机森林不会出现过拟合。)随机森林算法,出自于集成学习算法家族中的bagging,往往是我们解决决策树过拟合问题的有效方案之一。貌似随机森林算法的作者说过随机森林算法不会出现过拟合,也有人说他本意表达的意思是,随着树的增加,测试集的误差不会增大,而是趋于收敛;同时,看到有人说随机森林在噪声较大的数据集上依然会表现出过拟合(这就是我前面说的数据的影响,不能把数据的锅甩给模型啊)。我自己在使用过程中发现,当随机森林树的棵树较少时,例如sklearn中默认的10棵,这种情况,模型的方差依然会很大。所以用随机森林时,可以将树的数量设置多一些(R语言中随机森林默认好像是100棵树),不过树太多的话,模型训练时间长、对于计算资源的占用较大。

      网上有很多关于随机森林是否会产生过拟合的激烈讨论,这里也分享我在知乎上看到的一个帖子:https://www.zhihu.com/question/23578594 。最后,对于随机森林是否会产生过拟合的问题,总结一句:随机森林能有效的避免过拟合,但如果数据质量较差(例如噪声较大),那么模型的泛化能力也会受到很大影响。(貌似这样说才不显得那么武断。。)

      最后总结一下,导致过拟合的原因大概有以下几点:

      - 模型复杂度过高

      - 训练数据过少

      - 数据噪声较大

    2.交叉验证

      通过对过拟合的讨论之后,我们在运用机器学习算法模型时,要考虑两个问题:(1) 如何验证模型是否过拟合?(2) 如何避免过拟合?

      关于如何验证模型是否过拟合,上一节已经简单讨论。接下来想针对python机器学习算法模块sklearn中交叉验证相关函数的使用加以说明。

    2.1 cross_validate 与 cross_val_score

      这两个函数的区别是,cross_validate允许指定多个指标进行评估,同时,它还可以显示交叉验证训练集的评估score,而cross_val_score只能显示测试集的score。当我们需要直观判断模型是否过拟合时,可以采用 cross_validate 观察训练和测试集评估score相差的大小。而cross_val_score可以用作对模型性能的综合评估。

    2.2 如何利用交叉验证避免过拟合?

      避免模型过拟合的方法,总结大概以下几点:

      - 重新清洗数据(删除稀疏特征、对噪声数据进行处理(删除/替换))

      - 重新采样(改变采样方法等)

      - 增加训练数据

      - 采用交叉验证训练模型

      - 重新筛选特征

      - 降低模型复杂度(增加正则项:L1,L2)

      - dropout(神经网络中,让神经元一定的概率不工作)

      本文主要探讨一下如何利用交叉验证来避免模型过拟合。

      首先,我们要明确一下交叉验证的作用是什么,什么场景下会用到交叉验证。

      第一个作用就是对模型的性能进行评估。当我们通过一次划分样本对模型进行训练和测试时,由于样本划分的偶然性,会导致我们对模型的评估不准确。因此,可以采用交叉验证对模型进行评估(一般采用5折或10折,sklearn默认采用的是3折),以 n 折交叉验证结果的均值,作为模型的性能评估。

      第二个作用就是用来避免过拟合。例如当我们进行10折交叉验证时,训练了10次,得到了10个模型,每个模型的参数也是不同的,那么我们究竟用哪个模型作为我们最终的模型呢?答案是:一个都不用!我们要利用全量数据重新训练出一个最终模型!

      如果你觉得有点迷糊的话不用急,我们一起来梳理一下。我们训练模型是为了什么?是为了确定模型中的参数,例如多元回归模型的系数、神经网络各神经元的权重等。但是,有些模型除了参数还有超参数,例如KNN和KMeans的k值,支持向量机的C值,这些超参数是需要人为设定,没有办法让模型自己学习得到,我们只能通过经验或者多次训练比较,主观设定一个我们认为相对最优的值。而交叉验证的作用,就是让我们进行多次的模型训练比较。例如,我们期望从 [ 1, 10, 100, 1000 ] 这几个值中选择一个最优值,作为支持向量机的C值。那么我们就得分别用这4个值进行10折交叉验证(该过程经历了40次模型的训练测试),把每一次交叉验证结果的均值进行比较,从而选择出一个最优值。最优值选出来了,那么模型的超参数确定了,接下来,利用全量的数据(不要划分训练集测试集,而是用全部的数据)进行模型训练,训练出来的模型才是我们的最终模型。在此过程中可以看出,交叉验证帮助我们确定模型的超参数。这样训练出来的模型,是经过多次综合比较得出的相对最优模型,在一定程度上可以避免过拟合的问题,这就是为什么我们会说交叉验证可以避免过拟合。

      关于交叉验证和过拟合的问题,我就先谈这么多吧。(对于文章中表达的观点,欢迎指正与补充,谢谢。)

  • 相关阅读:
    ClickHouse 监控及备份 (三)ClickHouse 配置
    ClickHouse 监控及备份 (二)Prometheus&Grafana 的安装
    ClickHouse 监控及备份 (一)ClickHouse 监控概述
    ClickHouse 高级(八)运维(1)常见问题排查
    ClickHouse 高级(七)MaterializeMySQL 引擎
    ClickHouse 高级(六)物化视图
    使用Iperf调整网络
    WinForm中DataGridView的使用(四)
    数据库设计经验总结
    WinForm使用Label控件模拟分割线(竖向)
  • 原文地址:https://www.cnblogs.com/solong1989/p/9415606.html
Copyright © 2020-2023  润新知