文章目录
  1. 1. 决策树与随机森林
    1. 1.1. 决策树
    2. 1.2. 混合方法
    3. 1.3. 随机森林
  2. 2. 实现方法
  3. 3. 调用方法
    1. 3.1. 注意事项
    2. 3.2. 数据格式
    3. 3.3. CART决策树的调用方法
    4. 3.4. 随机森林的调用方法
  4. 4. 后记

写文章之前总是想交待清楚这篇文章的产生背景,如果把这一章改成“引言”,总感觉太单调,并且有点写学术论文的感觉,好吧,就这样吧,改个字体说明一下写作背景。最近在修台湾大学林轩田老师在Coursera上的公开课《机器学习技术》课程,讲到“Blending and Baging”一章,这一章免不了介绍决策树和随机森林,刚好课后作业需要用随机森林和决策树算法,一开始想找找开源的工具包,但是很难发现符合我这个任务的工具包。求人不如求己,受此任务驱动,自己用java实现了一个简单的决策树模型和随机森林模型,在此分享给大家,希望对大家有用。

决策树与随机森林


决策树

相信了解机器学习的朋友对决策树模型肯定不会陌生,《统计学习方法》一书里面也是对决策树这一方法作了详尽的描述,可以说决策树是一种非常接近人类思维习惯,可解释性非常强的模型,它可以看作是一系列if-then规则的集合,但是它也有一个很致命的弱点,就是非常容易过拟合。经典的决策树构建方法有ID3算法、C4.5算法、CART算法,前两个方法主要用来解决分类问题,区别在于前者用信息增益作为数据纯度衡量指标,而后者采用的是信息增益比,且后者对树进行了剪枝;CART算法则可以解决回归问题。具体细节本文就不展开说了。

混合方法

当我们有了多个不同的模型时,很容易产生一些想法,即如何把这些模型混合起来并且使混合模型的效果要优于单个模型。对于分类问题,最简单直观地有两种想法,第一种思路是让多个模型进行投票,得票多的类别即为最终的分类结果,这也就是现实生活中的民主法则;第二种思路是对各个模型进行加权,效果好的模型给他更大的权重,和现实生活中一样,权威人士和领导的话语权永远是比普通人更大的。第一种思路称为Baging,第二种思路就是非常有名的Adaboost方法,当然了如果深究下去其实还有第三种思路,即符合某种条件的时候用某一个模型,这其实就是决策树的基本思想。

随机森林

随机森林(Random Forest)可以说是Baging和决策树的完美结合,这其实就是“三个臭皮匠,顶个诸葛亮”、“众人拾柴火焰高”的典型例子了。森林两字我们很容易理解,树多了就成了森林,也就是告诉我们,随机森林模型需要很多决策树。那么,“随机”二字是如何体现的呢?其实“随机”体现在随机森林模型的方方面面,首先是其数据的随机,采用有放回随机抽样保证每次模型训练的数据都是不一样的;其次是特征的随机性,每次决策树的训练都随机抽取一些特征,这样保证了每次训练都是用的不一样的特征空间。随机森林通过其随机性等机制有效地弥补了决策树容易过拟合的缺陷。你一棵决策树容易犯错,那么我有一个森林的树去投票做决定这样犯错的可能性总会低不少吧?

实现方法


好了,做了这么多作铺垫,先不卖关子了,代码可以在我的个人gitcafe主页下载,此代码实现了简单CART(Classify and Regression Tree)算法的决策树分类算法,数据不纯度衡量指标选择的是基尼指数;基于此CART决策树实现了简单的随机森林模型,此随机森林模型目前只实现了数据的随机性,特征的随机性功能有待完善。具体使用方法可参照如下说明。

调用方法


注意事项

这里引用了一个矩阵运算的工具包ujmp,所以大家把代码下载了别忘了添加该引用,这个jar包放在了我的项目目录下的lib子目录下。为方便大家使用本人封装了几个基本方法留作外部调用的接口,感兴趣的朋友可查看内部代码并根据自己的需要作出更改。

数据格式

首先需要把数据处理成固定的格式,这里面我们只需要处理成最简单的格式,即每行代表一个样本,行中的特征用空格分隔,最后一列为该样本的类别标签。例如只有两维特征的数据格式如下所示

feature1 feature2 +1

feature1 feature2 -1

CART决策树的调用方法

调用决策树需要加载数据、建树、评价结果,其代码如下所示。

//CART完全决策树调用示例
DecisionTree dt = new DecisionTree();
String trainFile = "./data/hw3_train.dat";
String testFile = "./data/hw3_test.dat";
List<DataItem> dataList = Utility.loadData(trainFile);
List<DataItem> testList = Utility.loadData(testFile);
//根据已有数据创建CART决策树
dt.buildFullCartTree(dataList);
//评价结果错误率
double err = dt.evaluate(testList);
System.out.println(String.format("ErrorRate: %f", err));

随机森林的调用方法

随机森林加载数据的方法同上,这里需要设置2个参数,分别是森林中树的数量和抽样比例,其具体调用方法如下所示。

//随机森林调用示例
RandomForest rf = new RandomForest();
//设置参数,森林中树的个数和抽样比例
int treeCount = 300;
double sampleRate = 1.0d;
rf.buildFullCartForest(dataList, treeCount, sampleRate);
//评价结果错误率
err = rf.evaluate(testList);
System.out.println(String.format("ErrorRate: %f", err));

后记


写到这里,我的内心是有些遗憾的,因为在去年参加的阿里巴巴大数据竞赛中就可以应用决策树的扩展方法,而我却没有用到过,所以并没有取得太好的成绩,并且实验结果也证明了成绩好的队伍都是用这那种方法。那种方法其实就是决策树和混合方法第二种思路的完美结合,它有一个高大上的名字叫做梯度提升决策树(Gradient Boosted Decision Tree, GBDT),这种方法在台湾大学公开课《机器学习技法》中有详细的讲解,感兴趣的朋友可以参照。
其实上述代码只是实现了的只是最为简单的决策树和随机森林版本,我是一个懒人,一个任务驱动的懒人,将来可能需要添加剪枝、ID3算法、C4.5算法、回归决策树等功能,但是需要一个任务驱使才能有编码的动力,这些作为后续扩展吧,当然了更希望“有缘人”能去完善它。
谨以此文纪念我第一次在公共平台上共享代码。

文章目录
  1. 1. 决策树与随机森林
    1. 1.1. 决策树
    2. 1.2. 混合方法
    3. 1.3. 随机森林
  2. 2. 实现方法
  3. 3. 调用方法
    1. 3.1. 注意事项
    2. 3.2. 数据格式
    3. 3.3. CART决策树的调用方法
    4. 3.4. 随机森林的调用方法
  4. 4. 后记