-
2020-07-26 09:15:17
本文我们只谈调参,不讲理论,理论我也不会,爱咋咋地。
本文源自于这篇博文xgboost理论+实践,青出于蓝而不胜于蓝。
@@@@@@@@@@@@@@@@首先使用留出法验证,留出法比较节省时间@@@@@@@@@@@@第一步,确定n_estimators的数量
首先,确定测试集(给模型评估用),和xgb的初始参数(下面代码的参数是调好的,不要使用该参数,只是例子)。注意参数中eta最好大一点,基学习器的数量多一点。
valid_data = [(test_x,test_y)] xgb_params_final = {'eta': 0.1, 'n_estimators': 10000, 'gamma': 0, 'max_depth': 4, 'min_child_weight':5,'gamma':0.49,'subsample': 0.76,'colsample_bytree': 0.59, 'reg_lambda': 59,'reg_alpha': 0, 'colsample_bylevel': 1,'seed': 2020}
xgb_model_best = xgb.XGBRegressor(**xgb_params_final) xgb_model_best.fit(train_x_,train_y_,early_stopping_rounds = 50,eval_set = valid_set)
设置好早停次数和测试集就可以开始第一轮了。用此方法获得n_estimatoers。
第二步~ 第五步
参考下面的CV方法,不说了,只是我们使用for循环进行验证,不用cv。
最后一步,确定n_estimators的数量
参数确定好后,和第一步一样,降低学习率,获得n_estimators的数量,调参结束。
@@@@@@@@@@@@@@@@下面是CV方法@@@@@@@@@@@@@@
第一步,确定n_estimators的数量
首先需要确定一个较大的学习率,learning_rate先选择为0.1。其他次要参数随便设设就行
xgb_train_data = xgb.DMatrix(train_x,train_y) params = {'learning_rate' :0.1, #'n_estimators':10000, 'max_depth':5, 'min_child_weight':1, 'gamma':0, 'subsample':0.8, 'colsample_bytree':0.8, 'objective': 'multi:softmax', 'nthread':4, 'num_class':19, 'seed':27} xgb_cv = xgb.cv(params,xgb_train_data,num_boost_round = 10000, nfold = 5, metrics='mlogloss',early_stopping_rounds=50) len(xgb_cv)
第二步,确定max_depth 和 min_child_weight
params = { 'max_depth':range(3,12,2), 'min_child_weight':range(1,8,2) } grid = GridSearchCV(XGBClassifier(learning_rate =0.1, n_estimators=201, max_depth=5, min_child_weight=1, gamma=0, subsample=0.8, colsample_bytree=0.8, objective= 'multi:softmax', nthread=4, scale_pos_weight=1, seed=27), params, cv=5, scoring="accuracy",n_jobs = 4) grid.fit(train_x,train_y)
通常做法是先在一个大概的范围内确定一个粗糙的参数,然后再在这个粗糙的范围内细化。
第三步,确定gamma
在已经调整好其它参数的基础上,我们可以进行gamma参数的调优了。Gamma参数取值范围可以很大,我这里把取值范围设置为5了。你其实也可以取更精确的gamma值。
params = { 'gamma':[i/10.0 for i in range(0,5)] }
第四步,确定subsample 和 colsample_bytree
params = { 'subsample':[i/10.0 for i in range(6,10)], 'colsample_bytree':[i/10.0 for i in range(6,10)] }
第五步,正则化参数调优
params = { 'reg_alpha':[1e-5, 1e-2, 0.1, 1, 100] }
总结,其实大多数情况下,参数调优所带来的的性能提升很有限。性能想大幅度提升还是主要依靠特征工程MMP。
最后,当确定完所有的参数后,反过来再确定booster的数量。
更多相关内容 -
xgboost调参
2018-11-19 09:58:07xgboost调参教程 ,适合机器学习 与风控评分卡调参相关学习。 -
xgboost调参指南
2018-11-07 13:55:34xgboost调参过程,介绍xgboost调参的详细步骤,以及代码示例。 -
XGBoost调参步骤及常见问题
2021-11-30 10:22:12XGBoost参数设置 通用参数 这些参数用来控制XGBoost的宏观功能。 booster[默认gbtree] 选择每次迭代的模型,有两种选择: gbtree:基于树的模型 gbliner:线性模型 silent[默认0] 当这个参数值为1时,静默模式...XGBoost
xgboost中的基学习器除了可以是CART(gbtree)也可以是线性分类器(gblinear)
-
xgboost在目标函数中显示的加上了正则化项,基学习为CART时,正则化项与树的叶子节点的数量T和叶子节点的值有关。
正则项里包含了树的叶子节点个数、每个叶子节点上输出的score的L2模的平方和。
从Bias-variance tradeoff角度来讲,正则项降低了模型的variance,使学习出来的模型更加简单,防止过拟合,这也是xgboost优于传统GBDT的一个特性。
-
GB中使用Loss Function对f(x)的一阶导数计算出伪残差用于学习生成fm(x),xgboost不仅使用到了一阶导数,还使用二阶导数。
第t次的loss:
对上式做二阶泰勒展开:g为一阶导数,h为二阶导数
-
上面提到CART回归树中寻找最佳分割点的衡量标准是最小化均方差,XGBoost的并行是在特征粒度上的,XGBoost预先对特征的值进行排序,然后保存为block结构
xgboost寻找分割点的标准是最大化,lamda,gama与正则化项相关
xgboost算法的步骤和GB基本相同,都是首先初始化为一个常数,gb是根据一阶导数ri,xgboost是根据一阶导数gi和二阶导数hi,迭代生成基学习器,相加更新学习器。 -
xgboost考虑了训练数据为稀疏值的情况,可以为缺失值或者指定的值指定分支的默认方向,这能大大提升算法的效率
-
列抽样。xgboost借鉴了随机森林的做法,支持列抽样,不仅能降低过拟合,还能减少计算,这也是xgboost异于传统gbdt的一个特性。
XGBoost参数设置
通用参数
这些参数用来控制XGBoost的宏观功能。
-
booster[默认gbtree]
选择每次迭代的模型,有两种选择:
gbtree:基于树的模型
gbliner:线性模型 -
silent[默认0]
当这个参数值为1时,静默模式开启,不会输出任何信息。
一般这个参数就保持默认的0,因为这样能帮我们更好地理解模型。 -
nthread[默认值为最大可能的线程数]
这个参数用来进行多线程控制,应当输入系统的核数。
如果你希望使用CPU全部的核,那就不要输入这个参数,算法会自动检测它。
booster参数
-
max_depth[默认6]
和GBM中的参数相同,这个值为树的最大深度。
这个值也是用来避免过拟合的。max_depth越大,模型会学到更具体更局部的样本。
需要使用CV函数来进行调优。
典型值:3-10 -
eta[默认0.3]
和GBM中的 learning rate 参数类似。
通过减少每一步的权重,可以提高模型的鲁棒性。
典型值为0.01-0.2 -
base_score [ 默认0.5 ]
所有实例的初始化预测分数,全局偏置;
为了足够的迭代次数,改变这个值将不会有太大的影响。 -
min_child_weight[默认1]
决定最小叶子节点样本权重和。
和GBM的 min_child_leaf 参数类似,但不完全一样。XGBoost的这个参数是最小样本权重的和,而GBM参数是最小样本总数。
这个参数用于避免过拟合。当它的值较大时,可以避免模型学习到局部的特殊样本。
但是如果这个值过高,会导致欠拟合。这个参数需要使用CV来调整。 -
max_leaf_nodes
树上最大的节点或叶子的数量。
可以替代max_depth的作用。因为如果生成的是二叉树,一个深度为n的树最多生成 n 2 n^2 n2个叶子。
如果定义了这个参数,GBM会忽略max_depth参数。 -
gamma[默认0]
在节点分裂时,只有分裂后损失函数的值下降了,才会分裂这个节点。Gamma指定了节点分裂所需的最小损失函数下降值。
这个参数的值越大,算法越保守。这个参数的值和损失函数息息相关,所以是需要调整的。 -
max_delta_step[默认0]
这参数限制每棵树权重改变的最大步长。如果这个参数的值为0,那就意味着没有约束。如果它被赋予了某个正值,那么它会让这个算法更加保守。
通常,这个参数不需要设置。但是当各类别的样本十分不平衡时,它对逻辑回归是很有帮助的。
这个参数一般用不到,但是你可以挖掘出来它更多的用处。 -
subsample[默认1]
和GBM中的subsample参数一模一样。这个参数控制对于每棵树,随机采样的比例。
减小这个参数的值,算法会更加保守,避免过拟合。但是,如果这个值设置得过小,它可能会导致欠拟合。
典型值:0.5-1 -
colsample_bytree[默认1]
和GBM里面的max_features参数类似。用来控制每棵随机采样的列数的占比(每一列是一个特征)。
典型值:0.5-1 -
colsample_bylevel[默认1]
用来控制树的每一级的每一次分裂,对列数的采样的占比。
我个人一般不太用这个参数,因为subsample参数和colsample_bytree参数可以起到相同的作用。但是如果感兴趣,可以挖掘这个参数更多的用处。 -
lambda[默认1]
权重的L2正则化项。(和Ridge regression类似)。
这个参数是用来控制XGBoost的正则化部分的。虽然大部分数据科学家很少用到这个参数,但是这个参数在减少过拟合上还是可以挖掘出更多用处的。 -
alpha[默认1]
权重的L1正则化项。(和Lasso regression类似)。
可以应用在很高维度的情况下,使得算法的速度更快。 -
scale_pos_weight[默认1]
在各类别样本十分不平衡时,把这个参数设定为一个正值,可以使算法更快收敛
学习目标参数
这个参数用来控制理想的优化目标和每一步结果的度量方法
-
objective [ default=reg:linear ]
定义学习任务及相应的学习目标,可选的目标函数如下:
- “reg:linear” —— 线性回归。
- “reg:logistic”—— 逻辑回归。
- “binary:logistic”—— 二分类的逻辑回归问题,输出为概率。
- “binary:logitraw”—— 二分类的逻辑回归问题,输出的结果为wTx。
- “count:poisson”—— 计数问题的poisson回归,输出结果为poisson分布。在poisson回归中,max_delta_step的缺省值为0.7。(used to safeguard optimization)
- “multi:softmax” –让XGBoost采用softmax目标函数处理多分类问题,同时需要设置参数num_class(类别个数)
- “multi:softprob” –和softmax一样,但是输出的是ndata * nclass的向量,可以将该向量reshape成ndata行nclass列的矩阵。没行数据表示样本所属于每个类别的概率。
- “rank:pairwise” –set XGBoost to do ranking task by minimizing the pairwise loss
-
eval_metric [ default according to objective ]
对于回归问题,默认值是rmse,对于分类问题,默认值是error。- rmse 均方根误差
- mae 平均绝对误差
- logloss 负对数似然函数值
- error 二分类错误率(阈值为0.5)
- merror 多分类错误率
- mlogloss 多分类logloss损失函数
- auc 曲线下面积
-
seed [ default=0 ]
随机数的种子。缺省值为0
from sklearn.model_selection import train_test_split train_x, test_x, train_y, test_y = train_test_split(feature_matrix, labels, random_state=0) import xgboost as xgb dtrain=xgb.DMatrix(train_x,label=train_y) dtest=xgb.DMatrix(test_x) params={ 'booster': 'gbtree', 'objective': 'multi:softmax', # 多分类的问题 'num_class': 10, # 类别数,与 multisoftmax 并用 'gamma': 0.1, # 用于控制是否后剪枝的参数,越大越保守,一般0.1、0.2这样子。 'max_depth': 12, # 构建树的深度,越大越容易过拟合 'lambda': 2, # 控制模型复杂度的权重值的L2正则化项参数,参数越大,模型越不容易过拟合。 'subsample': 0.7, # 随机采样训练样本 'colsample_bytree': 0.7, # 生成树时进行的列采样 'min_child_weight': 3, 'silent': 1, # 设置成1则没有运行信息输出,最好是设置为0. 'eta': 0.1, # 如同学习率 'seed': 1000, 'nthread': 10 # cpu 线程数,默认值为最大可能的线程数 } watchlist = [(dtrain,'train')] bst=xgb.train(params,dtrain,num_boost_round=100,evals=watchlist) y_pred=bst.predict(dtest) y_pred_binary = (ypred >= 0.5)*1 from sklearn import metrics print 'AUC: %.4f' % metrics.roc_auc_score(test_y,y_pred) print 'ACC: %.4f' % metrics.accuracy_score(test_y,y_pred_binary) print 'Recall: %.4f' % metrics.recall_score(test_y,y_pred_binary) print 'F1-score: %.4f' %metrics.f1_score(test_y,y_pred_binary) print 'Precesion: %.4f' %metrics.precision_score(test_y,y_pred_binary) metrics.confusion_matrix(test_y,y_pred_binary)
参数调优的一般方法
我们会使用和GBM中相似的方法。需要进行如下步骤:
- 选择较高的学习速率(learning rate)。一般情况下,学习速率的值为0.1。但是,对于不同的问题,理想的学习速率有时候会在0.05到0.3之间波动。选择对应于此学习速率的理想决策树数量。XGBoost有一个很有用的函数“cv”,这个函数可以在每一次迭代中使用交叉验证,并返回理想的决策树数量。
- 对于给定的学习速率和决策树数量,进行决策树特定参数调优(max_depth, min_child_weight, gamma, subsample, colsample_bytree)。在确定一棵树的过程中,我们可以选择不同的参数。
- xgboost的正则化参数的调优。(lambda, alpha)。这些参数可以降低模型的复杂度,从而提高模型的表现。
- 降低学习速率,确定理想参数。
import xgboost as xgb data_train = xgb.DMatrix('agaricus_train.txt') data_test = xgb.DMatrix('agaricus_test.txt') print (data_train) print (type(data_train)) # 设置参数 param = {'max_depth': 3, 'eta': 1, 'silent': 1, 'objective': 'binary:logistic'} # 可以显示每一颗树添加后的误差 watchlist = [(data_test, 'eval'), (data_train, 'train')] n_round = 50 bst = xgb.train(param, data_train, num_boost_round=n_round, evals=watchlist, obj=log_reg, feval=error_rate) # 计算错误率 y_hat = bst.predict(data_test) y = data_test.get_label() print(y_hat) print(y)
XGBoost常见问题
xgboost 什么场景不适用
数据量很大以及特征比较多时太耗内存,太慢了,比如寻找最优特征分裂点时需要遍历所有特征去计算(虽然做了预排序和并行处理) ,但它还是很慢和很耗内存,需要读取所有数据到内存中才好做特征分裂。
GDBT 和Xgboost 的区别?
好的地方: 二阶泰勒展开,节点分数惩罚正则,增益计算不同,gbdt 是gini,xgb 是优化推导公式
-
传统的GBDT以CART作为基分类器,XGboost 还支持线性分类器,这时候xgboost 相当于带L1 和L2 正则化项的逻辑斯蒂回归(分类问题) 或者线性回归。
-
传统的GBDT在优化时只用到了一阶导数信息,xgboost 则对代价函数进行了二阶泰勒展开,同时用到了一阶和二阶导数,xgboost 还支持自定义代价函数,只要函数可一阶和二阶求导。
-
Xgboost 在代价函数中加入了正则项,用于控制模型的复杂度,正则项里包含了 树的叶子节点个数,每个叶子节点上输出的score 的L2 模的平方和。从Bias -variance tradeoff 角度来讲,正则项降低了模型的variance,使学习出来的模型更加简单,防止过拟合,这也就是xgboost 优于传统CBDT的一个特性。
-
Shrinkage ,相当于学习速率(xgboost 中的eta) .Xgboost 在进行完一次迭代后,会将叶子节点上权重·乘上该系数,主要是为了削弱每棵树的影响,让后面有更大的学习空间,实际应用中,一般把eta 设置的小一点,然后迭代次数设置的大一点。
-
列抽样,: xgboost 借鉴了随机森林的做法,支持列抽样,不仅能降低过拟合,还能减少计算,这也是xgboost 异于传统gdbt 的一个特性。
-
缺失值的处理,对特征的值有缺失的样本,xgboost 可以自动学习出它分裂的方向。
-
xgboost 支持并行,不是在trees 粒度的并行,而是在特征粒度上的,决策树的学习最耗时的一个步骤就是对特征的值进行排序(因为要确定最佳分割点) ,xgboost 在训练之前,预先对数据进行了排序,然后保存了block 结构,后面的迭代中重复使用了这个结构,大大减少了计算量。在进行节点分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算可以开多线程进行。
-
可并行的近似直方图算法,树节点在进行分裂时,我们需要计算每个特征的每个分割点对应的增益,即用贪心法枚举所有节能的分割点,当数据无法一次载入内存或者在分布式情况下,贪心算法效率就会变得很低,所以xgboost 还提出了一种可并行的近似直方图算法,用于高效的生成候选的分割点。
XGBoost 和lgb 的区别
是对GBDT 方法的不同实现,针对同一目标,做了不同的优化处理。
它们在基础逻辑上并没有啥不同,限定max_tree或者max_iterations,之后算法从0 棵树开始跑,每一轮根据上一轮的残差增加一颗决策树,在每一次增加决策树的时候选择当前最优结构,而在生成当前决策树的过程中,采用了不同的优化方案。
- XGBoost 使用基于预排序的决策树算法,每遍历一个特征需要计算一次特征增益,时间复杂度为Q(datafeature).
lgb 使用基于直方图的决策树算法,直方图的优化算法只需要计算k 次,时间复杂度为O(kfeature)
-
XGBoost 按照层生长的决策树生成,LGb采用带有深度限制的叶子节点算法,在分裂次数相同的情况下,leaf-wise 可以降低更多的误差,得到更好的精度,leaf-wise 的缺点在于会产生较深的决策树,产生过拟合。
-
支持类别特征,不需要进行独热编码处理。
-
优化了特征并行和数据并行算法,除此之外还添加了投票并行方案。
-
采用基于梯度的单边采用来保持数据分布,减少模型因数据分布发生变化而造成的模型精度下降。
-
特征捆绑转化为图着色问题,减少特征数量。
XGBoost分裂终止条件
-
当引入的分裂带来的增益小于一个阀值的时候,我们可以剪掉这个分裂,所以并不是每一次分裂loss function整体都会增加的,有点预剪枝的意思(其实我这里有点疑问的,一般后剪枝效果比预剪枝要好点吧,只不过复杂麻烦些,这里大神请指教,为啥这里使用的是预剪枝的思想,当然Xgboost支持后剪枝),阈值参数为γγ 正则项里叶子节点数T的系数(大神请确认下);
-
当树达到最大深度时则停止建立决策树,设置一个超参数max_depth,这个好理解吧,树太深很容易出现的情况学习局部样本,过拟合;
-
当样本权重和小于设定阈值时则停止建树,这个解释一下,涉及到一个超参数-最小的样本权重和min_child_weight,和GBM的 min_child_leaf 参数类似,但不完全一样,大意就是一个叶子节点样本太少了,也终止同样是过拟合;
-
-
Xgboost调参小结
2020-08-24 08:33:19XGBoost全称是eXtreme ... 本文主要介绍xgb算法的调参过程,xgb本质上是boosting方法,即通过在数据上逐一构建多个弱评估器,经过多次迭代逐渐累积多个弱评估器的方法。xgb中的每个分类器是cart树,因此树模型.XGBoost全称是eXtreme Gradient Boosting,由陈天奇所设计,和传统的梯度提升算法相比,XGBoost进行了许多改进,它能够比其他使用梯度提升的集成算法更加快速。关于xgboost的使用教程以及推导过程可以参考之前写的文章。
本文主要介绍xgb算法的调参过程,xgb本质上是boosting方法,即通过在数据上逐一构建多个弱评估器,经过多次迭代逐渐累积多个弱评估器的方法。xgb中的每个分类器是cart树,因此树模型对变量交叉会有较好的效果,但因此也容易产生过拟合。调参的步骤网上有很多教程,参数搜索的过程可以用网格搜索和贝叶斯优化(有空研究)。下面采用波士顿房产数据集,对xgb中调参做简单的学习介绍。
首先,建模并查看各类参数。from xgboost import XGBRegressor as XGBR from sklearn.ensemble import RandomForestRegressor as RFR from sklearn.linear_model import LinearRegression as LinearR from sklearn.datasets import load_boston from sklearn.model_selection import KFold, cross_val_score as CVS, train_test_split as TTS from sklearn.metrics import mean_squared_error as MSE import pandas as pd import numpy as np import matplotlib.pyplot as plt from time import time import datetime data = load_boston() X = data.data y = data.target Xtrain,Xtest,Ytrain,Ytest = TTS(X,y,test_size=0.3,random_state=420) #写明参数 param = {'silent':True #默认为False,通常要手动把它关闭掉 ,'objective':'reg:linear' ,"eta":0.1} num_round = 180 #n_estimators #类train,可以直接导入的参数是训练数据,树的数量,其他参数都需要通过params来导入 bst = xgb.train(param, dtrain, num_round) #接口predict preds = bst.predict(dtest)
xgb建模可以使用xgboost库,或者是使用sklearnAPI调用。实际情况中xgboost库本身训练模型效果会更优秀,且本身调参也方便许多。Xgboost自身有xgboost.cv()方法调参,如果是skleanAPI的话有GridSearchCV()方法进行调参。下面就用xgboost库建模,用xgboost.cv()的方法进行调参。
首先从设定默认参数开始,观察默认参数下交叉验证曲线的形状。
dfull = xgb.DMatrix(X,y) param1 = {'silent':True ,'obj':'reg:linear' ,"subsample":1 ,"max_depth":6 ,"eta":0.3 ,"gamma":0 ,"lambda":1 ,"alpha":0 ,"colsample_bytree":1 ,"colsample_bylevel":1 ,"colsample_bynode":1 ,"nfold":5} num_round = 200 cvresult1 = xgb.cv(param1, dfull, num_round) fig,ax = plt.subplots(1,figsize=(15,8)) ax.set_ylim(top=5) ax.grid() ax.plot(range(1,201),cvresult1.iloc[:,0],c="red",label="train,original") ax.plot(range(1,201),cvresult1.iloc[:,2],c="orange",label="test,original") ax.legend(fontsize="xx-large") plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FgBINfyj-1598229157502)(https://imgkr2.cn-bj.ufileos.com/bd1f050b-54dd-4ae4-b16c-34d52612d26e.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=6NaIiGfVLWbLu%252BiFTwTX0k2ti58%253D&Expires=1598275140)]
从曲线上可以看出模型处于过拟合状态,需要进行剪枝。剪枝的目的是训练集和测试集的结果尽量接近,即上图中训练集的曲线上升,测试集的曲线下降。
下面用三组曲线展示调参结果,一组是原始数据的结果,一组是上一个参数调节结束的结果,还有一组是现在在调节参数的结果。param1 = {'silent':True ,'obj':'reg:linear' ,"subsample":1 ,"max_depth":6 ,"eta":0.3 ,"gamma":0 ,"lambda":1 ,"alpha":0 ,"colsample_bytree":1 ,"colsample_bylevel":1 ,"colsample_bynode":1 ,"nfold":5} num_round = 200 cvresult1 = xgb.cv(param1, dfull, num_round) fig,ax = plt.subplots(1,figsize=(15,8)) ax.set_ylim(top=5) ax.grid() ax.plot(range(1,201),cvresult1.iloc[:,0],c="red",label="train,original") ax.plot(range(1,201),cvresult1.iloc[:,2],c="orange",label="test,original") param2 = {'silent':True ,'obj':'reg:linear' ,"max_depth":2 ,"eta":0.05 ,"gamma":0 ,"lambda":1 ,"alpha":0 ,"colsample_bytree":1 ,"colsample_bylevel":0.4 ,"colsample_bynode":1 ,"nfold":5} param3 = {'silent':True ,'obj':'reg:linear' ,"subsample":1 ,"eta":0.05 ,"gamma":20 ,"lambda":3.5 ,"alpha":0.2 ,"max_depth":4 ,"colsample_bytree":0.4 ,"colsample_bylevel":0.6 ,"colsample_bynode":1 ,"nfold":5} cvresult2 = xgb.cv(param2, dfull, num_round) cvresult3 = xgb.cv(param3, dfull, num_round) ax.plot(range(1,201),cvresult2.iloc[:,0],c="green",label="train,last") ax.plot(range(1,201),cvresult2.iloc[:,2],c="blue",label="test,last") ax.plot(range(1,201),cvresult3.iloc[:,0],c="gray",label="train,this") ax.plot(range(1,201),cvresult3.iloc[:,2],c="pink",label="test,this") ax.legend(fontsize="xx-large") plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3kzqOeBb-1598229157506)(https://imgkr2.cn-bj.ufileos.com/e8777aae-82d2-4862-8684-347ce59e2bec.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=3OIgIAOk26JtFx%252BRX6h0NtRxp6M%253D&Expires=1598275152)]
这里用到的是手动调参的方法,需要一定的调参经验结合损失函数的变化。网格搜索需要足够的计算机资源,且往往运行速度很慢,建议先用xgboost.cv()来确认参数的范围,而且调参过程中用np.linespace()还是np.arange()也会影响调参结果。
调参顺序也会会影响调参结果。所以一般会优先调对模型影响较大的参数。一般先n_estimators和eta共同调节,然后gamma和max_depth,再是采样和抽样参数,最后是正则化的两个参数。
调参常用参数介绍
附上之前学习xgboost时的笔记,记录了各个参数的含义及调参步骤。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cah5GjLr-1598229157510)(https://imgkr2.cn-bj.ufileos.com/f4bb58db-5161-42c6-9742-bdfda7bcdde7.jpg?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=5kLqPU57viLMKa89uQpGVPGzW%252BY%253D&Expires=1598275162)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TtafZLh7-1598229157515)(https://imgkr2.cn-bj.ufileos.com/3d288610-9faf-4dd6-9d8e-29e5ac4d0d8e.jpg?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=8ZAzojDOnzwzQNiDIJmDvGaLhdg%253D&Expires=1598275174)]
1.n_estimators
n_estimators是集成中弱估计器的数量,即树的个数。使用参数学习曲线观察n_estimators对模型的影响。axisx = range(10,1010,50) rs = [] for i in axisx: reg = XGBR(n_estimators=i,random_state=420) rs.append(CVS(reg,Xtrain,Ytrain,cv=cv).mean()) print(axisx[rs.index(max(rs))],max(rs)) plt.figure(figsize=(20,5)) plt.plot(axisx,rs,c="red",label="XGB") plt.legend() plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1rplHV9Z-1598229157518)(https://imgkr2.cn-bj.ufileos.com/7542bb0a-6c12-4496-bf59-7cf988ebd665.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=58qsGMQxzqyGsTtQAJr7nBhgVzE%253D&Expires=1598275186)]
从上图看出n_estimators在80附近的时候准确率已达到最高,这里无需选择准确率达到最高的n_estiamtors。在机器学习中,我们用来衡量模型在未知数据上的准确率的指标,叫做泛化误差。泛化误差由方差、偏差和噪声共同决定。其中,偏差是指模型的拟合程度,方差是指模型的稳定性,噪音则是随机因素。在绘制学习曲线时,不仅要考虑偏差的大小,还要考虑方差的大小。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-idEjxluH-1598229157521)(https://imgkr2.cn-bj.ufileos.com/047b4e8c-336b-4f42-a238-ee0eac212ac0.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=6Sz4B%252Fnlg8xNBZi9beT77BTDA74%253D&Expires=1598275197)]基于这种思路,来改进学习曲线:
axisx = range(50,1050,50) rs = [] var = [] ge = [] for i in axisx: reg = XGBR(n_estimators=i,random_state=420) cvresult = CVS(reg,Xtrain,Ytrain,cv=cv) #记录1-偏差 rs.append(cvresult.mean()) #记录方差 var.append(cvresult.var()) #计算泛化误差的可控部分 ge.append((1 - cvresult.mean())**2+cvresult.var()) #打印R2最高所对应的参数取值,并打印这个参数下的方差 print(axisx[rs.index(max(rs))],max(rs),var[rs.index(max(rs))]) #打印方差最低时对应的参数取值,并打印这个参数下的R2 print(axisx[var.index(min(var))],rs[var.index(min(var))],min(var)) #打印泛化误差可控部分的参数取值,并打印这个参数下的R2,方差以及泛化误差的可控部分 print(axisx[ge.index(min(ge))],rs[ge.index(min(ge))],var[ge.index(min(ge))],min(ge)) plt.figure(figsize=(20,5)) plt.plot(axisx,rs,c="red",label="XGB") plt.legend() plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3ldaRHvn-1598229157523)(https://imgkr2.cn-bj.ufileos.com/549c8c92-03a7-4a03-8e39-654540f55f2a.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=2W28Nsw6LF052Xkh3SpTUoH4ir4%253D&Expires=1598275207)]
由上图可知,泛化误差可控制的部分在n_estimators取150的时候最小。将模型的方差、偏差、泛化误差中可控部分绘制在一张图上:
axisx = range(100,300,10) rs = [] var = [] ge = [] for i in axisx: reg = XGBR(n_estimators=i,random_state=420) cvresult = CVS(reg,Xtrain,Ytrain,cv=cv) rs.append(cvresult.mean()) var.append(cvresult.var()) ge.append((1 - cvresult.mean())**2+cvresult.var()) print(axisx[rs.index(max(rs))],max(rs),var[rs.index(max(rs))]) print(axisx[var.index(min(var))],rs[var.index(min(var))],min(var)) print(axisx[ge.index(min(ge))],rs[ge.index(min(ge))],var[ge.index(min(ge))],min(ge)) rs = np.array(rs) var = np.array(var)*0.01 plt.figure(figsize=(20,5)) plt.plot(axisx,rs,c="black",label="XGB") #添加方差线 plt.plot(axisx,rs+var,c="red",linestyle='-.') plt.plot(axisx,rs-var,c="red",linestyle='-.') plt.legend() plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vB4xtsEa-1598229157526)(https://imgkr2.cn-bj.ufileos.com/5515e389-77c5-4ba9-9f49-bbc03abad7b0.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=THzYeJZ5GzEejTOyTsMKnxpM9rM%253D&Expires=1598275218)]
可以看到n_estimators在180时的时候模型效果最优,n_estimators是xgb中一般调整的第一个参数,300以下为佳。其它单个参数的调节方法可以以此类推。
2.subsample
确认了树的数目之后,对每一颗树如果都使用全量数据进行训练的话,会导致计算非常缓慢。因此需要对训练数据集进行抽样。有放回的抽样每次只能抽取一个样本,若我们需要总共N个样本,就需要抽取N次。每次抽取一个样本的过程是独立的。实际应用中,每次抽取50%左右的数据就能够有不错的效果。
在梯度提升树中,每一次迭代都要建立一棵新的树,因此每次迭代中,都要有放回抽取一个新的训练样本。为了保证每次建新树后,集成的效果都比之前要好。因此在梯度提升树中,每构建一个评估器,都让模型更加集中于数据集中容易被判错的那些样本。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hBP2strh-1598229157528)(https://imgkr2.cn-bj.ufileos.com/8af3f798-35f9-44ce-b3e4-14766909bef7.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=GLePatHuSpvIIR%252FWp3fqd7WDrM4%253D&Expires=1598275227)]3.eta
迭代决策树时的步长,又叫学习率。eta越大,迭代的速度越快,算法的极限很快被达到,有可能无法收敛到真正的最佳。 越小,越有可能找到更精确的最佳值,更多的空间被留给了后面建立的树,但迭代速度会比较缓慢。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z6RcOk04-1598229157529)(https://imgkr2.cn-bj.ufileos.com/b70bcf19-1905-468f-aa43-fea75a234a6e.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=93CWh1MFZmDx4iy7wVfO1tSHQr4%253D&Expires=1598275239)]eta默认值为0.1,而且更小的步长更利于现在的数据,但由于无
法确定对于其他数据会有怎么样的效果,所以通常对eta不做调整 ,即便调整,一般只会在[0.01,0.2]之间变动。4.Gamma
gamma是用来防止过拟合的重要参数,是梯度提升树影响最大的参数之一,同时也是停止树生长的重要参数之一。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2F0wohGM-1598229157531)(https://imgkr2.cn-bj.ufileos.com/082239b4-e394-41ee-a2bc-c2f5bc02fc9a.jpg?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=rEYxWNG0eevGizDsddCNUR7i0Ug%253D&Expires=1598275251)]
gamma是每增加一片叶子就会被减去的惩罚项,增加的叶子越多,结构分数之差Gain就会惩罚越重,因此gamma又被称作复杂性控制。只要Gain大于0,即只要目标函数还能够继续减小,树就可以进行继续分枝。所以gamma可以定义为在树的节点上进行进一步分支所需要的最小目标函数减少量。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fifCJnwk-1598229157533)(https://imgkr2.cn-bj.ufileos.com/f8b0fe1b-1ce9-4102-99d0-479d6684ae26.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=tYWrxENgmQhc3DqsmMFlimATBVQ%253D&Expires=1598275267)]param1 = {'silent':True,'obj':'reg:linear',"gamma":0} param2 = {'silent':True,'obj':'reg:linear',"gamma":20} num_round = 180 n_fold=5 cvresult1 = xgb.cv(param1, dfull, num_round,n_fold) cvresult2 = xgb.cv(param2, dfull, num_round,n_fold) plt.figure(figsize=(20,5)) plt.grid() plt.plot(range(1,181),cvresult1.iloc[:,0],c="red",label="train,gamma=0") plt.plot(range(1,181),cvresult1.iloc[:,2],c="orange",label="test,gamma=0") plt.plot(range(1,181),cvresult2.iloc[:,0],c="green",label="train,gamma=20") plt.plot(range(1,181),cvresult2.iloc[:,2],c="blue",label="test,gamma=20") plt.legend() plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AoWWRdX2-1598229157534)(https://imgkr2.cn-bj.ufileos.com/066b7d06-28dc-4b83-bb41-16a0cbdd7ecb.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=YG7aoGCZ1mvUBIx8PZFX71DbeuQ%253D&Expires=1598275280)]
这里的评价函数用的是RMASE,当gamma越小算法越复杂,相应的RMSE就会越低。在上图中表现就是gamma为0的曲线(红色)要低于gamma为20的曲线。在树增加到10棵之后,评价函数就不再有明显的下降趋势了。
作为天生过拟合的模型,XGBoost应用的核心之一就是减轻过拟合带来的影响。作为树模型,减轻过拟合的方式主要是靠对决策树剪枝来降低模型的复杂度,以求降低方差。用来防止过拟合的参数,有复杂度控制gamma ,正则化的两个参数lambda和alpha,控制迭代速度的参数eta以及随机有放回抽样的参数subsample。所有的这些参数都可以用来减轻过拟合。除此之外,还有几个影响重大的,专用于剪枝的参数:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oGOUX299-1598229157536)(https://imgkr2.cn-bj.ufileos.com/b41e6076-a486-4ec8-9cb2-dee88d289dfa.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=XWxMf4GCTNad5lFNqAkYFOolfVw%253D&Expires=1598275291)]1.这些参数中,树的最大深度是决策树中的剪枝法宝,算是最常用的剪枝参数,不过在XGBoost中,最大深度的功能与参数gamma相似,因此如果先调节了gamma,则最大深度可能无法展示出巨大的效果。通常来说,这两个参数中只使用一个。
2.三个随机抽样特征的参数中,前两个比较常用。在建立树时对特征进行抽样其实是决策树和随机森林中比较常见的一种方法,但是在XGBoost之前,这种方法并没有被使用到boosting算法当中过。Boosting算法一直以抽取样本(横向抽样)来调整模型过拟合的程度,而实践证明其实纵向抽样(抽取特征)更能够防止过拟合。
3.参数min_child_weight不太常用,它是一篇叶子上的二阶导数 之和,当样本所对应的二阶导数很小时,比如说为
0.01,min_child_weight若设定为1,则说明一片叶子上至少需要100个样本。本质上来说,这个参数其实是在控制叶子上所需的最小样本量,因此对于样本量很大的数据会比较有效。如果样本量很小则这个参数效用不大。【作者】:Labryant
【原创公众号】:风控猎人
【简介】:某创业公司策略分析师,积极上进,努力提升。乾坤未定,你我都是黑马。
【转载说明】:转载请说明出处,谢谢合作!~ -
XGboost调参
2018-09-05 16:55:32如果你的预测模型表现得有些不尽如人意,那就用XGBoost吧。XGBoost算法现在已经成为很多数据工程师的重要武器。它是一种十分精致的算法,可以处理各种不规则的数据。 构造一个使用XGBoost的模型十分简单。但是,提高...简介
如果你的预测模型表现得有些不尽如人意,那就用XGBoost吧。XGBoost算法现在已经成为很多数据工程师的重要武器。它是一种十分精致的算法,可以处理各种不规则的数据。
构造一个使用XGBoost的模型十分简单。但是,提高这个模型的表现就有些困难(至少我觉得十分纠结)。这个算法使用了好几个参数。所以为了提高模型的表现,参数的调整十分必要。在解决实际问题的时候,有些问题是很难回答的——你需要调整哪些参数?这些参数要调到什么值,才能达到理想的输出?
这篇文章最适合刚刚接触XGBoost的人阅读。在这篇文章中,我们会学到参数调优的技巧,以及XGboost相关的一些有用的知识。以及,我们会用Python在一个数据集上实践一下这个算法。你需要知道的
XGBoost(eXtreme Gradient Boosting)是Gradient Boosting算法的一个优化的版本。
特别鸣谢:我个人十分感谢Mr Sudalai Rajkumar (aka SRK)大神的支持,目前他在AV Rank中位列第二。如果没有他的帮助,就没有这篇文章。在他的帮助下,我们才能给无数的数据科学家指点迷津。给他一个大大的赞!
内容列表
1、XGBoost的优势
2、理解XGBoost的参数
3、调整参数(含示例)1、XGBoost的优势
XGBoost算法可以给预测模型带来能力的提升。当我对它的表现有更多了解的时候,当我对它的高准确率背后的原理有更多了解的时候,我发现它具有很多优势:
1、正则化
标准GBM的实现没有像XGBoost这样的正则化步骤。正则化对减少过拟合也是有帮助的。 实际上,XGBoost以“正则化提升(regularized boosting)”技术而闻名。
2、并行处理
XGBoost可以实现并行处理,相比GBM有了速度的飞跃。 不过,众所周知,Boosting算法是顺序处理的,它怎么可能并行呢?每一课树的构造都依赖于前一棵树,那具体是什么让我们能用多核处理器去构造一个树呢?我希望你理解了这句话的意思。 XGBoost 也支持Hadoop实现。
3、高度的灵活性
XGBoost 允许用户定义自定义优化目标和评价标准 它对模型增加了一个全新的维度,所以我们的处理不会受到任何限制。
4、缺失值处理
XGBoost内置处理缺失值的规则。 用户需要提供一个和其它样本不同的值,然后把它作为一个参数传进去,以此来作为缺失值的取值。XGBoost在不同节点遇到缺失值时采用不同的处理方法,并且会学习未来遇到缺失值时的处理方法。
5、剪枝
当分裂时遇到一个负损失时,GBM会停止分裂。因此GBM实际上是一个贪心算法。 XGBoost会一直分裂到指定的最大深度(max_depth),然后回过头来剪枝。如果某个节点之后不再有正值,它会去除这个分裂。 这种做法的优点,当一个负损失(如-2)后面有个正损失(如+10)的时候,就显现出来了。GBM会在-2处停下来,因为它遇到了一个负值。但是XGBoost会继续分裂,然后发现这两个分裂综合起来会得到+8,因此会保留这两个分裂。
6、内置交叉验证
XGBoost允许在每一轮boosting迭代中使用交叉验证。因此,可以方便地获得最优boosting迭代次数。 而GBM使用网格搜索,只能检测有限个值。
7、在已有的模型基础上继续
XGBoost可以在上一轮的结果上继续训练。这个特性在某些特定的应用上是一个巨大的优势。 sklearn中的GBM的实现也有这个功能,两种算法在这一点上是一致的。
相信你已经对XGBoost强大的功能有了点概念。注意这是我自己总结出来的几点,你如果有更多的想法,尽管在下面评论指出,我会更新这个列表的!
2、XGBoost的参数
XGBoost的作者把所有的参数分成了三类:
1、通用参数:宏观函数控制。
2、Booster参数:控制每一步的booster(tree/regression)。
3、学习目标参数:控制训练目标的表现。
在这里我会类比GBM来讲解,所以作为一种基础知识。通用参数
这些参数用来控制XGBoost的宏观功能。
1、booster[默认gbtree]
选择每次迭代的模型,有两种选择:
gbtree:基于树的模型
gbliner:线性模型2、silent[默认0]
当这个参数值为1时,静默模式开启,不会输出任何信息。 一般这个参数就保持默认的0,因为这样能帮我们更好地理解模型。
3、nthread[默认值为最大可能的线程数]
这个参数用来进行多线程控制,应当输入系统的核数。 如果你希望使用CPU全部的核,那就不要输入这个参数,算法会自动检测它。
还有两个参数,XGBoost会自动设置,目前你不用管它。接下来咱们一起看booster参数。booster参数
尽管有两种booster可供选择,我这里只介绍tree booster,因为它的表现远远胜过linear booster,所以linear booster很少用到。
1、eta[默认0.3]
和GBM中的 learning rate 参数类似。 通过减少每一步的权重,可以提高模型的鲁棒性。 典型值为0.01-0.2。
2、min_child_weight[默认1]
决定最小叶子节点样本权重和。 和GBM的 min_child_leaf 参数类似,但不完全一样。XGBoost的这个参数是最小样本权重的和,而GBM参数是最小样本总数。 这个参数用于避免过拟合。当它的值较大时,可以避免模型学习到局部的特殊样本。 但是如果这个值过高,会导致欠拟合。这个参数需要使用CV来调整。
3、max_depth[默认6]
和GBM中的参数相同,这个值为树的最大深度。 这个值也是用来避免过拟合的。max_depth越大,模型会学到更具体更局部的样本。 需要使用CV函数来进行调优。 典型值:3-10
4、max_leaf_nodes
树上最大的节点或叶子的数量。 可以替代max_depth的作用。因为如果生成的是二叉树,一个深度为n的树最多生成n2个叶子。 如果定义了这个参数,GBM会忽略max_depth参数。
5、gamma[默认0]
在节点分裂时,只有分裂后损失函数的值下降了,才会分裂这个节点。Gamma指定了节点分裂所需的最小损失函数下降值。 这个参数的值越大,算法越保守。这个参数的值和损失函数息息相关,所以是需要调整的。
6、max_delta_step[默认0]
这参数限制每棵树权重改变的最大步长。如果这个参数的值为0,那就意味着没有约束。如果它被赋予了某个正值,那么它会让这个算法更加保守。 通常,这个参数不需要设置。但是当各类别的样本十分不平衡时,它对逻辑回归是很有帮助的。 这个参数一般用不到,但是你可以挖掘出来它更多的用处。
7、subsample[默认1]
和GBM中的subsample参数一模一样。这个参数控制对于每棵树,随机采样的比例。 减小这个参数的值,算法会更加保守,避免过拟合。但是,如果这个值设置得过小,它可能会导致欠拟合。 典型值:0.5-1
8、colsample_bytree[默认1]
和GBM里面的max_features参数类似。用来控制每棵随机采样的列数的占比(每一列是一个特征)。 典型值:0.5-1
9、colsample_bylevel[默认1]
用来控制树的每一级的每一次分裂,对列数的采样的占比。 我个人一般不太用这个参数,因为subsample参数和colsample_bytree参数可以起到相同的作用。但是如果感兴趣,可以挖掘这个参数更多的用处。
10、lambda[默认1]
权重的L2正则化项。(和Ridge regression类似)。 这个参数是用来控制XGBoost的正则化部分的。虽然大部分数据科学家很少用到这个参数,但是这个参数在减少过拟合上还是可以挖掘出更多用处的。
11、alpha[默认1]
权重的L1正则化项。(和Lasso regression类似)。 可以应用在很高维度的情况下,使得算法的速度更快。
12、scale_pos_weight[默认1]
在各类别样本十分不平衡时,把这个参数设定为一个正值,可以使算法更快收敛。
学习目标参数
这个参数用来控制理想的优化目标和每一步结果的度量方法。
1、objective[默认reg:linear]
这个参数定义需要被最小化的损失函数。最常用的值有:
binary:logistic 二分类的逻辑回归,返回预测的概率(不是类别)。 multi:softmax 使用softmax的多分类器,返回预测的类别(不是概率)。
在这种情况下,你还需要多设一个参数:num_class(类别数目)。 multi:softprob 和multi:softmax参数一样,但是返回的是每个数据属于各个类别的概率。2、eval_metric[默认值取决于objective参数的取值]
对于有效数据的度量方法。 对于回归问题,默认值是rmse,对于分类问题,默认值是error。 典型值有:
rmse 均方根误差(∑Ni=1?2N??????√) mae 平均绝对误差(∑Ni=1|?|N) logloss 负对数似然函数值 error 二分类错误率(阈值为0.5) merror 多分类错误率 mlogloss 多分类logloss损失函数 auc 曲线下面积3、seed(默认0)
随机数的种子 设置它可以复现随机数据的结果,也可以用于调整参数
如果你之前用的是Scikit-learn,你可能不太熟悉这些参数。但是有个好消息,python的XGBoost模块有一个sklearn包,XGBClassifier。这个包中的参数是按sklearn风格命名的。会改变的函数名是:
1、eta ->learning_rate
2、lambda->reg_lambda
3、alpha->reg_alpha
你肯定在疑惑为啥咱们没有介绍和GBM中的’n_estimators’类似的参数。XGBClassifier中确实有一个类似的参数,但是,是在标准XGBoost实现中调用拟合函数时,把它作为’num_boosting_rounds’参数传入。调整参数(含示例)
我已经对这些数据进行了一些处理:
City变量,因为类别太多,所以删掉了一些类别。 DOB变量换算成年龄,并删除了一些数据。 增加了 EMI_Loan_Submitted_Missing 变量。如果EMI_Loan_Submitted变量的数据缺失,则这个参数的值为1。否则为0。删除了原先的EMI_Loan_Submitted变量。 EmployerName变量,因为类别太多,所以删掉了一些类别。 因为Existing_EMI变量只有111个值缺失,所以缺失值补充为中位数0。 增加了 Interest_Rate_Missing 变量。如果Interest_Rate变量的数据缺失,则这个参数的值为1。否则为0。删除了原先的Interest_Rate变量。 删除了Lead_Creation_Date,从直觉上这个特征就对最终结果没什么帮助。 Loan_Amount_Applied, Loan_Tenure_Applied 两个变量的缺项用中位数补足。 增加了 Loan_Amount_Submitted_Missing 变量。如果Loan_Amount_Submitted变量的数据缺失,则这个参数的值为1。否则为0。删除了原先的Loan_Amount_Submitted变量。 增加了 Loan_Tenure_Submitted_Missing 变量。如果 Loan_Tenure_Submitted 变量的数据缺失,则这个参数的值为1。否则为0。删除了原先的 Loan_Tenure_Submitted 变量。 删除了LoggedIn, Salary_Account 两个变量 增加了 Processing_Fee_Missing 变量。如果 Processing_Fee 变量的数据缺失,则这个参数的值为1。否则为0。删除了原先的 Processing_Fee 变量。 Source前两位不变,其它分成不同的类别。 进行了量化和独热编码(一位有效编码)。
如果你有原始数据,可以从资源库里面下载data_preparation的Ipython notebook 文件,然后自己过一遍这些步骤。
首先,import必要的库,然后加载数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<code>#Import libraries:
import
pandas as pd
import
numpy as np
import
xgboost as xgb
from xgboost.sklearn
import
XGBClassifier
from sklearn
import
cross_validation, metrics #Additional scklearn functions
from sklearn.grid_search
import
GridSearchCV #Perforing grid search
import
matplotlib.pylab as plt
%matplotlib inline
from matplotlib.pylab
import
rcParams
rcParams[
'figure.figsize'
] =
12
,
4
train = pd.read_csv(
'train_modified.csv'
)
target =
'Disbursed'
IDcol =
'ID'
</code>
注意我import了两种XGBoost:
xgb - 直接引用xgboost。接下来会用到其中的“cv”函数。 XGBClassifier - 是xgboost的sklearn包。这个包允许我们像GBM一样使用Grid Search 和并行处理。
在向下进行之前,我们先定义一个函数,它可以帮助我们建立XGBoost models 并进行交叉验证。好消息是你可以直接用下面的函数,以后再自己的models中也可以使用它。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<code><code>def modelfit(alg, dtrain, predictors,useTrainCV=True, cv_folds=
5
, early_stopping_rounds=
50
):
if
useTrainCV:
xgb_param = alg.get_xgb_params()
xgtrain = xgb.DMatrix(dtrain[predictors].values, label=dtrain[target].values)
cvresult = xgb.cv(xgb_param, xgtrain, num_boost_round=alg.get_params()[
'n_estimators'
], nfold=cv_folds,
metrics=
'auc'
, early_stopping_rounds=early_stopping_rounds, show_progress=False)
alg.set_params(n_estimators=cvresult.shape[
0
])
#Fit the algorithm on the data
alg.fit(dtrain[predictors], dtrain[
'Disbursed'
],eval_metric=
'auc'
)
#Predict training set:
dtrain_predictions = alg.predict(dtrain[predictors])
dtrain_predprob = alg.predict_proba(dtrain[predictors])[:,
1
]
#Print model report:
print
"\nModel Report"
print
"Accuracy : %.4g"
% metrics.accuracy_score(dtrain[
'Disbursed'
].values, dtrain_predictions)
print
"AUC Score (Train): %f"
% metrics.roc_auc_score(dtrain[
'Disbursed'
], dtrain_predprob)
feat_imp = pd.Series(alg.booster().get_fscore()).sort_values(ascending=False)
feat_imp.plot(kind=
'bar'
, title=
'Feature Importances'
)
plt.ylabel(
'Feature Importance Score'
)
</code></code>
这个函数和GBM中使用的有些许不同。不过本文章的重点是讲解重要的概念,而不是写代码。如果哪里有不理解的地方,请在下面评论,不要有压力。注意xgboost的sklearn包没有“feature_importance”这个量度,但是get_fscore()函数有相同的功能。
参数调优的一般方法。
我们会使用和GBM中相似的方法。需要进行如下步骤:
1. 选择较高的学习速率(learning rate)。一般情况下,学习速率的值为0.1。但是,对于不同的问题,理想的学习速率有时候会在0.05到0.3之间波动。选择对应于此学习速率的理想决策树数量。XGBoost有一个很有用的函数“cv”,这个函数可以在每一次迭代中使用交叉验证,并返回理想的决策树数量。
2. 对于给定的学习速率和决策树数量,进行决策树特定参数调优(max_depth, min_child_weight, gamma, subsample, colsample_bytree)。在确定一棵树的过程中,我们可以选择不同的参数,待会儿我会举例说明。
3. xgboost的正则化参数的调优。(lambda, alpha)。这些参数可以降低模型的复杂度,从而提高模型的表现。
4. 降低学习速率,确定理想参数。咱们一起详细地一步步进行这些操作。
第一步:确定学习速率和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函数来确定最佳的决策树数量。前文中的函数可以完成这个工作。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<code><code><code>#Choose all predictors except target & IDcols
predictors = [x
for
x in train.columns
if
x not in [target,IDcol]]
xgb1 = XGBClassifier(
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
)
modelfit(xgb1, train, predictors)
</code></code></code>
从输出结果可以看出,在学习速率为0.1时,理想的决策树数目是140。这个数字对你而言可能比较高,当然这也取决于你的系统的性能。
注意:在AUC(test)这里你可以看到测试集的AUC值。但是如果你在自己的系统上运行这些命令,并不会出现这个值。因为数据并不公开。这里提供的值仅供参考。生成这个值的代码部分已经被删掉了。
<喎�"/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjwvYmxvY2txdW90ZT4NCjxoMSBpZD0="第二步-maxdepth-和-minweight-参数调优">第二步: max_depth 和 min_weight 参数调优
我们先对这两个参数调优,是因为它们对最终结果有很大的影响。首先,我们先大范围地粗调参数,然后再小范围地微调。
注意:在这一节我会进行高负荷的栅格搜索(grid search),这个过程大约需要15-30分钟甚至更久,具体取决于你系统的性能。你也可以根据自己系统的性能选择不同的值。1
2
3
4
5
6
7
8
9
10
11
<code><code><code><code>param_test1 = {
'max_depth'
:range(
3
,
10
,
2
),
'min_child_weight'
:range(
1
,
6
,
2
)
}
gsearch1 = GridSearchCV(estimator = XGBClassifier( 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
),
param_grid = param_test1, scoring=
'roc_auc'
,n_jobs=
4
,iid=False, cv=
5
)
gsearch1.fit(train[predictors],train[target])
gsearch1.grid_scores_, gsearch1.best_params_, gsearch1.best_score_
</code></code></code></code>
至此,我们对于数值进行了较大跨度的12中不同的排列组合,可以看出理想的max_depth值为5,理想的min_child_weight值为5。在这个值附近我们可以再进一步调整,来找出理想值。我们把上下范围各拓展1,因为之前我们进行组合的时候,参数调整的步长是2。
1
2
3
4
5
6
7
8
9
10
11
<code><code><code><code><code>param_test2 = {
'max_depth'
:[
4
,
5
,
6
],
'min_child_weight'
:[
4
,
5
,
6
]
}
gsearch2 = GridSearchCV(estimator = XGBClassifier( 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
),
param_grid = param_test2, scoring=
'roc_auc'
,n_jobs=
4
,iid=False, cv=
5
)
gsearch2.fit(train[predictors],train[target])
gsearch2.grid_scores_, gsearch2.best_params_, gsearch2.best_score_
</code></code></code></code></code>
至此,我们得到max_depth的理想取值为4,min_child_weight的理想取值为6。同时,我们还能看到cv的得分有了小小一点提高。需要注意的一点是,随着模型表现的提升,进一步提升的难度是指数级上升的,尤其是你的表现已经接近完美的时候。当然啦,你会发现,虽然min_child_weight的理想取值是6,但是我们还没尝试过大于6的取值。像下面这样,就可以尝试其它值。
1
2
3
4
5
6
7
8
9
10
11
12
<code><code><code><code><code><code>param_test2b = {
'min_child_weight'
:[
6
,
8
,
10
,
12
]
}
gsearch2b = GridSearchCV(estimator = XGBClassifier( 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
),
param_grid = param_test2b, scoring=
'roc_auc'
,n_jobs=
4
,iid=False, cv=
5
)
gsearch2b.fit(train[predictors],train[target])
modelfit(gsearch3.best_estimator_, train, predictors)
gsearch2b.grid_scores_, gsearch2b.best_params_, gsearch2b.best_score_
</code></code></code></code></code></code>
我们可以看出,6确确实实是理想的取值了。
第三步:gamma参数调优
在已经调整好其它参数的基础上,我们可以进行gamma参数的调优了。Gamma参数取值范围可以很大,我这里把取值范围设置为5了。你其实也可以取更精确的gamma值。
1
2
3
4
5
6
7
8
9
10
<code><code><code><code><code><code><code>param_test3 = {
'gamma'
:[i/
10.0
for
i in range(
0
,
5
)]
}
gsearch3 = GridSearchCV(estimator = XGBClassifier( 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
),
param_grid = param_test3, scoring=
'roc_auc'
,n_jobs=
4
,iid=False, cv=
5
)
gsearch3.fit(train[predictors],train[target])
gsearch3.grid_scores_, gsearch3.best_params_, gsearch3.best_score_
</code></code></code></code></code></code></code>
从这里可以看出来,我们在第一步调参时设置的初始gamma值就是比较合适的。也就是说,理想的gamma值为0。在这个过程开始之前,最好重新调整boosting回合,因为参数都有变化。
从这里可以看出,得分提高了。所以,最终得到的参数是:1
2
3
4
5
6
7
8
9
10
11
12
13
14
<code><code><code><code><code><code><code><code>xgb2 = XGBClassifier(
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
)
modelfit(xgb2, train, predictors)
</code></code></code></code></code></code></code></code>
第四步:调整subsample 和 colsample_bytree 参数
下一步是尝试不同的subsample 和 colsample_bytree 参数。我们分两个阶段来进行这个步骤。这两个步骤都取0.6,0.7,0.8,0.9作为起始值。
1
2
3
4
5
6
7
8
9
10
11
<code><code><code><code><code><code><code><code><code>param_test4 = {
'subsample'
:[i/
10.0
for
i in range(
6
,
10
)],
'colsample_bytree'
:[i/
10.0
for
i in range(
6
,
10
)]
}
gsearch4 = GridSearchCV(estimator = XGBClassifier( 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
),
param_grid = param_test4, scoring=
'roc_auc'
,n_jobs=
4
,iid=False, cv=
5
)
gsearch4.fit(train[predictors],train[target])
gsearch4.grid_scores_, gsearch4.best_params_, gsearch4.best_score_
</code></code></code></code></code></code></code></code></code>
从这里可以看出来,subsample 和 colsample_bytree 参数的理想取值都是0.8。现在,我们以0.05为步长,在这个值附近尝试取值。
1
2
3
4
5
6
7
8
9
10
<code><code><code><code><code><code><code><code><code><code>param_test5 = {
'subsample'
:[i/
100.0
for
i in range(
75
,
90
,
5
)],
'colsample_bytree'
:[i/
100.0
for
i in range(
75
,
90
,
5
)]
}
gsearch5 = GridSearchCV(estimator = XGBClassifier( 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
),
param_grid = param_test5, scoring=
'roc_auc'
,n_jobs=
4
,iid=False, cv=
5
)
gsearch5.fit(train[predictors],train[target])
</code></code></code></code></code></code></code></code></code></code>
我们得到的理想取值还是原来的值。因此,最终的理想取值是:
subsample: 0.8 colsample_bytree: 0.8
第五步:正则化参数调优。
下一步是应用正则化来降低过拟合。由于gamma函数提供了一种更加有效地降低过拟合的方法,大部分人很少会用到这个参数。但是我们在这里也可以尝试用一下这个参数。我会在这里调整’reg_alpha’参数,然后’reg_lambda’参数留给你来完成。
1
2
3
4
5
6
7
8
9
10
<code><code><code><code><code><code><code><code><code><code><code>param_test6 = {
'reg_alpha'
:[1e-
5
, 1e-
2
,
0.1
,
1
,
100
]
}
gsearch6 = GridSearchCV(estimator = XGBClassifier( 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
),
param_grid = param_test6, scoring=
'roc_auc'
,n_jobs=
4
,iid=False, cv=
5
)
gsearch6.fit(train[predictors],train[target])
gsearch6.grid_scores_, gsearch6.best_params_, gsearch6.best_score_
</code></code></code></code></code></code></code></code></code></code></code>
我们可以看到,相比之前的结果,CV的得分甚至还降低了。但是我们之前使用的取值是十分粗糙的,我们在这里选取一个比较靠近理想值(0.01)的取值,来看看是否有更好的表现。
1
2
3
4
5
6
7
8
9
10
<code><code><code><code><code><code><code><code><code><code><code><code>param_test7 = {
'reg_alpha'
:[
0
,
0.001
,
0.005
,
0.01
,
0.05
]
}
gsearch7 = GridSearchCV(estimator = XGBClassifier( 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
),
param_grid = param_test7, scoring=
'roc_auc'
,n_jobs=
4
,iid=False, cv=
5
)
gsearch7.fit(train[predictors],train[target])
gsearch7.grid_scores_, gsearch7.best_params_, gsearch7.best_score_
</code></code></code></code></code></code></code></code></code></code></code></code>
可以看到,CV的得分提高了。现在,我们在模型中来使用正则化参数,来看看这个参数的影响。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<code><code><code><code><code><code><code><code><code><code><code><code><code>xgb3 = XGBClassifier(
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
)
modelfit(xgb3, train, predictors)
</code></code></code></code></code></code></code></code></code></code></code></code></code>
然后我们发现性能有了小幅度提高。
第6步:降低学习速率
最后,我们使用较低的学习速率,以及使用更多的决策树。我们可以用XGBoost中的CV函数来进行这一步工作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<code><code><code><code><code><code><code><code><code><code><code><code><code><code>xgb4 = XGBClassifier(
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
)
modelfit(xgb4, train, predictors)
</code></code></code></code></code></code></code></code></code></code></code></code></code></code>
至此,你可以看到模型的表现有了大幅提升,调整每个参数带来的影响也更加清楚了。
在文章的末尾,我想分享两个重要的思想:
1、仅仅靠参数的调整和模型的小幅优化,想要让模型的表现有个大幅度提升是不可能的。GBM的最高得分是0.8487,XGBoost的最高得分是0.8494。确实是有一定的提升,但是没有达到质的飞跃。
2、要想让模型的表现有一个质的飞跃,需要依靠其他的手段,诸如,特征工程(feature egineering) ,模型组合(ensemble of model),以及堆叠(stacking)等。结束语
这篇文章主要讲了如何提升XGBoost模型的表现。首先,我们介绍了相比于GBM,为何XGBoost可以取得这么好的表现。紧接着,我们介绍了每个参数的细节。我们定义了一个可以重复使用的构造模型的函数。
最后,我们讨论了使用XGBoost解决问题的一般方法,在AV Data Hackathon 3.x problem数据上实践了这些方法。
希望看过这篇文章之后,你能有所收获,下次使用XGBoost解决问题的时候可以更有信心哦~ -
xgboost调参大法
2018-03-19 00:59:09了解偏差-方差权衡(Bias-Variance Tradeoff)在机器学习df或统计课程中,偏差方差权衡可能...xgboost中的大多数参数是关于偏差方差权衡的。最好的模型应该在模型的复杂性及模型的预测能力上做细致的权衡(注:模型的复... -
xgboost调参函数(GridSearchCV的使用)
2020-02-23 17:29:55xgboost调参函数(GridSearchCV的使用) 转并整理自[xgboost调参](https://segmentfault.com/a/1190000014040317),非常实用 1.简介 调参用的是sklearn的GridSearchCV,其中,x_train和y_train分别指的训练集的特征和... -
XGBoost调参笔记
2018-11-02 12:30:05将之前XGBoost的笔记整理在CSDN上。 一、通用参数 一、这些参数用来控制XGBoost的宏观功能。 1、booster[默认gbtree] 选择每次迭代的模型,有两种选择: gbtree:基于树的模型 gbliner:线性模型 2、silent[默认... -
xgboost调参指南与实战
2019-11-12 16:01:461.XGboost的参数 1)通用参数:宏观函数控制; 2)Booster参数:控制每一步的booster(tree/regression); 3)学习目标参数:控制训练目标的表现。 1.1 通用参数 booster: default gbtree 选择每次迭代的模型,... -
机器学习实战项目Xgboost调参
2018-03-21 21:09:38机器学习实战项目Xgboost调参,完整的项目,机器学习实战项目Xgboost调参 -
Xgboost调参技巧
2018-08-29 21:43:37调参示例 4. XGBoost的优势 XGBoost算法可以给预测模型带来能力的提升。当我对它的表现有更多了解的时候,当我对它的高准确率背后的原理有更多了解的时候,我发现它具有很多优势: 4.1 正则化 标准GBM... -
XGboost调参指南
2020-12-24 18:02:28第二步: max_depth 和 min_weight 对最终结果有很大的影响 ‘max_depth’:range(3,10,2), ‘min_child_weight’:range(1,6,2) 先大范围地粗调参数,然后再小范围地微调。 第三步:gamma参数调优 ‘gamma’:[i/10.0... -
xgboost 调参经验
2017-12-01 16:03:101.xgboost 基本方法和默认参数 在训练过程中主要用到两个方法:xgboost.train()和xgboost.cv(). #xgboost.train()API xgboost.train(params,dtrain,num_boost_round=10,evals=(),obj=None,feval=None,... -
XGBoost调参指南
2018-03-09 12:47:18XGBoost调参指南 参考-官网 方法1 可按照max_depth, min_child_weight colsamplt_bytree,eta的顺序一个一个调,每次调的时候其他参数保持不变 方法2:防止过拟合 When you observe high training accuracy, ... -
模型融合---Xgboost调参总结
2020-12-24 18:03:23一、xgboost简介:全称:eXtreme Gradient Boosting作者:陈天奇...缺点:算法参数过多,调参负责,对原理不清楚的很难使用好XGBoost。不适合处理超高维特征数据。二、参数速查参数分为三类:通用参数:宏观函... -
Xgboost调参--针对过拟合和非平衡数据
2019-08-14 10:55:31调参须知: 在机器学习中,调参是一项dark art(可以理解为一项优美而道不明的事情)。一个模型的最优参数取决于很多因素。因此不可能建立一个完备的调参说明书去获取最优参数。 理解 Bias-Variance tradeoff (先说... -
xgboost调参经验
2019-10-11 22:28:54本文为kaggle上一位选手分享的xgboost调参经验的翻译。方便对xgboost模型参数的快速调试。 原文:... -
Python机器学习(六)-XGBoost调参
2019-04-05 13:36:31XGBoost 及调参简介 XGBoost(eXtreme Gradient Boosting)是Gradient Boosting算法的一个优化的版本,是大牛陈天奇的杰作(向上海交通大学校友顶礼膜拜)。Anaconda中不带这个模块,需要自行下载安装。搭建一个... -
XGBoost调参顺序---配合培训内容,陆续更新中
2021-11-06 19:55:41附代码:XGBoost参数调优完全指南 - 布尔先生 - 博客园 XGBoost的作者把所有的参数分成了三类: 1、通用参数:宏观函数控制。 2、Booster参数:控制每一步的booster(tree/regression)。 3、学习目标参数:控制训练... -
Xgboost调参策略
2019-05-08 20:55:06Xgboost参数 - 'booster':'gbtree',梯度提升决策树 - 'objective': 'multi:softmax', 多分类的问题 - 'num_class':10, 类别数,与 multisoftmax 并用 - 'gamma':损失下降多少才进行分裂,这个需要调一下,越大越... -
XGBOOST调参
2020-02-23 22:28:11通过step2调整树的深度和节点权重,这些参数对XGBoost性能影响最大,我们简要概述他们:max_depth:树的最大深度。增加这个值会使模型更加复杂,也容易出现过拟合,深度3-10是合理的;min_child_weight:正则化参数...