作者:William Koehrsen
翻译:和中华
校正:李润嘉

本文约6000字,建议阅读15分钟。
本文从单棵决策树讲起,然后逐步阐明了随机森林的事情事理,并利用sklearn中的随机森林对某个真实数据集进行预测。
如今由于像Scikit-Learn这样的库的涌现,我们可以很随意马虎地在Python中实现数百种机器学习算法。它们是如此易用,以至于我们常日都不须要任何关于模型底层事情机制的知识就可以利用它们。虽然没必要理解所有细节,但理解某个机器学习模型大致是如何事情的仍旧有帮助。这使得我们可以在模型表现不佳时进行诊断,或者阐明模型是如何做决策的,这一点至关主要,尤其当我们想要说服别人相信我们的模型时。
在本文中,我们将先容如何在Python中构建和利用随机森林(Random Forest)。除了查看代码之外,我们还将考试测验理解此模型的事情事理。由于随机森林由许多决策树(decision tree)组成,以是我们先来理解一下单个决策树如何在一个大略的问题上进行分类。随后,我们将利用随机森林来办理一个现实天下中的数据科学问题。本文的完全代码在GitHub上以Jupyter Notebook的形式供应。
把稳:本文最初涌如今enlight上,这是一个社区驱动的开源平台,为那些希望学习机器学习的人供应教程。
理解决策树
决策树是随机森林的基本构成要素,而且是一种直不雅观的模型。我们可以将决策树视为一系列关于数据的是/否问题,从而终极得出一个预测种别(或回归情形下的连续值)。 这是一个可阐明的模型,由于它非常像我们人类进行分类的过程:在我们做出决定之前(在空想天下中),我们会对可用数据进行一系列的讯问。
决策树的技能细节在于如何形成关于数据的问题。在CART算法中,通过确定问题(称为节点的分裂)来构建决策树,这些问题在得到应答时会导致基尼不纯度(Gini Impurity)的最大减少。这意味着决策树试图形成包含来自单个类的高比例样本(数据点)的节点,这个过程通过在能将数据干净地划分为不同类的特色中找到适当的值来实现。
我们稍后会商谈基尼不纯度的更底层细节,但首先,让我们构建一个决策树,以便我们能够在高层次上理解它。
大略问题上的决策树
我们将从一个非常大略的二元分类问题开始,如下所示:
目标是把数据点划分到各自所属的类
我们的数据只有两个特色(预测变量),x1和x2,共有6个数据点(样本),被分为2个不同的标签。虽然这个问题很大略,但它不是线性可分的(linearly separable),这意味着我们不能绘制一条通过数据的直线来对点进行分类。
然而,我们可以绘制一系列直线,将数据点划分入多个框,我们称这些框为节点。 事实上,这便是决策树在演习期间所做的事情。实际上决策树是通过布局许多线性边界而构建的一个非线性模型。
我们利用Scikit-Learn来创建决策树并在数据上演习(拟合)。
在演习过程中,我们为模型供应特色和标签,以帮助它学习如何根据特色对点进行分类。(针对这个大略问题我们没有测试集,在测试时,我们只为模型供应特色值并让它对标签进行预测。)
我们可以在演习数据上测试模型的准确性:
可以看到它得到了我们所期望的100%的准确性,这是由于我们给了它演习的答案(y),并且没有限定树的深度。事实证明,在演习数据中过强的学习能力可能是一个缺陷,由于它可能导致过拟合(overfitting),我们将在稍后对此进行谈论。
可视化决策树
当我们演习决策树时到底发生了什么?可视化可以帮助我们更好地理办理议方案树,这可以通过Scikit-Learn的一个功能来实现(详细信息,请查看notebook或这篇文章)。
大略的决策树
除叶子节点(彩色终端节点)外,所有节点都有5个部分:
基于某个特色的一个值对数据进行的提问,每个提问都有一个真或假的答案可以分裂节点。根据答案,数据点相应地向下移动。gini:节点的Gini不纯度。当我们沿着树向下移动时,均匀加权基尼不纯度会减少。samples:节点中的不雅观测数据数量。value:每个类中的样本数。例如,根节点中有2个样本属于类0,有4个样本属于类1。class:该节点中大多数点的分类。在叶节点中,即是对节点中所有样本的预测。
叶节点中不再提问,由于这里已经产生了终极的预测。要对某个新数据点进行分类,只需沿着树向下移动,利用新点的特色来回答问题,直达到到某个叶节点,该叶节点对应的分类便是终极的预测。
为了以不同的办法查看树,我们可以在原始数据上绘制由决策树构建的分割。
决策树构建的分割
每个分割都是一条线,它根据特色值将数据点划分到不同节点。对付这个大略的问题并且对最大深度没有做出限定,划分终极把每个点放置在仅包含同类点的一个节点中。(再次提醒,稍后我们将看到演习数据的这种完美划分可能并非我们想要的,由于它可能导致过拟合)
基尼不纯度(Gini Impurity)
是时候深入理解基尼不纯度的观点了(数学并不吓人!
)节点的基尼不纯度是指,根据节点中样本的分布对样本分类时,从节点中随机选择的样本被分错的概率。例如,在根节点中,根据节点中的样本标签有44.4%的可能性缺点地对某个随机选择的数据点进行分类。可以利用以下等式得出这个值:
节点n的基尼不纯度
节点n的基尼不纯度是1减去每个类(二元分类任务中是2)的样本比例的平方和。有点拗口,以是我们来一起打算出根节点的基尼不纯度。
根节点的基尼不纯度
在每个节点,决策树要在所有特色中搜索用于拆分的值,从而可以最大限度地减少基尼不纯度。(拆分节点的另一个替代方法是利用信息增益)。
然后,它以贪婪递归的过程重复这种拆分,直到达到最大深度,或者每个节点仅包含同类的样本。树每层的加权总基尼不纯度一定是减少的。在树的第二层,总加权基尼不纯度值为0.333:
(每个节点的基尼不纯度按照该节点中来自父节点的点的比例进行加权。)你可以连续为每个节点打算基尼不纯度(可视化图中有答案)。 就这样,从一些基本的数学中,出身了一个强大的模型!
终极,末了一层的加权总基尼不纯度变为0,也意味着每个节点都是完备纯粹的,从节点中随机选择的点不会被缺点分类。虽然这统统看起来挺好的,但这意味着模型可能过拟合,由于所有节点都是仅仅利用演习数据构建的。
过拟合:为什么森林比一棵树更好
你可能会想问为什么不能只用一个决策树呢?它彷佛很完美,由于它没有犯任何缺点!
但别忘了这个关键点,即这棵树是在演习数据上没有犯错。我们早已估量会涌现这种情形,由于我们给树供应了答案,而且没有限定最大深度(树的层数)。然而,机器学习模型的目标是可以对从未见过的新数据很好地泛化。
过拟合发生在当我们有一个非常灵巧的模型(模型具有高能力)时,实在质上是通过紧密拟合来记住演习数据。这样的问题是模型不仅学到了演习数据中的实际关系,还学习了存在的噪声。灵巧的模型具有高方差(variance),由于学到的参数(例如决策树的构造)将随着演习数据的不同而变革很大。
另一方面,由于对演习数据做出了假设,以是一个不灵巧的模型具有较高的偏差(bias),(它倾向于对数据预先构思的想法)例如,线性分类器假设数据是线性的,不具备拟合非线性关系的灵巧性。一个不灵巧的模型乃至可能无法拟合演习数据,在高方差和高偏差这两种情形下,模型都无法很好地泛化到新数据之上。
一个能记住演习数据的非常灵巧的模型与不能学习演习数据的不灵巧模型之间的平衡称为偏差-方差权衡(bias-variance-tradeoff),它是机器学习中的一个基本观点。
当我们不限定最大深度时决策树随意马虎过拟合的缘故原由是它具有无限的灵巧性,这意味着它可以持续成长,直到它为每个单独的不雅观察点都天生一个叶节点,达到完美地分类。如果返回到之前决策树的图像并将最大深度限定为2(仅进行一次拆分),则分类不再100%精确。我们减少了决策树的方差,但代价是增加了偏差。
限定树的深度可以减少方差(好)并且增加偏差(坏),一种替代方案是,我们可以将许多决策树组合成一个称为随机森林的集成模型(ensemble model)。
随机森林
随机森林是由许多决策树组成的模型。这个模型不是大略地均匀所有树(我们可以称之为“森林”)的预测,而是利用了两个关键观点,名字中的随机二字也是由此而来:
在构建树时对演习数据点进行随机抽样分割节点时考虑特色的随机子集
随机抽样演习不雅观测数据
在演习时,随机森林中的每棵树都会从数据点的随机样本中学习。样本被有放回的抽样,称为自助抽样法(bootstrapping),这意味着一些样本将在一棵树中被多次利用。背后的想法是在不同样本上演习每棵树,只管每棵树相对付特定演习数据集可能具有高方差,但总体而言,全体森林将具有较低的方差,同时不以增加偏差为代价。
在测试时,通过均匀每个决策树的预测来进行预测。这种在不同的自助抽样数据子集上演习单个学习器,然后对预测进行均匀的过程称为bagging,是bootstrap aggregating的缩写。
用于拆分节点的随机特色子集
随机森林中的另一个紧张观点是,只考虑所有特色的一个子集来拆分每个决策树中的每个节点。常日将其设置为sqrt(n_features)以进行分类,这意味着如果有16个特色,则在每个树中的每个节点处,只考虑4个随机特色来拆分节点。(随机森林也可以在每个节点处考虑所有的特色,如回归中常见的那样。这些选项可以在Scikit-Learn Random Forest的实现中掌握)。
如果你能理解一棵单独的决策树,bagging的理念,以及随机的特色子集,那么你对随机森林的事情办法也就有了很好的理解:
随机森林将成百上千棵决策树组合在一起,在略微不同的不雅观察集上演习每个决策树,在每棵树中仅考虑有限数量的特色来拆分节点。随机森林的终极预测是通过均匀每棵树的预测来得到的。想理解为什么随机森林优于单一的决策树,请想象以了局景:你要判断特斯拉的股票是否上涨,现在你身边有十几位对该公司都没有先验知识的剖析师。每个剖析师都有较低的偏见,由于他们没有任何假设,并且可以从新闻宣布的数据集中学习。
这彷佛是一个空想的情形,但问题是宣布中除了真实的旗子暗记外也可能包含噪音。 由于剖析师们完备根据数据做出预测,即他们具有很高的灵巧性,也就意味着他们可能会被无关的信息所旁边。剖析师们可能会从同一数据集中得出不同的预测。此外,如果供应不同的宣布演习集,每个剖析师都有高方差,并得出截然不同的预测。
办理方案是不依赖于任何一个人,而是搜集每个剖析师的投票。此外,与随机森林一样,许可每个剖析师仅利用一部分宣布,并希望通过采样来肃清噪声信息的影响。在现实生活中,我们也依赖于多种信息来源(从不信赖亚马逊的单独评论),因此,不仅决策树的思想很直不雅观,而且将它们组合在一起成为随机森林的想法同样如此。
实践中的随机森林
接下来,我们将在Python中用Scikit-Learn构建一个随机森林。我们不是学习一个大略的问题,而是会利用一个被分为演习集和测试集的真实数据,我们利用测试集来估计模型对新数据的性能,这也可以帮我们确定模型过拟合的程度。
数据集
我们要办理的问题是一个二元分类任务,目的是预测个人的康健状况。数据集的特色代表个人的社会经济和生活办法,标签为0表示康健状况不佳,1表示身体康健。该数据集由疾病掌握和预防中央网络,可在此处获取。
数据样本
常日,一个数据科学项目80%的事情是在洗濯,探索和提取数据中的特色。然而这篇文章我们的重点在于建模(有关其他步骤的详细信息,请参阅本文)。
这是一个不平衡的分类问题,因此准确率(accuracy)并不是一个得当的衡量指标。作为替代,我们将利用ROC和AUC,AUC是一个从0(最差)到1(最佳)的度量值,随机预测得分为0.5。我们还可以绘制ROC曲线来评估模型。
这个notebook包含了决策树和随机森林的实现,但在这里我们只关注随机森林。 在读取数据后,我们就可以实例化并且演习一个随机森林,详细如下:
在几分钟的演习后,模型已准备好对测试数据进行预测了,如下:
我们预测分类(predict)以及预测概率(predict_proba)来打算ROC AUC。一旦我们有了对测试集的预测结果,我们就可以打算出ROC AUC。
结果
随机森林的终极测试集ROC AUC为0.87,而具有无限最大深度的单一决策树的终极测试集ROC AUC为0.67。如果查看演习分数,则两个模型都达到了1.0的 ROC AUC,这也是可以预见到的,由于我们给这些模型供应了演习答案,并且没有限定每棵树的最大深度。
虽然随机森林过拟合了(在演习数据上比在测试数据上做得更好),但在测试数据上它比单一决策树泛化地更好。随机森林具有较低的方差(好处),同时能保持与一棵决策树相同的低偏差(也是好处)。
我们还可以绘制单个决策树(顶部)和随机森林(底部)的ROC曲线。靠近左上角的曲线代表着更好的模型:
决策树ROC曲线
随机森林ROC曲线
随机森林明显优于单一决策树。
另一个我们可以采取的模型诊断方法是绘制测试集预测结果的稠浊矩阵(详细信息,请参阅notebook):
在左上角和右下角它显示了模型的精确预测,在左下角和右上角显示了模型误判的预测。我们可以利用这类图来诊断我们的模型,来决定它是否表现的足够良好并可以投入生产。
特色主要性(Feature Importances)
随机森林中的特色主要性表示在该特色上拆分的所有节点的基尼不纯度减少的总和。我们可以利用它来考试测验找出随机森林认为最主要的预测变量。可以从一个演习好的随机森林中提取特色主要性,并将其放入Pandas的DataFrame中,如下所示:
通过见告我们哪些变量在类之间最具辨别力,特色主要性可以让我们更好地洞察问题。例如,DIFFWALK是表明患者是否行走困难的的主要的特色,这在问题的高下文中也说得通。
通过从最主要的特色中构建额外的特色,特色主要性可以被用于特色工程(feature engineering)。我们还可以通过删除不主要的特色,来把特色主要性用于特色选择。
可视化森林中的树
末了,我们可以可视化在森林中的单个决策树。这次我们必须限定树的深度,否则它将太大而无法被转换为一幅图像。为了制作下图,我将最大深度限定为6。但这仍旧产生了一棵我们无法完备解析的大树!
不过由于我们深入地研究过决策树,我们还是可以通过这幅图节制这个模型的事情事理。
随机森林中的单棵决策树
下一步
下一步是利用Scikit-Learn中的RandomizedSearchCV通过随机搜索来优化随机森林。优化是指在给天命据集上找到模型的最佳超参(hyperparameters)。最佳超参将随着数据集的不同而变革,因此我们必须在每个数据集上单独实行优化这也称为模型调度(model tuning)。
我喜好将模型调度视为给一个机器学习算法探求最佳设置。我们可以在随机森林中优化的东西包括决策树的数量,每个决策树的最大深度,拆分每个节点的最大特色数量,以及叶子节点中所能包含的最大数据点数。
有关随机森林模型优化的随机搜索的详细实现,请参阅Jupyter Notebook。
完全的运行示例
下面的代码是利用repl.it创建的,它展示了Python中随机森林的一个完全的交互式运行示例。你可以随意运行和变动代码(加载包可能须要一些韶光)。
建议查看原文中的交互环境
结论
虽然我们不须要理解底层事理就可以在Python中构建功能强大的机器学习模型,但我创造理解幕后发生的事情会更有效。在本文中,我们不仅在Python中构建和利用了随机森林,而且我们还从根本出发理解了该模型。
我们首先查看了单独的决策树,这也是一个随机森林的基本构成要素,然后我们学习了如何通过在一个称为随机森林的集成模型中组合数百个决策树来办理单个决策树的高方差问题。随机森林可以总结为利用不雅观测数据的随机抽样,特色的随机抽样并且均匀各个树的预测。
从这篇文章中理解到的关键观点是:
决策树:一种直不雅观的模型,可根据讯问有关特色值的一系列问题做出决策。具有低偏差和高方差的特色,这会导致过拟合演习数据。基尼不纯度:决策树在拆分每个节点时考试测验最小化的度量。表示根据节点中的样本分布对随机选择的样本分类缺点的概率。自助抽样法:有放回地对不雅观察值进行随机采样。随机特色子集:考虑对决策树中每个节点的分割时,选择一组随机特色。随机森林:利用自助抽样法,随机特色子集和均匀投票来进行预测的由许多决策树组成的凑集模型。这是Bagging的一个例子。偏差方差权衡:机器学习中的核心问题,描述了具有高灵巧性(高方差),即可以很好地学习演习数据,但以捐躯泛化新数据的能力的模型,与无法学习演习数据的不灵巧(高偏差)的模型之间的平衡。随机森林减少了单个决策树的方差,从而可以更好地预测新数据。
希望本文为你供应了在项目中利用随机森林所需的信心和对事理的理解。随机森林是一种强大的机器学习模型,但这不应该阻挡我们理解它的事情机制。我们对模型的理解越多,我们就越有能力有效地利用它并阐明它如何进行预测。
一如既往,欢迎进行评论反馈和培植性的批评。可以通过Twitter @koehrsen_will与我联系。本文最初发布于enlight,一个用于研究机器学习的开源社区。感谢enlight和用来托管文中代码的repl.it。
原文标题:An Implementation and Explanation of the Random Forest in Python副标题:A guide for using and understanding the random forest by building up from a single decision tree原文链接:https://towardsdatascience.com/an-implementation-and-explanation-of-the-random-forest-in-python-77bf308a9b76译者简介
和中华,留德软件工程硕士。由于对机器学习感兴趣,硕士论文选择了利用遗传算法思想改进传统kmeans。目前在杭州进行大数据干系实践。加入数据派THU希望为IT同行们尽自己一份绵薄之力,也希望结交许多志趣相投的小伙伴。
— 完 —
关注清华-青岛数据科学研究院官方微信公众年夜众平台“THU数据派”及姊妹号“数据派THU”获取更多讲座福利及优质内容。