前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >机器学习调优实战

机器学习调优实战

作者头像
陆勤_数据人网
发布2018-02-28 11:33:59
5920
发布2018-02-28 11:33:59
举报

导语

机器学习算法性能很差怎么办?过拟合和欠拟合是什么?调优方法有哪些?如何高效运用trick?

大家知道最近 A.I 非常火,经常看到各种相关技术介绍,像什么论坛啊、牛人讲座啊,当然网上也有很多非常好的大牛的教程,像最近公司刚跟优达学城合作,提供了很多免费的课程。相信大家或多或少都了解到一些机器学习的相关技术和算法了,有些同学可能也用过一些算法,然后就感觉自己可以称之为"懂机器学习"了。我曾经也是这么认为的,但是后来发现真正懂机器学习的人是确实知道如何高效运用的,而另一些人,像我这种,其实并没有完全理解,所以总是把时间浪费在一些毫无意义的尝试上面。最近我在学习吴恩达的 Machine Learning 课程中看到他讲的关于如何高效对机器学习效果进行调优的内容,感觉非常有用,想给大家分享下。

大概会从三个方面进行介绍,首先会给大家讲一个简单的例子,了解为什么要做调优这件事情。然后会介绍一些具体的调优方法。最后会对这些调优方法进行一个总结概括。

一、引子

我们都知道机器学习的应用范围很广,算法也有很多种,耳熟能详像逻辑回归,SVM,神经网络等算法。在用这些算法的过程中可能会遇到效果不能达到预期的情况,这个时候就需要对算法和模型进行调优。我们先来看一个例子。

1. 过拟合

这里我们来看一个识别天鹅的例子:

(1)打个形象的比方,有一些天鹅的图片,让机器通过这些图片来学习天鹅的特征,经过训练后,知道了天鹅是有翅膀的,天鹅的嘴巴是长长的弯曲的,天鹅的脖子是长长的有点曲度,天鹅的整个体型像一个"2"且略大于鸭子。这时候机器已经基本能区别天鹅和其他动物了。

(2)然后,很不巧已有的天鹅图片全是白天鹅的,于是机器经过学习后,会认为天鹅的羽毛都是白的,以后看到羽毛是黑的天鹅就会认为那不是天鹅。

好,来分析一下上面这个例子:(1) 中的规律都是对的,所有的天鹅都有的特征,是全局特征;然而,(2) 中的规律:天鹅的羽毛是白的。这实际上并不是所有天鹅都有的特征,只是局部样本的特征。机器在学习全局特征的同时,又学习了局部特征,这才导致了不能识别黑天鹅的情况。

机器在学习过程中是无法区别局部特征和全局特征的,学习的局部特征比重越多,那么新样本中不具有这些局部特征但具有所有全局特征的样本也越多,于是机器能识别到的正确样本的概率就会下降,也就是所谓的"泛化性"变差,这是过拟合会造成的最大问题。

所谓过拟合,就是指把学习进行的太彻底,把样本数据的几乎所有特征都学习到了,于是机器学到了过多的局部特征,过多的由于噪声带来的假特征,造成模型的"泛化性"和识别正确率几乎达到谷点,于是用这个机器识别新的样本的时候会发现就没几个是正确识别的。

解决过拟合的方法,其基本原理就是限制机器的学习,使机器学习特征时学得不那么彻底,因此这样就可以降低机器学到局部特征和错误特征的几率,使得识别正确率得到优化。

从上面的分析可以看出,要防止过拟合,训练数据的选取也是很关键的,良好的训练数据本身的局部特征应尽可能少,噪声也尽可能小。

2.欠拟合

我们再来看一下对应欠拟合的情况。同样让机器学习一堆天鹅图片的特征,然后经过训练后,知道了天鹅是有翅膀的,天鹅的嘴巴是长长的。因为具备这两个特征的动物很多,像鸭子、鹦鹉都具有这些特征,所以这时候让机器去区别天鹅和其他动物,效果是很差的。因为机器学习到的天鹅特征太少了,导致区分标准太粗糙,不能准确识别出天鹅。这个时候就需要去扩充天鹅的特征,让特征更为具体些。

二、调优方法选取

为了避免过拟合和欠拟合的情况,我们可以进行哪些优化呢?一提到模型优化,可能我们最容易想到的就是增大或者减小训练集,这算是一个方向;获取更多或者更少特性,这也是一个方向;除此以外,还有一些增加多项式特征、增加或者减少正则化参数λ等都是行之有效的方法。如下所示:

• 获取更多训练样本

• 尝试少些特征

• 尝试增大λ

• 尝试更多特征 • 尝试增加多项式特征(

• 尝试减小λ

这上面列的很多方法都可以扩展成一个六个月或者更长时间的项目。其实大部分人都是随随便便试一试,可能花费了六个月后发现这是一条不归路。其实是可以通过诊断,排除掉单子上至少一半的方法,留下真正有效的方法的,这样的话,可以节省大量不必要的时间开销。那到底如何做到这一点呢?接下来让我们看看如何判断什么时候该选取什么方法。

1.假设函数(hypothesis function)

为了介绍判断方法,我们首先来了解下假设函数。我们来看个预测房价的例子,如下图所示,这里仅考虑房屋面积对房价的影响。红叉叉是实际房价,蓝线是预测的房价。

如果我们用一条直线来拟合实际房价,如下图中左图所示,可以看到这些红叉叉基本上都不在蓝线上,并且有一定偏差。

为了更好的拟合这些红叉叉,我们改用一个 2 次函数来拟合,如中间这幅图所示,可以看到这些红叉叉基本上都在蓝线上或者临近的地方,偏差不算太大。

我们想继续减小偏差,于是用一个 4 次函数来拟合,如右图所示,可以看到几乎所有红叉叉都在线上,偏差趋于 0。

以上所用的这些函数就是假设函数。可以看到随着假设函数的次数越来越高,越来越复杂,对样本的拟合程度会越来越好。但是大家有没有想过,如果用右边这个函数来预测房价会有什么问题吗?因为这个函数对训练样本,也就是上面这些红叉叉拟合得太精确了,导致了过拟合,所以如果要预测一个训练集中从未出现过的样本的时候,它会缺乏预测能力,效果会很差。当然效果的好坏并不能全凭我们肉眼观察,特别对于更多样本、更多维度等更复杂的情况,我们应该如何选取最佳的假设函数呢。

2.评估假设函数 1.0

让我们来看看评估假设函数效果的方法。这里我们仍然以预测房价为例子,我们有一个 10 个数据样本的数据集,从中随机选择 7 个样本作为训练集,剩下 3 个作为测试集,为什么这么选,是因为 70%,30%这种配比是最常见的一种,当然也可以有其他选择。

这里我们要评估 10 种线性回归的假设函数,如上图所示,通过分别针对每个假设函数进行训练,最小化训练集的偏差,我们可以得到每个假设函数的参数 θ;然后把参数代入假设函数中,去计算测试集的总偏差,对比每个假设函数的测试集总偏差,选出最小的那个,就是我们认为最好的假设函数了。

这里提出一个问题。如上所示,可能大家会说简直是送分题,不就是 h5 吗?其实并不一定。因为 h5 是在特定测试集上的效果最好,所以它对于这个测试集中的那些样本是适配得最好的,但是如果换一个测试集就不一定了。所以如果以此作为判断来选取假设函数,其实并不公平。这样选取出来的假设函数对于从未出现过的新样本来说,并不一定支持得很好。所以为了解决这个问题,下面介绍改良版的评估假设函数的方法。

3.评估假设函数 2.0

同样我们有 10 个样本,然后从中随机选取 60%作为训练集,20%作为交叉验证集(cross validation),剩下 20%作为测试集。60%,20%,20%,这种配比,也是一种常规选择方法,当然也可以有所变化。

同样我们分别将 10 个假设函数用于训练集的训练,通过最小化训练集上的总偏差得到参数θ,然后分别将θ用于交叉验证集,计算出各自在交叉验证集上的总偏差,以此作为标准,对比选出最小的那个,例如是 h5,然后将 h5 对应的参数θ在测试集上进行验证,计算出测试集上的总偏差,这才能评估 h5 这个假设函数真正的性能。

4.高偏差 vs 高度不一致诊断

实际情况中我们不可能穷举所有假设函数,对比选出他们中效果最好的那个。我们只会选取少数几个假设函数进行评估,那么当我们针对一个假设函数,算出训练集和交叉验证集的偏差后,如何选择方法进行下一步优化呢?这里画一张关于假设函数的维度大小跟数据集总偏差的关系图:

横坐标是假设函数的维度,也就是前面所说的 1 次、2 次这种。纵坐标是数据集的总偏差。这里包括训练集和交叉验证集的总偏差两种。

我们知道当维度很低时,如一次函数,非常简单,所以在拟合训练集时,偏差会很大,同样把它用在交叉验证集上时,偏差也是很大的。但是因为有针对训练集做参数优化,所以交叉验证集的偏差还是会比训练集更大一些。所以就画出图上左边这部分,此时就是所谓的欠拟合状态,习惯上也叫高偏差状态,即训练集和交叉验证集的偏差都很高。

然后增加维度,如我们前面所说的 2 次函数,它的复杂性会适当提高,于是能更好的拟合训练集上的样本,于是训练集上的偏差会降低。对于交叉验证集来说,也会拟合得更好,所以交叉验证集的偏差也会降低。

继续增大维度,当维度过大时,如前面所说的 4 次函数,它的复杂性很高,所以对于训练集来说可以非常好的拟合,于是训练集偏差会继续下降,甚至趋于 0。但是因为复杂度过高,对于新样本泛化能力会变弱,所以对于交叉验证集来说,偏差会大大提高。即图中右边部分。此时就是过拟合状态,习惯上也叫高度不一致状态,即训练集的偏差和交叉验证集的偏差高度不一致。

通过这幅图可以看出:

  • 在高偏差的时候,训练集和交叉验证集的偏差都很大,且相近;
  • 而在高度不一致的时候,训练集的偏差很小,但是交叉验证集的偏差非常大,远远大于训练集偏差。

所以通过这种性质就能判断模型当前是高偏差还是高不一致,就可以对此采用行之有效的方法去解决。如果发现是高偏差可以提高假设函数的维度,如果是高不一致可以降低假设函数的维度。这就是一种解决方法。下面我们来认识另一种解决方法——正则化。

5.正则化

在实际应用中欠拟合的状态是比较容易发现的,因为在训练时就可知道,但是过拟合是比较难发现的。为了防止过拟合,我们在训练时,对训练集总偏差引入一个正则化项,也就是下图中黄色框框所示这部分,它的目的是让参数尽可能小,避免参数过多过大。

例如:对于这个 4 次假设函数来说,在它的总偏差后面加上这样一个正则化项,也就是将参数

的平方累加起来,前面乘上一个λ/2m,其中 m 是训练集样本数。

因为在训练模型时,我们的目的是让训练集的总偏差最小,所以在引入正则化项后,会更多的考虑让参数变小一些。特别是如果当 λ 非常大如 10000 时,参数

会趋近 0,这时候,我们的假设函数会约等于

,于是就变成一条直线,转变为欠拟合问题。相反,当 λ 很小,趋近于 0 时,就会让参数变大,于是就更倾向于没有正则化项的时候,也就是回到了过拟合问题。

既然 λ 这么有用,那么我们如何找到一个最佳的 λ 呢?

这里我们列出一系列 λ 的取值(通常会按照 0.01*2 的指数次方这种模式进行选取),针对每个 λ 进行训练,最小化训练集上的总偏差,得到各自对应的一组参数 θ,然后将各自的参数 θ 应用到交叉验证集上,算出交叉验证集上的总偏差 Jcv,然后对比选出最小的那个,这里假如是第 5 个,然后就用

这一组参数对测试集进行验证,就得到了测试集上的总偏差。

这里提出一个思考,也是容易误解的地方,我之前也是不小心掉进了这个坑:

不是说在计算总偏差时要加上正则化项吗?为何计算测试集偏差时不加上呢?

其实不管是计算训练集、还是交叉测试集、还是测试集的总偏差时,都不用也不能加上正则化式,因为它只是在训练时为了提高训练效果采用的一个技巧而已,跟偏差本身并没有半毛钱关系。这点需要理解清楚,不然就没理解为啥要用 λ 。

为了进一步理解正则化参数 λ 对数据集偏差的影响,我们也来画一张它们之间的关系图:

当 λ 很大的时候,参数会变小,更倾向于一条直线,所以模拟函数会变简单,倾向于欠拟合,所以训练集偏差很大,交叉验证集的偏差也很大,且两者近似。

这时候减小 λ,参数会变大,模拟函数会稍微复杂一些,拟合程度会提高,所以训练集和交叉验证集的偏差都会降低。

继续减小 λ,到λ很小的时候,参数会继续变大,模拟函数会更复杂,拟合程度会更好,更容易出现过拟合,所以训练集偏差很小,但是交叉验证集偏差很大。

于是就得到图中这样两条曲线。中间会有一个点让交叉验证集上的偏差最小。对应的λ就是我们要求的最优 λ 。

所以可以根据这个图确定当前所处的状态,并可以据此调节 λ 来提高模型效果。

6.学习曲线(learning curves)

下面介绍另一种很有用的工具,学习曲线。通过画出学习曲线,也可以判断当前模型是否处于高偏差或者高不一致状态。学习曲线反应的是训练集大小跟数据集总偏差之间的关系,下面我们看下怎么画出一条学习曲线。

我们首先来画训练集的:

这里我们选取假设函数为一个二次函数,当样本数为 1 时,用二次函数很容易拟合一个点,误差绝对也很小,当样本数为 2 时也可以完全拟合,然后继续增加样本数到 3、4,也还是可以基本拟合,只是误差会逐渐变大一点。事实上随着训练集越来越大,会发现拟合所有点越来越困难了,也就是说误差会越来越大。于是我们得到一条学习曲线,如浅蓝色曲线所示。

那对交叉验证集来说误差又会如何变化呢?当训练集样本很少时,泛化程度很差,对新样本的适应能力很差,所以误差会非常大。随着训练样本的增加,泛化程度会越来越好,对新样本的适应能力会越来越强,所以误差会越来越小。就得到了关于交叉验证集的红色的这条学习曲线。

下面我们来看下过拟合和欠拟合,也可以是高偏差状态下的学习曲线是什么样子。

假设我们用一条直线来拟合我们的训练集,当只有一个样本的时候,可以完全拟合,所以误差为 0,然后随着样本的增加,它很快就不能很好的拟合这些样本了。所以误差会越来越大,当找到一个最佳拟合的直线后,再增大训练集,发现误差也不会有太大变化了,所以趋于平直。大致也就是淡蓝色曲线所示的样子。

而交叉验证集的误差如何变化呢?一开始同样因为泛化能力差,所以误差很大,然后随着样本增加,泛化能力变强所以误差会降低,然后等到找到最佳拟合直线后,误差就基本上不会怎么变化了,趋于平直,并且误差跟训练集相近。

所以在高偏差的情况下呢,无论如何增大训练集样本,训练集和交叉验证集的误差都会处于一个比较高的水平,而且两者比较接近。

所以当我们发现画出的学习曲线中,交叉验证集误差不会随着横坐标的增大而有明显下降,而是变为水平了,就说明算法处于高偏差的情况,这个时候增大训练集,对于改善算法并没有太大用处,所以也不要在这上面做太多无用功了。

接下来再让我们看下高不一致的情况吧。

我们选用一个超级复杂的假设函数,一个 100 次的函数,即使用了正则化,λ 也非常小。这时候如果要用这个函数去拟合几个点,会发现拟合得非常非常好,继续增大训练集,虽然误差有所上升,但仍然拟合得非常好。误差始终处于一个相对较低的水平。

但是对于交叉验证集误差来说又如何呢?同样当样本非常少时,由于缺乏泛化能力,所以误差很高,随着样本的增加,误差有所下降,但是因为存在过拟合的情况,所以交叉验证集的误差始终很高。所以在训练集和交叉验证集之间存在着一个很大的差距。

同时从图中可以看出如果继续增大训练集,也就是把图中的线往右边延伸,两条曲线是在逐渐逼近的,虽然训练集误差在增大,但我们更关注的交叉验证集的误差在减小,所以增大训练样本在过拟合的情况下是有意义的。

当然我们上面画的这些学习曲线都是理想情况下的,实际中可能会出现一点噪声或者干扰,但大体上还是差不多的。所以可以通过画出学习曲线,帮助我们去判断当前算法模型是处于高偏差还是高不一致,还是两者都有的情形。这样可以节省不少时间。

三、总结

通过前面介绍的这些判断方法,就可以判断当前算法模型所处状态,一旦我们确定当前算法是过拟合还是欠拟合后,就可以采取对应的方法进行调优了。

总结起来就是这些方法。

  • 针对过拟合
    • 获取更多训练样本
    • 尝试少些特征
    • 尝试增大 λ
  • 针对欠拟合
    • 尝试更多特征
    • 尝试增加多项式特征(

    • 尝试减小 λ

针对过拟合的场景:我们可以获取更多训练样本,这样可以覆盖更多场景。第二个呢,可以尝试少一些特征,这样模拟函数会简单一些。也可以尝试增大正则化参数 λ,这样函数参数会变小一些,模拟函数会更倾向于简单。

相反,针对欠拟合的情况呢:可以尝试更多特征,让模拟函数复杂一些;也可以尝试增加多项式特征,也是为了让模拟函数复杂一些。还可以尝试减小 λ,这样函数参数会变大一些,模拟函数会更倾向于复杂。

最后我们来看看在神经网络中,如何判断和解决过拟合欠拟合问题。

当设计神经网络算法时,首先要选择层次。最常用的神经网络是三层,也就是一个隐藏层,当神经网络层次很少,然后每一层的节点很少的时候,对应的参数就很少,模型就更简单,计算就更简单,但是也更容易出现欠拟合;

当神经网络层次很多,或者每一层的节点很多的时候,对应的参数就很多,模型就会很复杂,计算开销也会很大,也就更容易出现过拟合。一个很有效的避免过拟合的方法就是使用正则化项。前面我们也提到了增大正则化参数 λ 对避免过拟合的好处。

实际应用中可以把数据集拆分成训练集、交叉训练集和测试集,然后用交叉验证的方法来尝试多种层次和节点个数,对比他们的效果,最终选定一个最佳的神经网络结构。

感谢作者分享。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-06-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据科学与人工智能 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导语
  • 一、引子
    • 1. 过拟合
      • 2.欠拟合
      • 二、调优方法选取
        • 1.假设函数(hypothesis function)
          • 2.评估假设函数 1.0
            • 3.评估假设函数 2.0
              • 4.高偏差 vs 高度不一致诊断
                • 5.正则化
                  • 6.学习曲线(learning curves)
                  • 三、总结
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档