Spark随机森林实现学习

前言 html

最近阅读了spark mllib(版本:spark 1.3)中Random Forest的实现,发如今分布式的数据结构上实现迭代算法时,有些地方与单机环境不同。单机上一些直观的操做(递归),在分布式数据上,必须进行优化,不然I/O(网络,磁盘)会消耗大量时间。本文整理spark随机森林实现中的相关技巧,方便后面回顾。 git

 

随机森林算法概要 github

随机森林算法的详细实现和细节,能够参考论文Breiman 2001。这里简单说说大致思路,方便理解代码。 算法

随机森林是一个组装(ensemble model)模型,内部的模型使用决策树。基本思想是生成不少不少决策树(构成森林),最后由这些决策数一块儿投票决定最终结果。生成树的过程当中,从行和列两个方向添加随机过程。行方向,在构建每棵树前,使用有放回抽样(称为Bootstrapping),获得训练数据。列方向,每次选择切分点时,对feature进行无放回随机抽样,获得一个feature子集,在当前节点上,只使用这些子集对应的数据计算最优切分点。这也是为何此算法称为随机森林,是否是很直观。相比于单一决策树,随机森林有如下一些优势: apache

  1. 结果比较稳定,不容易出现过拟合;
  2. Out-Of-Bag error评估模型效果,无需交叉检验;
  3. 可获得feature重要性。

固然,为了获得上面的优势,必须付出计算开销做为代价。在单机时代,使用随机森林(R或scikit-learn)每每成本很高,可是如今有了spark,使得大规模,分布式迭代计算成为了可能,因此在spark上运用随机森林是技术发展的必然结果! 服务器

 

Spark实现优化 网络

spark在实现随机森林时,采用了下面几个优化策略: 数据结构

  1. 切分点抽样
  2. feature装箱(bin)
  3. 分区统计
  4. 逐层计算(level-wise)

使用这些策略,缘由在于RDD的数据时分布在不一样服务器上,为了不过多的I/O,必须在原始算法上作出一些优化,不然执行时间可能难以接受。下面分别详细讨论这三个优化策略。 app

 

切分点抽样 dom

此优化主要针对连续变量。先回忆一下通常的决策树是如何对连续变量进行切分点选择的。通常是先对feature进行排序,而后选取相邻两个数据之间的点做为切分点。若是在RDD上执行这个操做,不可避免会使用shuffle过程,此过程会带来大量的网络通信。并且,通常RDD上的数据都很大,少则几百万,多则几亿到几十亿,甚至更多。在这样的数量级上进行排序操做,想一想也是醉了。因此,为了不排序操做,mllib经过抽样的方法,在样本上进行排序,而且根据样本,获取切分点。据spark团队反馈,使用此策略虽然牺牲了部分精度,可是在实际运用过程当中,并无带来过多的影响,模型效果能够接受。

 

feature装箱

根据抽样,获得切分点后,接下来是对feature进行装箱操做,箱子就是由相邻的样本切分点构成。箱子的个数是很是小的,通常实际中采用30个左右。计算每一个箱子中不一样种类的占比,能够很快计算出最优切分点。

举个例子,参考上面的示例数据,第一行是每一个切分点的比例统计。基于上面的数据,可能生成3中切分状况,分别有棕,红和绿色三行表示。若是须要计算棕色的切分状况,只须要按照第一行的组合方式,就能够很快的计算所出来。

 

分区统计

RDD分区中装箱数据单独统计后,能够经过reduce将每一个分区的数据合并,获得整体的装箱数据(经过mapPartition实现分区统计)。正是因为装箱统计数据能够合并,因此能够很好的适应分布式数据环境,最后须要合并的数据也只是一些统计数据,不会带来很大的网络通信开销。

 

逐层计算

单机版本的决策数生成过程是经过递归调用(本质上是深度优先)的方式构造树,在构造树的同事,须要移动数据,将同一个子节点的数据移动到一块儿。此方法在分布式数据结构上没法有效的执行,并且也没法执行,由于数据太大,没法放在一块儿,因此在分布式存储。mlib采用的策略是逐层构建树节点(本质上是广度优先),这样遍历全部数据的次数等于全部树的最大层数。每次遍历时,只须要计算每一个节点全部feature的装箱统计参数,遍历完后,根据节点装箱统计量,决定是否切分,以及如何切分。

 

以上就是spark mllib实现的随机森林的关键技巧。固然还有不少实现细节这里没有描述,不过若是理解了这些技巧,对阅读spark mllib随机森林源代码会有很大帮助,但愿对读者有用。

 

Spark Random Forest实现的不足

截止到spark 1.3,mllib的随机森林仍然不支持OOB error和variable importance的支持,也有一些网友在spark社区咨询此问题,可是目前没有获得官方的回应。但愿后面,spark能够支持此特性。

 

应用案例

目前,在网络游戏流失预测的场景下,使用spark随机森林模型(1000棵树)和单机c50模型作了对比试验。试验中覆盖5款不一样类型的游戏,共执行608轮,试验周期跨度为4个月。采用了相同的数据,因为单机数据量计算限制,C50使用了10%的采样建模,而spark使用了全量数据(计算能力秒杀)。试验结果是随机森林的模型效果明显优于C50。F1值有37%的提高,而F2(召回率优先)提高度高达72%

提高可能的缘由有两个:

1 随机森林模型效果确实优于C50

2 随机森林建模数据量有质的飞跃,致使性能提高

 

参考资料

  1. Spark源代码
  2. Spark峰会关于分布式决策树实现的分享
相关文章
相关标签/搜索