
随机森林
Random Forest
谈及随机森林算法的产生与发展,我们必须回溯到20世纪80年代。可以说,该算法是Leo Breiman, Adele Cutler, Ho Tin Kam, Dietterich, Amit和Geman这几位大师呕心沥血的共同结晶,他们中的每个人都对随机森林算法的早期发展作出了重要的贡献。Leo Breiman和 Adele Cutler最早提出了执行随机森里的关键算法,这一算法也成为了他们的专利之一。Amit, Gemen和Ho Tim Kam各自独立地介绍了特征随即选择的思想,并且运用了Breiman的“套袋”思想构建了控制方差的决策树集合。在此之后,Deitterich在模型中引入了随即节点优化的思想,对随机森里进行了进一步完善。
近年来,随机森林模型在界内的关注度与受欢迎程度有着显著的提升,这多半归功于它可以快速地被应用到几乎任何的数据科学问题中去,从而使人们能够高效快捷地获得第一组基准测试结果。在各种各样的问题中,随机森林一次又一次地展示出令人难以置信的强大,在各种数据竞赛中也展示出了广泛的适用性和强大的解题能力。
随机森林顾名思义,是用随机的方式建立一个森林,森林里面有很多的决策树组成,随机森林的每一棵决策树之间是没有关联的。在得到森林之后,当有一个新的输入样本进入的时候,就让森林中的每一棵决策树分别进行一下判断,看看这个样本应该属于哪一类(对于分类算法),然后看看哪一类被选择最多,就预测这个样本为那一类。
深入了解随机森林
集成学习(Ensemble Learning)
集成学习是解决单个预测问题的数个模型的组合。集成学习通过生成多个独立学习并进行预测的分类器/模型生效。然后这些预测结果被组合成一个预测,这个预测的准确率应当等于或大于任一分类器做出的预测。随机森林是集成学习中非常有效的一种,因为它依赖于许多决策树的集合。
随机决策树(Randomized Decision Trees)
我们已经知道随机森林是其他模型的聚合,那么它聚合的是哪些模型呢?正如它的名字所示,随机森林是分类(或回归)决策树的聚合,决策树由一系列能够用于对一个数据集的观察进行分类的决策组成。
随机森林(Random Forest)
诱发随机森林的算法将自动创建许多随机决策树。由于这些树是随机生成的,它们大多数(大概99.9%)不会对学习分类/回归问题有影响。
如果观察到长度为45,眼睛是蓝色,并且有两条腿,那么它将被归类为红色。
为什么使用随机森林
简单容易上手
随机森林就像学习方法中的瑞士军刀,任何东西它都可以给你修好。随机森林尤其擅长预估推断变换(inferred transformations),因此,它不需要像 SVM 那样进行很多调试。
有关变换的一个例子
随机森林能够在没有精心设计的数据变换(data transformations)的环境下学习。以 f (x) = log(x)函数为例。首先,制造一些不真实数据(fake data)来加入一点噪音。
import numpy as np
x = np.random.uniform(1, 100, 1000)
y = np.log(x) + np.random.normal(0, .3, 1000)
如果我们尝试建一个基本线性模型来用 x预测 y,我们需要作一条直线来平分 log (x)。但如果我们使用随机森林,能得到一条接近 log (x)的曲线,看起来更像实际的函数。
你可能认为随机森林对 log (x)函数过度拟合了。不管怎么说,我觉得它很好地说明了随机森林不受线性约束的限制。
随机森林的用途
特征选择
随机森林的最佳使用实例之一是特征选择(feature selection)。尝试许多决策树变量(variations)带来的副产品之一是,你可以检验每棵树中哪个变量最相关/无关。
当一棵树使用某个变量,而另一棵不用这个时,你可以比较包含/排除该变量时丢失或得到的值。在下面的例子中,我们试图找出哪些变量在将酒分类为红酒和白酒的任务中最重要。
分类
随机森林也很擅长分类任务。它能用于对具有多个可能值的类别进行预测,也能被校准来输出概率。需要注意的是过拟合(overfitting)。随机森林可能容易过拟合,尤其是使用相对小型的数据集时。如果你的模型在我们的测试集中表现“太好”,就应该怀疑过拟合了。
引起过拟合的原因之一是在模型中只使用真正相关的特征。虽然不是固定的方式,但使用一些特征选择技术(例如前文提到的)可以避免过拟合。
回归
随机森林不像其他算法——在学习分类变量或分类变量和真实变量的结合时真的很有效。高基数的分类变量处理起来很棘手,因此随机森林会大有帮助。
一个 Python 实现的例子
Scikit-Learn 对开始使用随机森林的人来说非常友好。Scikit-Learn API 在各种算法中都非常一致,因此可以很容易地在模型之间进行比较和切换。多数时候我会从简单的地方开始,再转移到随机森林。
随机森林在 scikit-learn 中实现得最好的特征之一是 n_jobs 参数。它会根据你想要使用的核的数量自动并行拟合随机森林。这里是scikit-learn的贡献者Olivier Grisel的一个很棒的报告,在这个报告中他谈论了使用20个节点的EC2集群训练随机森林。
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
import pandas as pd
import numpy as np
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['is_train'] = np.random.uniform(0, 1, len(df)) <= .75
df['species'] = pd.Factor(iris.target, iris.target_names)
df.head()
train, test = df[df['is_train']==True], df[df['is_train']==False]
features = df.columns[:4]
clf = RandomForestClassifier(n_jobs=2)
y, _ = pd.factorize(train['species'])
clf.fit(train[features], y)
preds = iris.target_names[clf.predict(test[features])]
pd.crosstab(test['species'], preds, rownames=['actual'], colnames=['preds'])