【R语言】用gbm包来提升决策树能力

中国有句老话:三个臭皮匠,顶个诸葛亮。这个说法至少在变形金刚中得到了体现,没有组合之前的大力神只是五个可以被柱子哥随手秒掉工地苦力。但组合之后却是威力大增。在机器学习领域也是如此,一堆能力一般的“弱学习器”也能组合成一个“强学习器”。前篇文章提到的随机森林就是一种组合学习的方法,本文要说的是另一类组合金刚: 提升方法(Boosting) 。提升方法是一大类集成分类学习的统称。它用不同的权重将基学习器进行线性组合,使表现优秀的学习器得到重用。在 R语言中gbm包 就是用来实现一般提升方法的扩展包。根据基学习器、损失函数和优化方法的不同,提升方法也有各种不同的形式。 自适应提升方法AdaBoost 它是一种传统而重要的Boost算法,在学习时为每一个样本赋上一个权重,初始时各样本权重一样。在每一步训练后,增加错误学习样本的权重,这使得某些样本的重要性凸显出来,在进行了N次迭代后,将会得到N个简单的学习器。最后将它们组合起来得到一个最终的模型。 梯度提升方法Gradient Boosting 梯度提升算法初看起来不是很好理解,但我们和线性回归加以类比就容易了。回忆一下线性回归是希望找到一组参数使得残差最小化。如果只用一次项来解释二次曲线一定会有大量残差留下来,此时就可以用二次项来继续解释残差,所以可在模型中加入这个二次项。 同样的,梯度提升是先根据初始模型计算伪残差,之后建立一个基学习器来解释伪残差,该基学习器是在梯度方向上减少残差。再将基学习器乘上权重系数(学习速率)和原来的模型进行线性组合形成新的模型。这样反复迭代就可以找到一个使损失函数的期望达到最小的模型。在训练基学习器时可以使用再抽样方法,此时就称之为 随机梯度提升算法stochastic gradient boosting 。 在gbm包中,采用的是决策树作为基学习器,重要的参数设置如下:

  • 损失函数的形式(distribution)
  • 迭代次数(n.trees)
  • 学习速率(shrinkage)
  • 再抽样比率(bag.fraction)
  • 决策树的深度(interaction.depth)

损失函数的形式容易设定,分类问题一般选择bernoulli分布,而回归问题可以选择gaussian分布。学习速率方面,我们都知道步子迈得太大容易扯着,所以学习速率是越小越好,但是步子太小的话,步数就得增加,也就是训练的迭代次数需要加大才能使模型达到最优,这样训练所需时间和计算资源也相应加大了。gbm作者的经验法则是设置shrinkage参数在0.01-0.001之间,而n.trees参数在3000-10000之间。 下面我们用mlbench包中的数据集来看一下gbm包的使用。其中响应变量为diabetes,即病人的糖尿病诊断是阳性还是阴性。

# 加载包和数据library(gbm)data(PimaIndiansDiabetes2,package='mlbench')# 将响应变量转为0-1格式data <- PimaIndiansDiabetes2data$diabetes <- as.numeric(data$diabetes)data <- transform(data,diabetes=diabetes-1)# 使用gbm函数建模model <- gbm(diabetes~.,data=data,shrinkage=0.01,
             distribution='bernoulli',cv.folds=5,
             n.trees=3000,verbose=F)# 用交叉检验确定最佳迭代次数best.iter <- gbm.perf(model,method='cv')
# 观察各解释变量的重要程度summary(model,best.iter)
# 变量的边际效应plot.gbm(model,1,best.iter)
# 用caret包观察预测精度library(caret)data <- PimaIndiansDiabetes2fitControl <- trainControl(method = "cv", number = 5,returnResamp = "all")model2 <- train(diabetes~., data=data,method='gbm',distribution='bernoulli',trControl = fitControl,verbose=F,tuneGrid = data.frame(.n.trees=best.iter,.shrinkage=0.01,.interaction.depth=1))
model2

Accuracy Kappa Accuracy SD Kappa SD 0.78 0.504 0.0357 0.0702 观察到gbm迭代到800次左右最优,得到的预测正确率为0.78,这个比随机森林的正确率还要略高一些。提升算法继承了单一决策树的优点,例如:能处理缺失数据,对于噪声数据不敏感,但又摒弃了它的缺点,使之能拟合复杂的非线性关系,精确度大为提高。通过控制迭代次数能控制过度拟合,计算速度快。但由于它是顺序计算的,所以不好进行分布式计算。

原文发布于微信公众号 - 大数据挖掘DT数据分析(datadw)

原文发表时间:2016-01-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏MelonTeam专栏

ArrayList源码完全分析

导语: 这里分析的ArrayList是使用的JDK1.8里面的类,AndroidSDK里面的ArrayList基本和这个一样。 分析的方式是逐个API进行解析 ...

4469
来自专栏项勇

笔记68 | 切换fragmengt的replace和add方法笔记

1434
来自专栏desperate633

LeetCode Invert Binary Tree题目分析

Invert a binary tree. 4 / \ 2 7 / \ / \1 3 6 9 to4 / \ 7 2 / \ / \9 6 3 1 Tri...

831
来自专栏xingoo, 一个梦想做发明家的程序员

Spark踩坑——java.lang.AbstractMethodError

百度了一下说是版本不一致导致的。于是重新检查各个jar包,发现spark-sql-kafka的版本是2.2,而spark的版本是2.3,修改spark-sql-...

1190
来自专栏学海无涯

Android开发之奇怪的Fragment

说起Android中的Fragment,在使用的时候稍加注意,就会发现存在以下两种: v4包中的兼容Fragment,android.support.v4.ap...

3155
来自专栏xingoo, 一个梦想做发明家的程序员

20120918-向量实现《数据结构与算法分析》

#include <iostream> #include <list> #include <string> #include <vector> #include...

1706
来自专栏聊聊技术

原 初学图论-Kahn拓扑排序算法(Kah

2878
来自专栏拭心的安卓进阶之路

Java 集合深入理解(12):古老的 Vector

今天刮台风,躲屋里看看 Vector ! 都说 Vector 是线程安全的 ArrayList,今天来根据源码看看是不是这么相...

2437
来自专栏Java Edge

AbstractList源码解析1 实现的方法2 两种内部迭代器3 两种内部类3 SubList 源码分析4 RandomAccessSubList 源码:AbstractList 作为 Lis

它实现了 List 的一些位置相关操作(比如 get,set,add,remove),是第一个实现随机访问方法的集合类,但不支持添加和替换

402
来自专栏Phoenix的Android之旅

Java 集合 Vector

List有三种实现,ArrayList, LinkedList, Vector, 它们的区别在于, ArrayList是非线程安全的, Vector则是线程安全...

642

扫码关注云+社区