可以这么说,我们用机器学习建模的过程,就是和过拟合现象持续作斗争的过程。那么,什么是过拟合?我们怎么防止模型出现过拟合的问题呢?
什么是过拟合在我们解释概念前,请你先看一下某相亲平台给出的相亲结果的数据集示意图。
现在,我们假设你的机器学习模型根据这个数据集,给了你一个非常漂亮的函数。这个函数是:如果你不富也不帅,那么你在这个平台相亲就会失败;如果是其它任何一种情况,那你一定会成功。
你有没有感觉到哪里不对?其实,这个模型有一个很严重的问题,就是它过于准确了,犯了在训练集上过拟合的问题。
下面这张图片是嘲讽过拟合现象的,很有意思。 最左边是一堆数据点,中间的模型试图在这些杂乱无章的数据点中挖掘出一些规律,而最右边的模型精准地穿越了每个数据点,最后画出了一只猫。
最右边这个模型,对于当前训练集的挖掘不可谓不精准,但是请你想一想,用这么精细的模型,去套另外一组数据,不大可能会套出另外一只猫,因此这个模型无法泛化到其它数据,它当然就是一个很失败的猫分类模型。
而且,你可别以为模型对训练集的预测达到百分之百准确,是一件多难的事。它其实并不难,只要模型足够复杂,训练集上的精度可以想多高就多高。比如我们常见的决策树模型,它对回归问题和分类问题,都能达到 100% 的预测或分类准确率。因为决策树的原理就是在训练集上持续优化分割边界,直到完全正确为止。所以,就像我们开头在图中看到的那样,它在训练集上 R^2 的分数能达到满分。
这对我们来说是一个非常失败的模型,因为我们不是要一个复杂的、在训练集上预测完全精准的模型,而是想要构建一个泛化能力尽可能高的模型。如果一个模型能够对它没见过且性质相似的数据做出准确预测,那我们就可以认为它具有不错的泛化能力,这个模型就是相对成功的。
那为什么模型会出现过拟合的状态呢?其实,这是因为机器和我们程序员一样,都有强迫症。模型在针对训练集的优化过程中不找到最小的误差点,它们是不会停的。我们说,过拟合是机器学习模型在训练数据集上,通过拟合函数形成的。在过拟合的形成过程中,一般会经历三个阶段:欠拟合、平衡点和过拟合。
在初期的时候,模型对训练集的拟合还未完善,能力不够强, 偏差也比较大。此时的模型就处于欠拟合的状态,把模型应用于测试集数据,效果肯定也不好,所以还需要继续训练。
随着训练次数增多,以及模型自身的调整优化,模型的拟合能力变得越来越强,就差不多可以用了。此刻,实际上已经出现了欠拟合和过拟合之间的平衡点。
然而,如果训练继续进行,模型经过充分训练后,就会完全拟合训练集数据。如果把此时的模型应用于测试集,我们并不一定能得到好的效果,很容易出现很高的误差。这就是过拟合的状态。我们开头提到的决策树模型就明显处于这种状态。
这里说明一下,对于过拟合的讨论,我们多限于监督学习的应用范围,也就是回归和分类两大类问题。当然,也有人认为无监督学习中也存在过拟合现象,但是无监督学习中的过拟合被讨论的不多。所以,我们重点来看看回归和分类问题中的过拟合。
对于回归问题来说,你可以通过下面的图理解过拟合:
对于分类问题来说,你可以通过下面的图理解过拟合:
那么,解决过拟合问题的方法都有哪些呢?这里有三个思路:
一般来说,数据点少,模型很容易就能完全描绘出从特征到标签的映射。所以,增加数据集中数据的数量可以在一定程度上防止过拟合。如果特征工程做得不好,数据集中的无用信息多,就会放大过拟合的影响,因为模型描绘出来的是无用信息和标签之间关系,当然泛化能力就受影响。所以,进行优质的特征工程,筛除无用的特征,去芜取精,去伪存真,有利于避免过拟合。我们前面提到,模型比较复杂时,它在训练集上的精度可以想多高就多高,这是因为从数学的角度,多次函数的图像远远比一次、二次函数复杂。模型越复杂,所能够覆盖的特征空间就越大。所以,如果数据集较小,或者说问题比较简单,我们尽量选择简单的模型。凡事选择简单的解决方案,这个道理人称奥卡姆剃刀定理。因为数据集很难收集,特征工程又很考验机器学习工程师的水平,所以,防止过拟合的最佳策略就是要在模型的简单和复杂之间寻找一个平衡点。
决策树和线性回归模型比较容易出现过拟合问题,而随机森林则本身就可以基于决策树的过拟合问题实现优化,因此,下面我会带你看看怎么把决策树模型和线性回归模型简单化,来帮你进一步理解如何防止过拟合。
决策树模型的构造和剪枝决策树这个算法的原理很好理解,它就是将一大堆的 if…else 语句进行连接,直到最后得到想要的结果。算法中的各个节点是根据训练数据集中的特征形成的。在对特征节点的选择不同时,就可以生成很多不一样的决策树。
下图所示是一个相亲数据集和根据该数据集而形成的决策树。此处我们随机设定一个根节点——身高,作为我们决策的起点,从该点出发,根据数据集中的特征和标签值给树分叉。
生成一个决策树有两个阶段,分别是构造和剪枝。
那么什么是构造呢?构造就是选择什么特征作为节点生成决策树的过程。在构造过程中,有三种节点:
根节点:就是树的最顶端节点。在上图中,“高不高”就是根节点;内部节点:就是树中间的那些节点,比如说“富不富”、“美不美”;叶节点:就是树最底部的节点,也就是决策结果“同意”或者“不同意”。在这些节点之间存在一种父子关系。比如根节点会有子节点,子节点还有子节点,到了叶节点就停止了,不再有子节点。在构造过程中,我们可以根据信息增益的程度来选择哪个属性作为根节点;哪些属性作为子节点;什么时候停止并得到目标状态,也就是叶节点。
那么什么是信息增益呢,就是数据集的熵和选定某个特征的条件熵之差,而熵就是对随机变量不确定性的度量,熵越大不确定性越大。我们应该选择熵比较小的特征作为根节点,来增加信息的增益。
如果我们在构造的过程中,选择不同的特征作为根节点,然后根节点下面选择不同的特征形成内部节点,就可以得到另外一棵决策树,也就是一个新的模型:
由于 if…else 可以无限制地写下去,对于任何训练集,只要树的深度足够,决策树肯定能够达到 100% 的准确率。我们在前面讲过,这并不是一件好事,因为这样的模型认为其它所有数据的特点都和训练集中的数据完全一样的,所以它的泛化能力会很差。
对于这种情况,我们要在构造过程中对决策树进行剪枝,让树的深度不要太深,以免决策树太过于和精确。这样“模糊”一些的决策树,虽然在训练集上面的分数会降低,但是能够得到更强的泛化能力。
所以,针对具体数据集为模型选择适合的深度非常重要。下图所展示的就是一棵经过剪枝的决策树,剪枝之后树的深度从原来的 3 层变成了 2 层。
那上面这个数据集实际上是在用决策树解决分类问题,用的是决策树分类模型。我们再来看看下面这个决策树回归模型,对某个数据集中数据点的拟合示意图,相信你更能明白为什么我说树太深,就会对训练数据集拟合的太准,随之而来的也就会出现过拟合的现象了。
在这张图中,绿色线是当决策树深度为 5 是的模型拟合状态,蓝色线是决策树深度为 2 时的模型拟合状态。很明显,经过深度为 5 的模型训练集损失小,但深度为 2 的模型,泛化能力会更好。
其实,决策树的深度是一个可调的超参数,也就是 max_depth。这个超参数能限制树的最大深度,把超过设定深度的树枝全部剪掉,这也是最常见的剪枝策略。
线性回归模型的正则化线性回归模型,其实就是通过梯度下降确定参数的过程。如果数据集中有 3 个特征,公式就是:
y=w1x1+w2x2+w3x3+b
那么线性回归模型中的过拟合是如何产生的呢?如果在 x_{1}、x_{2}、x_{3} 这些特征中,有某个特征的值域较大,而如果模型拟合的结果中,其权重参数 w 的值也比较大,那么这个特征就会占据“主导”地位,使模型往这些较大值的位置偏移,形成了对这些值的“过拟合”。
那么,如果我们能让这类特征项的权重参数变小,也许就可以得到更为平衡的模型,来防止过拟合现象的出现。这种在一定程度上减小这些参数的值的方法,就是机器学习中的正则化(regularization)。具体来说,在损失函数当中加入的正则项也叫惩罚项,也就是给需要训练的函数加上一些规矩、一些限制,让它们不要自我膨胀。
线性回归的损失函数的正则项有两种添加方法,分别叫做 L1 正则项和 L2 正则项。
添加 L1 正则项之后,一些特征的权重会变小,一些绝对值较小的系数甚至直接变为 0(相当于抛弃了一些特征),来增强模型的泛化能力。这种回归也叫 Lasso 回归。
添加 L2 正则项之后,模型在不抛弃任何一个特征的情况下,会缩小回归系数,也就是某些特征的权重,让模型相对稳定,通常模型的泛化能力也更好。这种回归也叫 Rigde 回归。
其实,我们前面对决策树进行剪枝,避免过拟合,也可以称得上是一种正则化,因为剪枝过程也是对模型进行约束,不让树任意生长。如果多棵经过剪枝的决策树集合而成随机森林模型,那么这个模型其实也是一种正则化了的模型。