【MATLAB第37期】 #保姆级教程 XGBOOST模型参数完整且详细介绍,调参范围、思路及具体步骤介绍
一、XGBOOST参数介绍
(一)模型参数
1.XGBoost模型[default=gbtree]
有两种模型可以选择gbtree和gblinear。gbtree使用基于树的模型进行提升计算,gblinear使用线性模型进行提升计算。其中gbtree的效果要远好于gblinear。
2.objective目标函数 [ default=reg:linear ]
定义学习任务及相应的学习目标,可选的目标函数如下:
“reg:linear” –线性回归。
“reg:logistic” –逻辑回归。
“binary:logistic” –二分类的逻辑回归问题,输出为概率。
“binary:logitraw” –二分类的逻辑回归问题,输出的结果为wTx。
“count:poisson” –计数问题的poisson回归,输出结果为poisson分布。在poisson回归中,max_delta_step的缺省值为0.7。
“multi:softmax” –让XGBoost采用softmax目标函数处理多分类问题,同时需要设置参数num_class(类别个数)
“multi:softprob” –和softmax一样,但是输出的是ndata * nclass的向量,可以将该向量reshape成ndata行nclass列的矩阵。没行数据表示样本所属于每个类别的概率。
“rank:pairwise” –通过最小化成对损失对任务进行排序
3.eval_metric——评价指标[default=取决于objective参数的取值]
对于回归问题,默认值是rmse,对于分类问题,默认值是error。选项如下所示:
rmse(均方根误差)
mae(平均绝对误差)
logloss(负对数似然函数值)
error(二分类误差,阈值0.5)
merror(多分类错误率)
mlogloss(多分类logloss损失函数)
auc(曲线下面积)
“ndcg”:归一化贴现累积收益
“map”:平均精度
(二)通用参数
1.max_depth ——数的最大深度[default=6],取值范围为:[1,∞]
通过控制树的深度从而控制树模型的复杂程度,来减少过拟合分风险。max_depth越大,模型会学到更具体更局部的样本
2.min_child_weight ——子节点最小样本权重和[default=1],取值范围为: [0,∞]
最小样本权重的和;这个参数用于避免过拟合,当它的值较大时,可以避免模型学习到局部的特殊样本。但是如果这个值过高,会导致欠拟合。
3.subsample ——每个决策树所用的子样本占总样本的比例[default=1],取值范围为:(0,1]
用于训练模型的子样本占整个样本集合的比例。如果设置为0.5则意味着XGBoost将随机的从整个样本集合中随机的抽取出50%的子样本建立树模型,这能够防止过拟合。参数默认值是1,该参数控制的就是对于每棵树,随机采样的比例。减少这个参数的值,同样会使算法更加保守,避免过拟合,但是如果设置的过于小,可能会导致欠拟合。典型的取值范围[0.5-1.0]。
4.colsample_bytree——在建立树时对特征采样的比例 [default=1],取值范围:(0,1]
用来控制每棵随机采样的列数的占比(每一列是一个特征)。控制每棵树的特征抽取比例,减少过拟合的风险。参数默认值是1,典型的取值范围[0.5-1.0]。
5.colsample_bylevel——对列数的采样的占比 [default=1]
参数默认值是1,用来控制树的每一级的每一次分裂,对列数的采样的占比。
6.silent ——运行信息[default=0]
取0时表示打印出运行时信息,取1时表示以缄默方式运行,不打印运行时信息。
7.nthread——输入系统的核数[default=当前系统可获得的最大线程数]
XGBoost运行时的线程数。看到这个参数的第一反应就猜到是和多线程相关的,果不其然,该参数是用来控制应当输入系统的核数。如果不输入这个参数的话,算法自动检测会默认使用CPU的全部核。
8.base_score ——所有实例的初始预测分数,全局偏差[ default=0.5 ]
9.max_delta_step——每个树的权重最大增量 [default=0],取值范围为:[0,∞]
该参数限制的是每棵树权重改变的最大步长。如果该参数设置为0,则表示没有约束,如果其被赋予了某个正值,则会让算法更加保守。原文说该参数一般用不到,但是在样本不平衡的情况下,对逻辑回归很有帮助(有待测试)。但当类极不平衡时,它可能有助于逻辑回归。将其设置为1-10可能有助于控制更新。
10.num_pbuffer——预测缓冲区的大小
[由xgboost自动设置,无需用户设置],通常设置为训练实例的数量。缓冲器用于保存上一个升压步骤的预测结果。
11.num_feature——特征维数
[由xgboost自动设置,无需用户设置]特征个数
12.lambda——L2 正则的惩罚系数 [default=1]
这个参数是用来控制XGBoost的正则化部分的。在减少过拟合上可挖掘更多用处。参数默认值是1,权重的L2正则化项(类似于Ridge Regression),该参数是用来控制XGBoost中的正则化部分的,一般很少用,但是在减少过拟合方面,该参数应该还是能起到很大作用的。
13.alpha ——L1 正则的惩罚系数[default=0]
参数默认值是1,权重的L1正则化项(类似于Lasso Regression),原文说该参数能应用到很高维度的情况,可以让算法的速度更快(有待测试)。
14.lambda_bias——在偏置上的L2正则[default=0]**
在L1上没有偏置项的正则,因为L1时偏置不重要
15.seed——随机种子数 [ default=0 ]
随机数的种子,用于复现随机数据的结果,也可以用于调整参数。
16.tree_method——数算法[default=近似]
要使用精确的贪婪算法,需要将tree_method设置为“exact”
17.max-leaf-nodes——树上最大的节点或叶子数
直观解释就是:。用于避免决策树的过拟合。试想一颗深度为n的二叉树,其叶子节点数最多为n^2。
18.scale_pos_weight——缩放百分比权重[default=1]
参数默认值是1,该参数用于样本十分不平衡时,把该参数设置为一个正值,可以使算法很快收敛。
19.num_parallel_tree——并行树数量[default=1]
20.eta——收缩步长 [default=0.3],取值范围为:[0,1]
和learning rate类似,通过减小每一步的权重,可以提高模型的鲁棒性。xgboost在进行完一次迭代后,会将叶子节点的权重乘上该系数,主要是为了削弱每棵树的影响,防止过拟合,让后面有更大的学习空间。 eta通过缩减特征的权重使提升计算过程更加保守。实际应用中,一般把eta设置得小一点,典型的取值范围是[0.01-0.2]。
21.num_round–迭代次数,取值范围为:[1,+∞]
建立弱分类器数量(也即迭代次数),其数量越大,模型的学习能力就会越强。但是,较大num_round会造成过拟合,且增加到一定程度之后,模型达到上限,不会再增加准确率。
22.gamma——树结点分裂的最低要求 [default=0],取值范围为:[0,+∞]
在树的叶节点上进行进一步分区所需的最小损失减少。控制子树的复杂程度,减低模型复杂度(减少过拟合)这个参数的值越大,算法越保守。这个参数的值和损失函数息息相关。参数默认值是0,我们都知道,XGBoost在分裂节点时都会看分裂后损失函数的增益,只有增益大于一个阈值,才会对节点进行分裂。该参数指定的就是那个阈值,该参数越大,则表示决策树越难进行分裂,也就意味着算法越保守。该参数和损失函数息息相关。
二、调参思路
调参思路来源:https://jiuaidu.com/it/2579833/
(一)详细版本
参数调优的一般方法。我们会使用和GBM中相似的方法。需要进行如下步骤:
选择较高的学习速率(learning rate)。一般情况下,学习速率的值为0.1。但是,对于不同的问题,理想的学习速率有时候会在0.05到0.3之间波动。选择对应于此学习速率的理想决策树数量。XGBoost有一个很有用的函数“cv”,这个函数可以在每一次迭代中使用交叉验证,并返回理想的决策树数量。
对于给定的学习速率和决策树数量,进行决策树特定参数调优(max_depth, min_child_weight, gamma, subsample, colsample_bytree)。在确定一棵树的过程中,我们可以选择不同的参数,待会儿我会举例说明。
xgboost的正则化参数的调优。(lambda, alpha)。这些参数可以降低模型的复杂度,从而提高模型的表现。
降低学习速率,确定理想参数。
第一步:确定学习速率和tree_based 参数调优的估计器数目。
为了确定boosting 参数,我们要先给其它参数一个初始值。咱们先按如下方法取值:
1、max_depth = 5 :这个参数的取值最好在3-10之间。我选的起始值为5,但是你也可以选择其它的值。起始值在4-6之间都是不错的选择。
2、min_child_weight = 1:在这里选了一个比较小的值,因为这是一个极不平衡的分类问题。因此,某些叶子节点下的值会比较小。
3、gamma = 0: 起始值也可以选其它比较小的值,在0.1到0.2之间就可以。这个参数后继也是要调整的。
4、subsample,colsample_bytree = 0.8: 这个是最常见的初始值了。典型值的范围在0.5-0.9之间。
5、scale_pos_weight = 1: 这个值是因为类别十分不平衡。
注意哦,上面这些参数的值只是一个初始的估计值,后继需要调优。这里把学习速率就设成默认的0.1。然后用xgboost中的cv函数来确定最佳的决策树数量。前文中的函数可以完成这个工作。
learning_rate =0.1, n_estimators=1000, max_depth=5, min_child_weight=1, gamma=0, subsample=0.8, colsample_bytree=0.8, objective= 'binary:logistic', nthread=4, scale_pos_weight=1, seed=27
从输出结果可以看出,在学习速率为0.1时,理想的决策树数目是140。这个数字对你而言可能比较高,当然这也取决于你的系统的性能。
注意:在AUC(test)这里你可以看到测试集的AUC值。但是如果你在自己的系统上运行这些命令,并不会出现这个值。因为数据并不公开。这里提供的值仅供参考。生成这个值的代码部分已经被删掉了。
第二步: max_depth 和 min_weight 参数调优
我们先对这两个参数调优,是因为它们对最终结果有很大的影响。首先,我们先大范围地粗调参数,然后再小范围地微调。
注意:在这一节我会进行高负荷的栅格搜索(grid search),这个过程大约需要15-30分钟甚至更久,具体取决于你系统的性能。你也可以根据自己系统的性能选择不同的值。
'max_depth':range(3,10,2), 'min_child_weight':range(1,6,2) learning_rate =0.1 n_estimators=140, max_depth=5, min_child_weight=1, gamma=0, subsample=0.8 colsample_bytree=0.8, objective= 'binary:logistic', nthread=4, scale_pos_weight=1 seed=27
至此,我们对于数值进行了较大跨度的12中不同的排列组合,可以看出理想的max_depth值为5,理想的min_child_weight值为5。在这个值附近我们可以再进一步调整,来找出理想值。我们把上下范围各拓展1,因为之前我们进行组合的时候,参数调整的步长是2。
'max_depth':[4,5,6], 'min_child_weight':[4,5,6] learning_rate=0.1, n_estimators=140, max_depth=5, min_child_weight=2, gamma=0, subsample=0.8, colsample_bytree=0.8, objective= 'binary:logistic', nthread=4, scale_pos_weight=1, seed=27
至此,我们得到max_depth的理想取值为4,min_child_weight的理想取值为6。同时,我们还能看到cv的得分有了小小一点提高。需要注意的一点是,随着模型表现的提升,进一步提升的难度是指数级上升的,尤其是你的表现已经接近完美的时候。当然啦,你会发现,虽然min_child_weight的理想取值是6,但是我们还没尝试过大于6的取值。像下面这样,就可以尝试其它值。
'min_child_weight':[6,8,10,12] learning_rate=0.1, n_estimators=140, max_depth=4, min_child_weight=2, gamma=0, subsample=0.8, colsample_bytree=0.8, objective= 'binary:logistic', nthread=4, scale_pos_weight=1, seed=27
我们可以看出,6确确实实是理想的取值了。
第三步:gamma参数调优
在已经调整好其它参数的基础上,我们可以进行gamma参数的调优了。Gamma参数取值范围可以很大,我这里把取值范围设置为5了。你其实也可以取更精确的gamma值。
'gamma':[i/10.0 for i in range(0,5)] learning_rate =0.1, n_estimators=140, max_depth=4, min_child_weight=6, gamma=0, subsample=0.8, colsample_bytree=0.8, objective= 'binary:logistic', nthread=4, scale_pos_weight=1, seed=27
从这里可以看出来,我们在第一步调参时设置的初始gamma值就是比较合适的。也就是说,理想的gamma值为0。在这个过程开始之前,最好重新调整boosting回合,因为参数都有变化。
从这里可以看出,得分提高了。所以,最终得到的参数是:
learning_rate =0.1, n_estimators=1000, max_depth=4, min_child_weight=6, gamma=0, subsample=0.8, colsample_bytree=0.8, objective= 'binary:logistic', nthread=4, scale_pos_weight=1, seed=27
第四步:调整subsample 和 colsample_bytree 参数
下一步是尝试不同的subsample 和 colsample_bytree 参数。我们分两个阶段来进行这个步骤。这两个步骤都取0.6,0.7,0.8,0.9作为起始值。
'subsample':[i/10.0fori in range(6,10)], 'colsample_bytree':[i/10.0fori in range(6,10)] learning_rate =0.1, n_estimators=177, max_depth=3, min_child_weight=4, gamma=0.1, subsample=0.8, colsample_bytree=0.8, objective= 'binary:logistic', nthread=4, scale_pos_weight=1, seed=27
从这里可以看出来,subsample 和 colsample_bytree 参数的理想取值都是0.8。现在,我们以0.05为步长,在这个值附近尝试取值。
'subsample':[i/100.0fori in range(75,90,5)], 'colsample_bytree':[i/100.0fori in range(75,90,5)] learning_rate =0.1, n_estimators=177, max_depth=4, min_child_weight=6, gamma=0, subsample=0.8, colsample_bytree=0.8, objective= 'binary:logistic', nthread=4, scale_pos_weight=1, seed=27
我们得到的理想取值还是原来的值。因此,最终的理想取值是:
subsample: 0.8 colsample_bytree: 0.8
* 第五步:正则化参数调优。**
下一步是应用正则化来降低过拟合。由于gamma函数提供了一种更加有效地降低过拟合的方法,大部分人很少会用到这个参数。但是我们在这里也可以尝试用一下这个参数。我会在这里调整’reg_alpha’参数,然后’reg_lambda’参数留给你来完成。
'reg_alpha':[1e-5, 1e-2, 0.1, 1, 100] learning_rate =0.1, n_estimators=177, max_depth=4, min_child_weight=6, gamma=0.1, subsample=0.8, colsample_bytree=0.8, objective= 'binary:logistic', nthread=4, scale_pos_weight=1, seed=27
我们可以看到,相比之前的结果,CV的得分甚至还降低了。但是我们之前使用的取值是十分粗糙的,我们在这里选取一个比较靠近理想值(0.01)的取值,来看看是否有更好的表现。
'reg_alpha':[0, 0.001, 0.005, 0.01, 0.05] learning_rate =0.1, n_estimators=177, max_depth=4, min_child_weight=6, gamma=0.1, subsample=0.8, colsample_bytree=0.8, objective= 'binary:logistic', nthread=4, scale_pos_weight=1 ,seed=27
可以看到,CV的得分提高了。现在,我们在模型中来使用正则化参数,来看看这个参数的影响。
learning_rate =0.1, n_estimators=1000, max_depth=4, min_child_weight=6, gamma=0, subsample=0.8, colsample_bytree=0.8, reg_alpha=0.005, objective= 'binary:logistic', nthread=4, scale_pos_weight=1, seed=27
然后我们发现性能有了小幅度提高。
第6步:降低学习速率
最后,我们使用较低的学习速率,以及使用更多的决策树。我们可以用XGBoost中的CV函数来进行这一步工作。
learning_rate =0.01, n_estimators=5000, max_depth=4, min_child_weight=6, gamma=0, subsample=0.8, colsample_bytree=0.8, reg_alpha=0.005, objective= 'binary:logistic', nthread=4, scale_pos_weight=1, seed=27
(二)简化版本:
一般Xgboost调优的顺序可以参考如下:
确定一个较大的学习速率0.1
num_boost_round调优
max_depth 和 min_weight 参数调优
gamma参数调优
正则化参数调优
降低学习速率
第一步:关于num_boost_round的调优,一般有两种可选的方法:
首先将num_boost_round设的足够大,然后在运行的过程中我们看训练集和测试集的auc变化,一般来说训练集上面的auc会一直增加,但是测试集上面的auc会随着num_boost_round增大因为过拟合而下降,这样我们就会在训练过程中找到测试集的一个峰值,一旦找到,我们就可以结束训练了。
第二步:max_depth 和 min_weight 参数调优
先对这两个参数调优,是因为它们对最终结果有很大的影响。首先,我们先大范围地粗调参数,然后再小范围地微调。
第三步:gamma参数调优
第四步:调整subsample 和 colsample_bytree 参数
下一步是尝试不同的subsample 和 colsample_bytree 参数。我们分两个阶段来进行这个步骤。这两个步骤都取0.6,0.7,0.8,0.9作为起始值。
第五步:正则化参数调优
下一步是应用正则化来降低过拟合。由于gamma函数提供了一种更加有效地降低过拟合的方法,大部分人很少会用到这个参数。但是我们在这里也可以尝试用一下这个参数。
至此,你可以看到模型的表现有了大幅提升,调整每个参数带来的影响也更加清楚了。
三、总结
1、仅仅靠参数的调整和模型的小幅优化,想要让模型的表现有个大幅度提升是不可能的。GBM的最高得分是0.8487,XGBoost的最高得分是0.8494。确实是有一定的提升,但是没有达到质的飞跃。
2、要想让模型的表现有一个质的飞跃,需要依靠其他的手段,诸如,特征工程(feature egineering) ,模型组合(ensemble of model),以及堆叠(stacking)等。