随机之美,随机森林

2017 年 8 月 25 日 Python开发者

(点击上方蓝字,快速关注我们)


来源:伯乐在线 - 云戒

如有好文章投稿,请点击 → 这里了解详情


摘要:随机森林和决策树相比,能更好的防止过拟合。虽然每个基分类器很弱,但最后组合的结果通常很强,这也类似于:“三个臭皮匠顶个诸葛亮”的思想。对比发现Random Forest(随机森林)和SVM(支持向量机)名列第一、第二名。


01 树与森林


在构建决策树的时候,可以让树进行完全生长,也可以通过参数控制树的深度或者叶子节点的数量,通常完全生长的树会带来过拟合问题。过拟合一般由数据中的噪声和离群点导致,一种解决过拟合的方法是进行剪枝,去除树的一些杂乱的枝叶。


注:你可能需要参考前面的文章:《0x0B 菩提决策树,姻缘算法求》


实际应用中,一般可用随机森林来代替,随机森林在决策树的基础上,会有更好的表现,尤其是防止过拟合。


在机器学习算法中,有一类算法比较特别,叫组合算法(Ensemble),即将多个基算法(Base)组合起来使用。每个基算法单独预测,最后的结论由全部基算法进行投票(用于分类问题)或者求平均(包括加权平均,用于回归问题)。


组合算法中,一类是Bagging(装袋),另一类是Boosting(提升),随机森林便是Bagging中的代表。使用多颗树进行单独预测,最后的结论由这些树预测结果的组合共同来决定,这也是“森林”名字的来源。每个基分类器可以很弱,但最后组合的结果通常能很强,这也类似于:“三个臭皮匠顶个诸葛亮”的思想。


《统计学习方法》作者李航博士的文章:http://blog.sina.com.cn/s/blog_7ad48fee0102vb9c.html 有说明:“来自JMLR(Journal of Machine Learning Research,机器学习顶级期刊)杂志的文章,有人让179种不同的分类学习算法在UCI 121个数据集上进行了“大比武”(UCI是机器学习公用数据集,每个数据集的规模都不大)。结果发现Random Forest(随机森林)和SVM(支持向量机)名列第一、第二名,但两者差异不大”。英文的原文在这儿http://jmlr.org/papers/v15/delgado14a.html, 感兴趣的可以参考。


上面文章换一种理解,即为:掌握了随机森林,基本上可以处理很多常见的机器学习问题。由此可见,组合算法在很多时候,其预测的性能都会优于单独的算法,这也正是随机森林的魅力所在。


02 处处随机


多个人组成的团队,是不是一定就强于一个人呢?团队的产出并不能把每个人的力量相加,并非和“众人拾柴火焰高”的道理一样。要让团队的总产出高于单个人的产出,那必须是每个人都有其它人不具备的知识或者能力,如果大家都是完全相同的知识或者能力,在解决难题上并没有帮助。假设对一个数据的预测,大家的结论都是1,最后组合结论依然是1,没有任何改变。对预测准确率,没有任何提升。


这也是“森林”前面还有“随机”这个修饰词的原因,随机就是让每个颗树不一样,如果都一样,组合后的效果不会有任何提升。假设每颗树不一样,单独预测错误率大概都是40%(够弱了吧,很多时候都会犯错),但三颗树组合的后的错误率就变成了35.2%(至少一半以上(两颗树)同时犯错结果才会犯错),其计算方法为:


3个全错(一种情况) + 2个错1个对(3种组合):

1 0.4^3 + 3 0.4^2 * (1-0.4)^1 = 0.352


因此,随机森林算法中,“随机”是其核心灵魂,“森林”只是一种简单的组合方式而已。随机森林在构建每颗树的时候,为了保证各树之间的独立性,通常会采用两到三层的随机性。


从数据抽样开始,每颗树都随机地在原有数据的基础上进行有放回的抽样。假定训练数据有1万条,随机抽取8千条数据,因为是有放回的抽样,可能原数据中有500条被抽了两次,即最后的8千条中有500条是重复的数据。每颗树都进行独立的随机抽样,这样保证了每颗树学习到的数据侧重点不一样,保证了树之间的独立性。


抽取了数据,就可以开始构建决策分支了,在每次决策分支时,也需要加入随机性,假设数据有20个特征(属性),每次只随机取其中的几个来判断决策条件。假设取4个属性,从这4个特征中来决定当前的决策条件,即忽略其它的特征。取特征的个数,通常不能太小,太小了使得单颗树的精度太低,太大了树之间的相关性会加强,独立性会减弱。通常取总特征的平方根,或者log2(特征数)+1,在scikit-learn的实现中,支持sqrt与log2,而spark还支持onethird(1/3)。


在结点进行分裂的时候,除了先随机取固定个特征,然后选择最好的分裂属性这种方式,还有一种方式,就是在最好的几个(依然可以指定sqrt与log2)分裂属性中随机选择一个来进行分裂。scikit-learn中实现了两种随机森林算法,一种是RandomForest,另外一种是ExtraTrees,ExtraTrees就是用这种方式。在某些情况下,会比RandomForest精度略高。


总结起来,使用随机性的三个地方:


  • 随机有放回的抽取数据,数量可以和原数据相同,也可以略小;

  • 随机选取N个特征,选择最好的属性进行分裂;

  • 在N个最好的分裂特征中,随机选择一个进行分裂;


因此,理解了这几个地方的随机性,以及随机性是为了保证各个基算法模型之间的相互独立,从而提升组合后的精度。当然,还需要保证每个基分类算法不至于太弱,至少要强于随机猜测,即错误率不能高于0.5。


03 sklearn与mllib


scikit-learn和spark中都实现了随机森林,但各自有些细小的区别。


在scikit-learn中,同样只是简单几行代码即可:


# sklearn_rf.py

import pandas as pd

from sklearn.ensemble import RandomForestClassifier

 

df = pd.read_csv('sklearn_data.csv')

train, test = df.query("is_date != -1"), df.query("is_date == -1")

y_train, X_train = train['is_date'], train.drop(['is_date'], axis=1)

X_test = test.drop(['is_date'], axis=1)

 

model = RandomForestClassifier(n_estimators=50,

                               criterion='gini',

                               max_features="sqrt",

                               min_samples_leaf=1,

                               n_jobs=4,

                           )

model.fit(X_train, y_train)

print model.predict(X_test)

print zip(X_train.columns, model.feature_importances_)


调用RandomForestClassifier时的参数说明:


  • n_estimators:指定森林中树的颗数,越多越好,只是不要超过内存;

  • criterion:指定在分裂使用的决策算法;

  • max_features:指定了在分裂时,随机选取的特征数目,sqrt即为全部特征的平均根;

  • min_samples_leaf:指定每颗决策树完全生成,即叶子只包含单一的样本;

  • n_jobs:指定并行使用的进程数;


从前面的随机森林构建过程来看,随机森林的每颗树之间是独立构建的,而且尽量往独立的方向靠,不依赖其它树的构建,这一特点,在当前的大数据环境下,尤其被人喜爱,因为它能并行,并行,并行……。


能完全并行的算法,一定会被人们追捧,在资源够的情况下,可以同时并行构建大量的决策树。scikit-learn虽然是单机版本,不能做分布式,但也可以利用单机的多枋来并行。


spark中,更是能发挥分布式的特点了:


from pprint import pprint

from pyspark import SparkContext

from pyspark.mllib.tree import RandomForest

from pyspark.mllib.regression import LabeledPoint

 

sc = SparkContext()

data = sc.textFile('spark_data.csv').map(lambda x: x.split(',')).map(lambda x: (float(x[0]), int(x[1]), int(x[2]), float(x[3]), int(x[4]), int(x[5])))

train = data.filter(lambda x: x[5]!=-1).map(lambda v: LabeledPoint(v[-1], v[:-1]))

test = data.filter(lambda x: x[5]==-1)#.map(lambda v: LabeledPoint(v[-1], v[:-1]))

 

model = RandomForest.trainClassifier(train,

                                     numClasses=2,

                                     numTrees=50,

                                     categoricalFeaturesInfo={1:2, 2:2, 4:3},

                                     impurity='gini',

                                     maxDepth=5,

                                 )

 

print 'The predict is:', model.predict(test).collect()

print 'The Decision tree is:', model.toDebugString()


和决策树版本相比,唯一的变化,就是将DecistionTree换成了RandomForest,另外增加了一个指定树颗数的参数:numTrees=50。


而和scikit-learn版本相比,spark中会通过categoricalFeaturesInfo={1:2, 2:2, 4:3}参数指定第5个属性(工作属性)具有3种不同的类别,因此spark在划分的时候,是按类别变量进行处理。而scikit-learn中,依然当成连续的变量处理,所以在条件判断的时候,才会有house


当有多个最优分割的时候,spark与scikit-learn在选择上也有区别,spark会按属性顺序进行选择,而scikit-learn会随机选择一个。这也是导致scikit-learn在多次运行中会输出0和1的问题。


scikit-learn中,还可以输出参数重要性,这也是决策树和随机森林的优点之一(目前pyspark还不支持输入参数重要性):


# scikit-learn中

print zip(X_train.columns, model.feature_importances_)


[(‘height’, 0.25), (‘house’,’car’, 0.0), (‘handsome’, 0.60), (‘job’, 0.0)]


04 特点与应用


随机森林基本上继承决策树的全部优点,只需做很少的数据准备,其他算法往往需要数据归一化。决策树能处理连续变量,还能处理离散变量,当然也能处理多分类问题,多分类问题依然还是二叉树。决策树就是if-else语句,区别只是哪些条件写在if,哪些写在else,因此易于理解和解释。


决策树的可解释性强 ,你可以打印出整个树出来,从哪个因素开始决策,一目了然。但随机森林的可解释性就不强了。所谓可解释性,就是当你通过各种调参进行训练,得出一个结论,你老大来问你,这个结论是怎么得出来的?你说是模型自己训练出来的,老大又问了,比如举一条具体的数据,你说一说得出结论的过程呢?因为随机森林引入了随机取特征,而且是由多颗树共同决定,树一旦多了,很难说清楚得出结论的具体过程。虽然可以打印每颗树的结构,但很难分析。


虽然不好解释,但它解决了决策树的过拟合问题,使模型的稳定性增加,对噪声更加鲁棒,从而使得整体预测精度得以提升。


因为随机森林能计算参数的重要性,因此也可用于对数据的降维,只选取少量几维重要的特征来近似表示原数据。同理,在数据有众多的特征时,也可以用于特征选择,选择关键的特征用于算法中。


随机森林还有天生的并行性,可以很好的处理大规模数据,也可以很容易的在分布式环境中使用。


最后,在大数据环境下,随着森林中树的增加,最后生成的模型可能过大,因为每颗树都是完全生长,存储了用于决策的全部数据,导致模型可能达到几G甚至几十G。如果用于在线的预测,光把模型加载到内存就需要很长时间,因此比较适合离线处理。


看完本文有收获?请转发分享给更多人

关注「大数据与机器学习文摘」,成为Top 1%

登录查看更多
0

相关内容

随机森林 指的是利用多棵树对样本进行训练并预测的一种分类器。

知识荟萃

精品入门和进阶教程、论文和代码整理等

更多

查看相关VIP内容、论文、资讯等
专知会员服务
42+阅读 · 2020年7月7日
【经典书】机器学习:贝叶斯和优化方法,1075页pdf
专知会员服务
404+阅读 · 2020年6月8日
【干货书】用于概率、统计和机器学习的Python,288页pdf
专知会员服务
287+阅读 · 2020年6月3日
【硬核书】可扩展机器学习:并行分布式方法
专知会员服务
85+阅读 · 2020年5月23日
已删除
将门创投
3+阅读 · 2018年3月13日
RF(随机森林)、GBDT、XGBoost面试级整理
数据挖掘入门与实战
7+阅读 · 2018年2月6日
机器学习面试题精讲(一)
七月在线实验室
4+阅读 · 2018年1月11日
算法|随机森林(Random Forest)
全球人工智能
3+阅读 · 2018年1月8日
超级干货 :一文读懂集成学习(附学习资源)
数据分析
9+阅读 · 2017年10月30日
为什么『无监督集成学习』乏人问津?
AI研习社
10+阅读 · 2017年10月24日
机器学习(17)之集成学习原理总结
机器学习算法与Python学习
19+阅读 · 2017年9月16日
Arxiv
110+阅读 · 2020年2月5日
Adaptive Neural Trees
Arxiv
4+阅读 · 2018年12月10日
Arxiv
7+阅读 · 2018年9月27日
Feature Selection Library (MATLAB Toolbox)
Arxiv
7+阅读 · 2018年8月6日
Arxiv
3+阅读 · 2017年7月6日
VIP会员
相关资讯
已删除
将门创投
3+阅读 · 2018年3月13日
RF(随机森林)、GBDT、XGBoost面试级整理
数据挖掘入门与实战
7+阅读 · 2018年2月6日
机器学习面试题精讲(一)
七月在线实验室
4+阅读 · 2018年1月11日
算法|随机森林(Random Forest)
全球人工智能
3+阅读 · 2018年1月8日
超级干货 :一文读懂集成学习(附学习资源)
数据分析
9+阅读 · 2017年10月30日
为什么『无监督集成学习』乏人问津?
AI研习社
10+阅读 · 2017年10月24日
机器学习(17)之集成学习原理总结
机器学习算法与Python学习
19+阅读 · 2017年9月16日
相关论文
Arxiv
110+阅读 · 2020年2月5日
Adaptive Neural Trees
Arxiv
4+阅读 · 2018年12月10日
Arxiv
7+阅读 · 2018年9月27日
Feature Selection Library (MATLAB Toolbox)
Arxiv
7+阅读 · 2018年8月6日
Arxiv
3+阅读 · 2017年7月6日
Top
微信扫码咨询专知VIP会员