机器学习--有监督--GBM(Boosting)

集成学习(ensemble learning)是采用多个机器学习模型组合进行综合预测,从而提升模型性能的思路,分为bagging与boosting两种。之前学习的随机森林便是bagging的典型代表;而本次学习Gradient boosting machines为代表的boosting则是另一种集成思路。此外,集成学习使用的基学习器模型一般都是决策树(decision tree)。


1、bagging与boosting的区别

(1) bagging

  • 建立多个独立(independent)的、弱关联(de-correlated)、的base learner基学习器,每个单独的基学习器都是强学习器;
  • 进行预测结果时,综合考虑所有模型的预测值;即每个模型都有相同的权重,是平等的。
  • bagging适合于low bias and high variance,希望降低variance的情况;

(2) boosting

  • 建立一系列(sequential)的weak base learner基学习器。其中第一个base learner的性能仅仅由于随机猜测(random guessing),之后建立的模型都是在前一个模型的基础上通过调整参数(重点关注上一个模型预测最不准确地样本),从而逐渐提高后续模型的准确率。
  • 进行预测结果时,以每个基学习器的预测性能为权重(大致意思是性能优的基学习器有更高的话语权),综合考虑所有模型的预测值。
  • boosting适合于high bias and low variance,希望降低bias的情况。

2、GBM,Gradient boosting machines简单理解

2.1 Gradient descent

  • boosting的核心是以提高上一个模型性能为目的,建立一系列基学习器。而提升性能的标准可通过损失函数进行评价;而每一次提高性能的多少用学习率(learning rate)表示;


  • AdaBoost算法是早期boosting的流行形式之一,其使用SSE作为损失函数,即性能评价的标准。而GBM算法更加多元,它可以使用除SSE以外的其它指标作为损失函数;

The name gradient boosting machine comes from the fact that this procedure can be generalized to loss functions other than SSE.

2.2 GBM的超参数

GBM的超参数主要包含两类,一类是boosting相关的参数;一类是决策树本身的超参数

(1)boosting hyperparameters
  • Number of trees:首先是建立多少个基学习器。一般boosting需要建立较多数目(thousands)的决策树,从而提高后续模型的性能。但是过多的数目又可能带来过拟合的问题(bagging则不用担心这个问题)。
  • Learning rate:取值范围在0-1之间,一般取0.001~0.3。太大的学习率可能会使模型错过最佳的参数,从而导致过拟合;太小的值则可能需要建非常多的树,从而提高了计算资源与时间的需求。
    由于不同的学习率都有不同的最佳决策树的数目,所以不需要特别设置树参数,尽量取一个较大值即可。
(2)tree hyperparameters
  • 树的深度:一般建议取值范围在3~8;
  • 终端节点(terminal nodes)的最小样本数:一般建议取值范围在5~15;

超参数调整策略

  • 先确定最佳的学习率参数
  • 再调整决策树的相关参数

3、代码实操

示例数据:预测房价
ames <- AmesHousing::make_ames()
dim(ames)
## [1] 2930   81

set.seed(123)
library(rsample)
split <- initial_split(ames, prop = 0.7, 
                       strata = "Sale_Price")
ames_train  <- training(split)
# [1] 2049   81
ames_test   <- testing(split)
# [1] 881  81

  • 建模R包
library(gbm)
step1 : 先大致探索一下
set.seed(123) # for reproducibility
ames_gbm1 <- gbm(
  formula = Sale_Price ~ .,
  data = ames_train,
  distribution = "gaussian", # SSE loss function
  n.trees = 5000,
  shrinkage = 0.1,
  interaction.depth = 3,
  n.minobsinnode = 10,
  cv.folds = 10)

# find index for number trees with minimum CV error
best <- which.min(ames_gbm1$cv.error)
# [1] 1119

# get MSE and compute RMSE
sqrt(ames_gbm1$cv.error[best])
## [1] 22402.07

# plot error curve
gbm.perf(ames_gbm1, method = "cv")

如下可以看出在1119棵树的时候,交叉验证指标已经达到平台期


step2:学习率指标优化
# create grid search
hyper_grid <- expand.grid(
  learning_rate = c(0.3, 0.1, 0.05, 0.01, 0.005),
  RMSE = NA,
  trees = NA,
  time = NA
)
# execute grid search
for(i in seq_len(nrow(hyper_grid))) {
  # fit gbm
  set.seed(123) # for reproducibility
  train_time <- system.time({
    m <- gbm(
      formula = Sale_Price ~ .,
      data = ames_train,
      distribution = "gaussian",
      n.trees = 5000,
      shrinkage = hyper_grid$learning_rate[i],
      interaction.depth = 3,
      n.minobsinnode = 10,
      cv.folds = 10
    )
  })
  # add SSE, trees, and training time to results
  hyper_grid$RMSE[i] <- sqrt(min(m$cv.error))
  hyper_grid$trees[i] <- which.min(m$cv.error)
  hyper_grid$time[i] <- train_time[["elapsed"]]
}

dplyr::arrange(hyper_grid, RMSE)
#   learning_rate     RMSE trees  time
# 1         0.050 21807.96  1565 66.83
# 2         0.010 22102.34  4986 66.73
# 3         0.100 22402.07  1119 67.84
# 4         0.005 23054.68  4995 66.04
# 5         0.300 24411.95   269 64.84
  • 如上确定最佳的学习率参数为0.05。
step3:优化决策树参数
# search grid
hyper_grid <- expand.grid(
  n.trees = 5000,
  shrinkage = 0.05,
  interaction.depth = c(3, 5, 7),
  n.minobsinnode = c(5, 10, 15)
)

# create model fit function
model_fit <- function(n.trees, shrinkage, interaction.depth, n.minobsinnode) {
  set.seed(123)
  m <- gbm(
    formula = Sale_Price ~ .,
    data = ames_train,
    distribution = "gaussian",
    n.trees = n.trees,
    shrinkage = shrinkage,
    interaction.depth = interaction.depth,
    n.minobsinnode = n.minobsinnode,
    cv.folds = 10
  )
  # compute RMSE
  sqrt(min(m$cv.error))
}

# perform search grid with functional programming
hyper_grid$rmse <- purrr::pmap_dbl(
  hyper_grid,
  ~ model_fit(
    n.trees = ..1,
    shrinkage = ..2,
    interaction.depth = ..3,
    n.minobsinnode = ..4
  )
)
# results
dplyr::arrange(hyper_grid, rmse)
#   n.trees shrinkage interaction.depth n.minobsinnode     rmse
# 1    5000      0.05                 5             10 21793.28
# 2    5000      0.05                 3             10 21807.96
# 3    5000      0.05                 5              5 21976.76
# 4    5000      0.05                 3              5 22104.49
# 5    5000      0.05                 5             15 22156.30
# 6    5000      0.05                 3             15 22170.16
# 7    5000      0.05                 7             10 22268.51
# 8    5000      0.05                 7              5 22316.37
# 9    5000      0.05                 7             15 22595.51
  • 如上可以看出,最佳的决策树超参数组合:(1)interaction.depth=5;(2)n.minobsinnode = 10;
  • 但最佳组合的rmse值(21793)也仅比默认值(21807)降低了很少,所以决策树参数对GBM的影响相对较小。
step4:确定最佳模型,测试集评价
ame_gbm <- gbm(
  formula = Sale_Price ~ .,
  data = ames_train,
  distribution = "gaussian",
  n.trees = 5000,
  shrinkage = 0.05,
  interaction.depth = 5,
  n.minobsinnode = 10,
  cv.folds = 10)
(best <- which.min(ame_gbm$cv.error))
# [1] 1305
sqrt(ame_gbm$cv.error[best])
# [1] 22475.02

#自动调用最佳数目进行预测
pred = predict(ame_gbm, ames_test)
ModelMetrics::rmse(pred, ames_test$Sale_Price)
# [1] 20010.21

评价特征变量的重要性

vip::vip(ame_gbm) 

由于GBM是基于梯度下降的思路,当遇到非碗形的损失函数曲线时,有可能遇到局部的最低点local minimas,Stochastic gradient descent算法可采用抽样建模方式尽可能找到全局最低点;此外XGBoost可以尽可能避免boosting算法出现过拟合的情况。具体用法就暂不学习了~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容