十一城

跬步千里,小流江海。

Home Linux ML Python Java Thoughts KmKg BookCan Links About

2018-01-12
机器学习-集成学习-理解与应用XGBoost

• 分类: ml • 标签:

XGBoost–eXtreme Gradient Boosting

发展历程

XGBoost是从决策树一步步发展而来的。

  1. 决策树 ⟶ 对样本重抽样,然后多个树平均 ⟶ Tree bagging
  2. Tree bagging ⟶ 再同时对特征进行随机挑选 ⟶ 随机森林
  3. 随机森林 ⟶ 对随机森林中的树进行加权平均,而非简单平均 ⟶ Boosing (Adaboost, GradientBoost)
  4. boosting ⟶ 对boosting中的树进行正则化 ⟶ XGBoosting

基础

在运行XGBoost之前,必须设置三种类型成熟:general parameters,booster parameters和task parameters:

  • General parameters:参数控制在提升(boosting)过程中使用哪种booster,常用的booster有树模型(tree)和线性模型(linear model)。
  • Booster parameters:这取决于使用哪种booster。
  • Task parameters:控制学习的场景,例如在回归问题中会使用不同的参数控制排序。
  • 除了以上参数还可能有其它参数,在命令行中使用

XGBoost使用的基学习器是CART

  • 决策规则与决策树的一样
  • 每个叶子节点上都包含了一个权重,也有人叫做分数

二阶泰勒展开

pass

决策树的复杂度

Shrinkage与列抽样

  • Shrinkage(缩减),相当于学习速率(xgboost中的eta)。xgboost在进行完一次迭代后,会将叶子节点的权重乘上该系数,主要是为了削弱每棵树的影响,让后面有更大的学习空间。实际应用中,一般把eta设置得小一点,然后迭代次数设置得大一点。(补充:传统GBDT的实现也有学习速率)
  • 列抽样(column subsampling)。xgboost借鉴了随机森林的做法,支持列抽样,不仅能降低过拟合,还能减少计算,这也是xgboost异于传统gbdt的一个特性。

缺失值处理

对缺失值的处理。对于特征的值有缺失的样本,xgboost可以自动学习出它的分裂方向。

  • XGBoost内置处理缺失值的规则。
  • 用户需要提供一个和其它样本不同的值,然后把它作为一个参数传进去,以此来作为缺失值的取值。XGBoost在不同节点遇到缺失值时采用不同的处理方法,并且会学习未来遇到缺失值时的处理方法。

近似直方图算法

可并行的近似直方图算法。树节点在进行分裂时,我们需要计算每个特征的每个分割点对应的增益,即用贪心法枚举所有可能的分割点。当数据无法一次载入内存或者在分布式情况下,贪心算法效率就会变得很低,所以xgboost还提出了一种可并行的近似直方图算法,用于高效地生成候选的分割点。

交叉验证

  • XGBoost允许在每一轮boosting迭代中使用交叉验证。因此,可以方便地获得最优boosting迭代次数。

GridSearchCV

1
2
3
4
5
6
from xgboost import XGBClassifier
from sklearn.model_selection import GridSearchCV
xgb_model = XGBClassifier(n_estimators=1)
parameters = {'learning_rate': [0.01, 0.02, 0.03], 'max_depth': [4, 5, 6]}
clf = GridSearchCV(xgb_model, parameters, scoring='roc_auc')
clf.fit(data, target)

并行化

xgboost工具支持并行。

boosting不是一种串行的结构吗?怎么并行的?注意xgboost的并行不是tree粒度的并行,xgboost也是一次迭代完才能进行下一次迭代的(第t次迭代的代价函数里包含了前面t-1次迭代的预测值)。xgboost的并行是在特征粒度上的。我们知道,决策树的学习最耗时的一个步骤就是对特征的值进行排序(因为要确定最佳分割点),xgboost在训练之前,预先对数据进行了排序,然后保存为block结构,后面的迭代中重复地使用这个结构,大大减小计算量。这个block结构也使得并行成为了可能,在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行。

机器学习算法中GBDT和XGBOOST的区别有哪些?

首先XGBoost是Gradient Boosting的一种高效系统实现,并不是一种单一算法。XGBoost里面的基学习器除了用tree(gbtree),也可用线性分类器(gblinear)。而GBDT则特指梯度提升决策树算法。XGBoost相对于普通gbm的实现,可能具有以下的一些优势:

  1. 显式地将树模型的复杂度作为正则项加在优化目标
  2. 公式推导里用到了二阶导数信息,而普通的GBDT只用到一阶
  3. 允许使用column(feature) sampling来防止过拟合,借鉴了Random Forest的思想,sklearn里的gbm好像也有类似实现
  4. 实现了一种分裂节点寻找的近似算法,用于加速和减小内存消耗
  5. 节点分裂算法能自动利用特征的稀疏性
  6. data事先排好序并以block的形式存储,利于并行计算
  7. cache-aware, out-of-core computation
  8. 支持分布式计算可以运行在MPI,YARN上,得益于底层支持容错的分布式通信框架rabit。

LR+XGBoost

pass

Xgboost和LightGBM部分参数对照

Xgboost LightGbm
booster(default=gbtree) boosting(default=gbdt)
eta(default=0.3) learning_rate(default=0.1)
max_depth(default=6) num_leaves(default=31)
min_child_weight(default=1) min_sum_hessian_in_leaf(1e-3)
gamma(default=0) min_gain_to_split(default=20)
subsample(default=1) bagging_fraction(default=1.0)
colsample_bytree(default=1) feature_fraction( default=1.0)
alpha(default=0) lambda_l1(default=0)
lambda(default=1) lambda_l2(default=0)
objective( default=reg:linear) application(default=regression)
eval_metric(default according to objective) metric
nthread num_threads
  1. 使用num_leaves

因为LightGBM使用的是leaf-wise的算法,因此在调节树的复杂程度时,使用的是num_leaves而不是max_depth。

大致换算关系:num_leaves = 2^(max_depth)。它的值的设置应该小于2^(max_depth),否则可能会导致过拟合。

  1. 对于非平衡数据集:可以param[‘is_unbalance’]=’true’

  2. Bagging参数:bagging_fraction+bagging_freq(必须同时设置)、feature_fraction。bagging_fraction可以使bagging的更快的运行出结果,feature_fraction设置在每次迭代中使用特征的比例。

  3. min_data_in_leaf:这也是一个比较重要的参数,调大它的值可以防止过拟合,它的值通常设置的比较大。

  4. max_bin:调小max_bin的值可以提高模型训练速度,调大它的值和调大num_leaves起到的效果类似。

参数速查:

xgb lgb xgb.sklearn lgb.sklearn
booster=’gbtree’ boosting=’gbdt’ booster=’gbtree’ boosting_type=’gbdt’
objective=’binary:logistic’ application=’binary’ objective=’binary:logistic’ objective=’binary’
max_depth=7 num_leaves=2**7 max_depth=7 num_leaves=2**7
eta=0.1 learning_rate=0.1 learning_rate=0.1 learning_rate=0.1
num_boost_round=10 num_boost_round=10 n_estimators=10 n_estimators=10
gamma=0 min_split_gain=0.0 gamma=0 min_split_gain=0.0
min_child_weight=5 min_child_weight=5 min_child_weight=5 min_child_weight=5
subsample=1 bagging_fraction=1 subsample=1.0 subsample=1.0
colsample_bytree=1.0 feature_fraction=1 colsample_bytree=1.0 colsample_bytree=1.0
alpha=0 lambda_l1=0 reg_alpha=0.0 reg_alpha=0.0
lambda=1 lambda_l2=0 reg_lambda=1 reg_lambda=0.0
scale_pos_weight=1 scale_pos_weight=1 scale_pos_weight=1 scale_pos_weight=1
seed bagging_seedfeature_fraction_seed random_state=888 random_state=888
nthread num_threads n_jobs=4 n_jobs=4
evals valid_sets eval_set eval_set
eval_metric metric eval_metric eval_metric
early_stopping_rounds early_stopping_rounds early_stopping_rounds early_stopping_rounds
verbose_eval verbose_eval verbose verbose

XGBoost还需要做特征工程吗?

特征工程是个很广的概念,包括特征筛选、特征变换、特征合成、特征提取等等。对于XGBoost,它能够很好地做到特征选择,所以这一点不用我们去操心太多。至于特征变换(离散化、归一化、标准化、取log等等),我们也不需要做太多,因为XGBoost是基于决策树,决策树自然能够解决这些。相比较来说,线性模型则需要做离散化或者取log处理。因为XGBoost(树类模型)不依赖于线性假设。但是对于分类特征,XGBoost需要对其进行独热编码,否则无法训练模型。XGBoost也可以免于一部分特征合成的工作,比如线性回归中的交互项a:b,在树类模型中都可以自动完成。但是对于加法a+b,减法a-b,除法a-b这类合成的特征,则需要手动完成。

绝大部分模型都无法自动完成的一步就是特征提取。很多nlp的问题或者图象的问题,没有现成的特征,你需要自己去提取这些特征,这些是我们需要人工完成的。

综上来说,XGBoost的确比线性模型要省去很多特征工程的步骤。但是特征工程依然是非常必要的。

附录——参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
max_depth : int
Maximum tree depth for base learners.

learning_rate : float #learning_rate = 0.1 或更小,越小就需要多加入弱学习器
Boosting learning rate (xgb’s “eta”)
n_estimators : int
Number of boosted trees to fit.
silent : boolean
Whether to print messages while running boosting.
objective : string or callable
Specify the learning task and the corresponding learning objective or a custom objective function to be used (see note below).
booster: string
Specify which booster to use: gbtree, gblinear or dart.
nthread : int
Number of parallel threads used to run XGBoost. (Deprecated, please use n_jobs)
n_jobs : int
Number of parallel threads used to run XGBoost. (replaces nthread)
gamma : float
Minimum loss reduction required to make a further partition on a leaf node of the tree.
min_child_weight : int
Minimum sum of instance weight(hessian) needed in a child.
max_delta_step : int
Maximum delta step we allow each tree’s weight estimation to be.
subsample : float
Subsample ratio of the training instance.
colsample_bytree : float
Subsample ratio of columns when constructing each tree.
colsample_bylevel : float
Subsample ratio of columns for each split, in each level.
reg_alpha : float (xgb’s alpha)
L1 regularization term on weights
reg_lambda : float (xgb’s lambda)
L2 regularization term on weights
scale_pos_weight : float
Balancing of positive and negative weights.
base_score:
The initial prediction score of all instances, global bias.
seed : int
Random number seed. (Deprecated, please use random_state)
random_state : int
Random number seed. (replaces seed)
missing : float, optional
Value in the input which needs to be present as a missing value. If None, defaults to np.nan.

参考

  1. http://wepon.me/2016/05/07/XGBoost%E6%B5%85%E5%85%A5%E6%B5%85%E5%87%BA/
  2. http://blog.csdn.net/weiyongle1996/article/details/78446244
  3. https://www.jianshu.com/p/8346d4f80ab0
  4. http://chuan92.com/2016/03/19/XGBoost-and-gbdt
  5. http://sofasofa.io/forum_main_post.php?postid=1001161

dzzxjl

Home Linux ML Python Java Thoughts KmKg BookCan Links About