算法小白菜和大叔走大数据应用之路个人收藏

xgboost原理及调参方法-通俗易懂版本

2019-06-01  本文已影响153人  不分享的知识毫无意义

  xgboost是各种比赛中最常使用的方法,网上介绍非常多,但是大部分看起来都比较费劲,这篇文章我将通俗的讲一下xgboost是在干什么,是怎么实现的,每一步的细节中要注意什么问题,达到理解—应用的程度,想了解具体理论的各位看官请移步其他文章。

1.xgboost原理

  说起xgboost,我们不得不提一下GBDT,也就是梯度提升决策树,这是一种基于树的集成算法,至于什么方法构成了GBDT的决策树,无非就是ID3、C4.5、C5.0、CART,最常用的就是那个CART,多棵树的集合就构成了GBDT。其实GBDT是对残差的拟合,什么意思呢?假设目标函数是9,第一棵树预测为5,剩下4的误差,那么下一颗树继续拟合4,直至误差满足我们的要求,这和xgboost的思路是一样的。那么问题来了,有了GBDT为啥还要用xgboost呢,有一种说法是,GBDT的每一步优化都依赖于上一步的误差,当大数据量的时候就太慢了,xgboost通过改变目标函数来避免了这个问题。
  GBDT的目标函数是预测值和真实值差的累加,也就是误差累加,可以看出每一步计算都依赖于上面所有步的误差,效率比较低。xgboost自然要做出改进,怎么优化呢,一步步分解来看。

2.python导入相关包

  python简直太友好了,可以直接调用xgboost包跑程序,我们要做的就是提取指标和调参,提取指标这个事我教不了你,得根据业务来,调参倒是有套路可寻。首先你要实现一个xgboost,你要知道你用什么工具去实现,python里有两个包,一个就叫xgboost,另外一个是xgboost的sklearn接口,叫XGBClassifer。另外要调参还有一个并行的网格搜索包,sklearn里的GridSearchCV。其他还有一些包需要引入就是打打辅助。

import pandas as pd
import numpy as np
import xgboost as xgb
from xgboost.sklearn import XGBClassifier
from sklearn import cross_validation, metrics   #交叉验证和效果评估,其他模型也很常用。
from sklearn.grid_search import GridSearchCV   #并行搜索,加快速度。

3.xgboost调参

  准备工作已经做好了,接下来开始调参工作了,调参之前大家记得要做两件件事,就是先把数据整理好,把模型搭建好。

3.1 搭建模型

  简单的很,已经引入了XGBClassifier,直接把相关默认参数设置好就可以了。

clf1 = 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)

3.2 参数解释

我们看到在建立xgboost的模型时,有很多参数,这些参数是什么意思呢,我们来看一下。

  知道了这些参数,想要弄明白调参是干啥,调整什么就很容易了,下面会结合例子来说明。

3.3 调参方法

  先来推荐一个大哥的博客,这个链接里https://blog.csdn.net/u014465639/article/details/74351982写了好几种模型的调参方法,想要了解的不妨去看看。
  开始之前,给大家介绍一个新朋友,这个东西可以很好的帮助我们进行调参,它是sklearn里的一个包,[sklearn.model_selection.GridSearchCV],我们调参就是基于这个包的。那么这个包怎么实现调参呢,来看一眼它的常用参数。
(1)estimator:优化器,也就是你建立的模型,这里自然就是xgboost模型,如果要对其他集成算法调优,那就写其他模型了,注意模型需要初始化哦。
(2)param_grid:字典或者列表,一般用字典,请在这里输入你要优化的参数值。
(3)scoring :用啥子估计误差,如果不设置,那我没办法了,就用estimator的误差来衡量吧。
  有了上面的方法,我们还会怕调参数吗,当然不会了,先设置好常用的参数,然后再依次调参。请注意,调参是有顺序的,按照下面这个来。

cv_params = {'n_estimators': [400, 500, 600, 700, 800]}
other_params = {'learning_rate': 0.1, 'n_estimators': 500, 'max_depth': 5, 'min_child_weight': 1, 'seed': 0,
                    'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0, 'reg_lambda': 1}

  咦,这里边有n_estimators的值了,其实就是以他为基准进行挑选啊,首先给个基础值进去,给谁啊,当然是建立的初始模型了。

model = xgb.XGBRegressor(**other_params)

  然后跑一下模型,这个我最后统一说,反正最后给出一个最优值,但是我们设置的粒度太粗了,不能直接用,接下来细调,同样方法跑一遍。

cv_params = {'n_estimators': [550, 575, 600, 650, 675]}
cv_params = {'max_depth': [3, 4, 5, 6, 7, 8, 9, 10], 'min_child_weight': [1, 2, 3, 4, 5, 6]}
other_params = {'learning_rate': 0.1, 'n_estimators': 550, 'max_depth': 5, 'min_child_weight': 1,
 'seed': 0,'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0, 'reg_lambda': 1}

cv_params = {'gamma': [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]}
cv_params = {'subsample': [0.6, 0.7, 0.8, 0.9], 'colsample_bytree': [0.6, 0.7, 0.8, 0.9]}
cv_params = {'reg_alpha': [0.05, 0.1, 1, 2, 3], 'reg_lambda': [0.05, 0.1, 1, 2, 3]}
cv_params = {'learning_rate': [0.01, 0.05, 0.07, 0.1, 0.2]}

  基本调参就告一段落了,这里需要特别指出一点就是调参可以提高模型性能,但是更重要的还是特征选择,数据清洗,特征融合等工作,大家注意把基础工作做好。

4.完整代码

  基础数据啥的我就不列了啊,大概说一下概要吧,和网上的不一样,我也是按照自己的想法做了一些省略。

#1.建立一个初步的模型,看一下效果怎么样。
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)#经验值
xgb_param = xgb1.get_xgb_params()#得到模型的参数 
xgtrain = xgb.DMatrix(dtrain[predictors].values, label=dtrain[target].values)#转换成原生xgboost需要的数据格式。
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)#注意啊这是原生的模型自带的,你只需传参,cv_folds=5,表示5%的数据用于交叉验证。这个cvresults返回训练集和测试集的误差,行数就是最大迭代的次数。
xgb1.set_params(n_estimators=cvresult.shape[0])
xgb1.fit(dtrain[predictors], dtrain['Disbursed'],eval_metric='auc')
dtrain_predictions = alg.predict(dtrain[predictors])#算准确率用的
dtrain_predprob = alg.predict_proba(dtrain[predictors])[:,1]#算auc用的
feat_imp = pd.Series(alg.booster().get_fscore()).sort_values(ascending=False)#算重要度的指标
#‘weight’ - the number of times a feature is used to split the data across all trees.‘gain’ - the average gain of the feature when it is used in trees.‘cover’ - the average coverage of the feature when it is used in trees.
#weight - 该特征在所有树中被用作分割样本的特征的次数。gain - 在所有树中的平均增益。cover - 在树中使用该特征时的平均覆盖范围。
#
#2开始按步骤调参用的XGBclassifer。
#第一步调优
params_test1 = {'n_estimators': [400, 500, 600, 700, 800]}
other_params = {'learning_rate': 0.1, 'n_estimators': 500, 'max_depth': 5, 'min_child_weight': 1, 'seed': 27,
                    'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0, 'reg_lambda': 1}
model = XGBClassfoer(**other_params)
optimized_XGB 1= GridSearchCV(estimator=model, param_grid=cv_params, scoring='r2', cv=5, verbose=1, n_jobs=4)
optimized_XGB.fit(X_train, y_train)
evalute_result = optimized_GBM.grid_scores_
##第二步调优
param_test2 = { 'max_depth':range(3,10,2), 'min_child_weight':range(1,6,2)}
optimized_XGB2= 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_test2,     scoring='roc_auc',n_jobs=4,iid=False, cv=5)
optimized_XGB2.fit(train[predictors],train[target])
optimized_XGB2.grid_scores_, optimized_XGB2.best_params_,     optimized_XGB2.best_score_
#依次类推,得到最后的最优参数集合,再建立模型用于预测
#3.最终模型
model = XGBClassifer(learning_rate=0.1, n_estimators=550, max_depth=4, min_child_weight=5, seed=27,
                             subsample=0.7, colsample_bytree=0.7, gamma=0.1, reg_alpha=1, reg_lambda=1)
model.fit(X_train, y_train)
ans = model.predict(X_test)
  以上就是本篇的所有内容,很多东西就是讲思路,让大家都知道怎么回事,准确性可能差点,如果你想有更深的理解,还是结合其他人的文章看看。
上一篇 下一篇

猜你喜欢

热点阅读