xgboost 调参
文章来自于:https://blog.csdn.net/zllnau66/article/details/81980876
1. 简介
如果你的预测模型表现得有些不尽如人意,那就用XGBoost吧。XGBoost算法现在已经成为很多数据工程师的重要武器。它是一种十分精致的算法,可以处理各种不规则的数据。
构造一个使用XGBoost的模型十分简单。但是,提高这个模型的表现就有些困难(至少我觉得十分纠结)。这个算法使用了好几个参数。所以为了提高模型的表现,参数的调整十分必要。在解决实际问题的时候,有些问题是很难回答的——你需要调整哪些参数?这些参数要调到什么值,才能达到理想的输出?
这篇文章最适合刚刚接触XGBoost的人阅读。在这篇文章中,我们会学到参数调优的技巧,以及XGboost相关的一些有用的知识。以及,我们会用Python在一个数据集上实践一下这个算法。
2. 你需要知道的
XGBoost(eXtreme Gradient Boosting)是Gradient Boosting算法的一个优化的版本。因为我在前一篇文章,基于Python的Gradient Boosting算法参数调整完全指南,里面已经涵盖了Gradient Boosting算法的很多细节了。我强烈建议大家在读本篇文章之前,把那篇文章好好读一遍。它会帮助你对Boosting算法有一个宏观的理解,同时也会对GBM的参数调整有更好的体会。
特别鸣谢:我个人十分感谢Mr Sudalai Rajkumar (aka SRK)大神的支持,目前他在AV Rank中位列第二。如果没有他的帮助,就没有这篇文章。在他的帮助下,我们才能给无数的数据科学家指点迷津。给他一个大大的赞!
3. 内容列表
1、XGBoost的优势
2、理解XGBoost的参数
3、调参示例
4. XGBoost的优势
XGBoost算法可以给预测模型带来能力的提升。当我对它的表现有更多了解的时候,当我对它的高准确率背后的原理有更多了解的时候,我发现它具有很多优势:
4.1 正则化
- 标准GBM的实现没有像XGBoost这样的正则化步骤。正则化对减少过拟合也是有帮助的。
- 实际上,XGBoost以“正则化提升(regularized boosting)”技术而闻名。
4.2 并行处理
- XGBoost可以实现并行处理,相比GBM有了速度的飞跃。
- 不过,众所周知,Boosting算法是顺序处理的,它怎么可能并行呢?每一课树的构造都依赖于前一棵树,那具体是什么让我们能用多核处理器去构造一个树呢?我希望你理解了这句话的意思。如果你希望了解更多,点击这个链接。
- XGBoost 也支持Hadoop实现。
4.3 高度的灵活性
- XGBoost 允许用户定义自定义优化目标和评价标准
- 它对模型增加了一个全新的维度,所以我们的处理不会受到任何限制。
4.4 缺失值处理
- XGBoost内置处理缺失值的规则。
- 用户需要提供一个和其它样本不同的值,然后把它作为一个参数传进去,以此来作为缺失值的取值。XGBoost在不同节点遇到缺失值时采用不同的处理方法,并且会学习未来遇到缺失值时的处理方法。
4.5 剪枝
- 当分裂时遇到一个负损失时,GBM会停止分裂。因此GBM实际上是一个贪心算法。
- XGBoost会一直分裂到指定的最大深度(max_depth),然后回过头来剪枝。如果某个节点之后不再有正值,它会去除这个分裂。
- 这种做法的优点,当一个负损失(如-2)后面有个正损失(如+10)的时候,就显现出来了。GBM会在-2处停下来,因为它遇到了一个负值。但是XGBoost会继续分裂,然后发现这两个分裂综合起来会得到+8,因此会保留这两个分裂。
4.6 内置交叉验证
- XGBoost允许在每一轮boosting迭代中使用交叉验证。因此,可以方便地获得最优boosting迭代次数。
- 而GBM使用网格搜索,只能检测有限个值。
4.7、在已有的模型基础上继续
- XGBoost可以在上一轮的结果上继续训练。这个特性在某些特定的应用上是一个巨大的优势。
- sklearn中的GBM的实现也有这个功能,两种算法在这一点上是一致的。
- 二、网格调参
五、网格调参
用xgboost既可以用来做二分类、多分类,也可以用来做回归预测数值,除了特征之外,影响模型的是如何调参了,一般是按一定的步骤、网格搜索最优参数,如下两篇文章一个是用来分类,一个是用来预测 数值的案例,并且详细给出了调参的步骤和代码:
https://blog.csdn.net/han_xiaoyang/article/details/52665396 (用来分类XGBClassifier)
https://segmentfault.com/a/1190000014040317 (用来预测数字,XGBRegressor)
六、实践
参考以上的博客,用iris经典数据集进行多分类的预测(三个类别):
import pandas as pd import numpy as np import xgboost as xgb from xgboost.sklearn import XGBClassifier from sklearn import model_selection, metrics from sklearn.grid_search import GridSearchCV #Perforing grid search import matplotlib.pylab as plt %matplotlib inline import warnings warnings.filterwarnings(module='sklearn*', action='ignore', category=DeprecationWarning)
from sklearn import datasets data=iris.data label=iris.target
from sklearn.cross_validation import train_test_split train_x, test_x, train_y, test_y = train_test_split(data, label,test_size=0.3, random_state=0) dtrain=xgb.DMatrix(train_x,label=train_y) dtest=xgb.DMatrix(test_x,label=test_y)
cv_params = {'n_estimators': [1,2,3,4,5,6]} 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} model = xgb.XGBClassifier(**other_params) optimized_GBM = GridSearchCV(estimator=model, param_grid=cv_params, scoring='accuracy', cv=5, verbose=1, n_jobs=4) optimized_GBM.fit(train_x, train_y) evalute_result = optimized_GBM.grid_scores_ #print('每轮迭代运行结果:{0}'.format(evalute_result)) print('参数的最佳取值:{0}'.format(optimized_GBM.best_params_)) print('最佳模型得分:{0}'.format(optimized_GBM.best_score_))
Fitting 5 folds for each of 6 candidates, totalling 30 fits 参数的最佳取值:{'n_estimators': 4} 最佳模型得分:0.9619047619047619 [Parallel(n_jobs=4)]: Done 30 out of 30 | elapsed: 8.9s finished
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': 4, 'max_depth': 5, 'min_child_weight': 1, 'seed': 0, 'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0, 'reg_lambda': 1} model = xgb.XGBClassifier(**other_params) optimized_GBM = GridSearchCV(estimator=model, param_grid=cv_params, scoring='accuracy', cv=5, verbose=1, n_jobs=4) optimized_GBM.fit(train_x, train_y) evalute_result = optimized_GBM.grid_scores_ #print('每轮迭代运行结果:{0}'.format(evalute_result)) print('参数的最佳取值:{0}'.format(optimized_GBM.best_params_)) print('最佳模型得分:{0}'.format(optimized_GBM.best_score_))
Fitting 5 folds for each of 48 candidates, totalling 240 fits 参数的最佳取值:{'max_depth': 4, 'min_child_weight': 1} 最佳模型得分:0.9619047619047619 [Parallel(n_jobs=4)]: Done 240 out of 240 | elapsed: 8.7s finished
cv_params = {'gamma': [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]} other_params = {'learning_rate': 0.1, 'n_estimators': 4, 'max_depth': 4, 'min_child_weight': 1, 'seed': 0, 'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0, 'reg_lambda': 1} model = xgb.XGBClassifier(**other_params) optimized_GBM = GridSearchCV(estimator=model, param_grid=cv_params, scoring='accuracy', cv=5, verbose=1, n_jobs=4) optimized_GBM.fit(train_x, train_y) evalute_result = optimized_GBM.grid_scores_ #print('每轮迭代运行结果:{0}'.format(evalute_result)) print('参数的最佳取值:{0}'.format(optimized_GBM.best_params_)) print('最佳模型得分:{0}'.format(optimized_GBM.best_score_))
Fitting 5 folds for each of 6 candidates, totalling 30 fits 参数的最佳取值:{'gamma': 0.1} 最佳模型得分:0.9619047619047619 [Parallel(n_jobs=4)]: Done 30 out of 30 | elapsed: 8.6s finished
cv_params = {'subsample': [0.6, 0.7, 0.8, 0.9], 'colsample_bytree': [0.6, 0.7, 0.8, 0.9]} other_params = {'learning_rate': 0.1, 'n_estimators':4, 'max_depth': 4, 'min_child_weight':1, 'seed': 0, 'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0.1, 'reg_alpha': 0, 'reg_lambda': 1} model = xgb.XGBClassifier(**other_params) optimized_GBM = GridSearchCV(estimator=model, param_grid=cv_params, scoring='accuracy', cv=5, verbose=1, n_jobs=4) optimized_GBM.fit(train_x, train_y) evalute_result = optimized_GBM.grid_scores_ #print('每轮迭代运行结果:{0}'.format(evalute_result)) print('参数的最佳取值:{0}'.format(optimized_GBM.best_params_)) print('最佳模型得分:{0}'.format(optimized_GBM.best_score_))
Fitting 5 folds for each of 16 candidates, totalling 80 fits 参数的最佳取值:{'colsample_bytree': 0.8, 'subsample': 0.8} 最佳模型得分:0.9619047619047619 [Parallel(n_jobs=4)]: Done 80 out of 80 | elapsed: 9.5s finished
cv_params = {'reg_alpha': [0.05, 0.1, 1, 2, 3], 'reg_lambda': [0.05, 0.1, 1, 2, 3]} other_params = {'learning_rate': 0.1, 'n_estimators': 4, 'max_depth': 4, 'min_child_weight': 1, 'seed': 0, 'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0.1, 'reg_alpha': 0, 'reg_lambda': 1} model = xgb.XGBClassifier(**other_params) optimized_GBM = GridSearchCV(estimator=model, param_grid=cv_params, scoring='accuracy', cv=5, verbose=1, n_jobs=4) optimized_GBM.fit(train_x, train_y) evalute_result = optimized_GBM.grid_scores_ #print('每轮迭代运行结果:{0}'.format(evalute_result)) print('参数的最佳取值:{0}'.format(optimized_GBM.best_params_)) print('最佳模型得分:{0}'.format(optimized_GBM.best_score_))
Fitting 5 folds for each of 25 candidates, totalling 125 fits 参数的最佳取值:{'reg_alpha': 0.05, 'reg_lambda': 0.05} 最佳模型得分:0.9619047619047619 [Parallel(n_jobs=4)]: Done 125 out of 125 | elapsed: 8.6s finished
cv_params = {'learning_rate': [0.01, 0.05, 0.07, 0.1, 0.2]} other_params = {'learning_rate': 0.1, 'n_estimators': 4, 'max_depth': 4, 'min_child_weight': 1, 'seed': 0, 'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0.1, 'reg_alpha': 0.05, 'reg_lambda': 0.05} model = xgb.XGBClassifier(**other_params) optimized_GBM = GridSearchCV(estimator=model, param_grid=cv_params, scoring='accuracy', cv=5, verbose=1, n_jobs=4) optimized_GBM.fit(train_x, train_y) evalute_result = optimized_GBM.grid_scores_ #print('每轮迭代运行结果:{0}'.format(evalute_result)) print('参数的最佳取值:{0}'.format(optimized_GBM.best_params_)) print('最佳模型得分:{0}'.format(optimized_GBM.best_score_))
Fitting 5 folds for each of 5 candidates, totalling 25 fits 参数的最佳取值:{'learning_rate': 0.1} 最佳模型得分:0.9619047619047619 [Parallel(n_jobs=4)]: Done 25 out of 25 | elapsed: 8.7s finished
params={ 'booster':'gbtree', 'objective': 'multi:softmax', #指明是分类问题 # 'eval_metric': 'auc', 'num_class':3, # 类数,与 multisoftmax 并用 'gamma':0.1, # 用于控制是否后剪枝的参数,越大越保守,一般0.1、0.2这样子。 'max_depth':4, # 构建树的深度,越大越容易过拟合 'lambda':0.05, #控制模型复杂度的权重值的L2正则化项参数,参数越大,模型越不容易过拟合。 'subsample':0.8, # 采样训练数据,设置为0.5,随机选择一般的数据实例 (0:1] 'colsample_bytree':0.8, # 构建树树时的采样比率 (0:1] 'min_child_weight':1, # 节点的最少特征数 'silent':1 ,# 设置成1则没有运行信息输出,最好是设置为0. 'eta': 0.1, # 如同学习率 'seed':710, 'alpha':0.05, 'nthread':4,# cpu 线程数,根据自己U的个数适当调整 } plst = list(params.items()) num_rounds=100 watchlist = [(dtrain,'train'),(dtest,'eval')] model=xgb.train(plst,dtrain,num_rounds,evals=watchlist)
[0] train-merror:0.038095 eval-merror:0.088889 [1] train-merror:0.019048 eval-merror:0.022222 [2] train-merror:0.028571 eval-merror:0.022222 [3] train-merror:0.019048 eval-merror:0.022222 [4] train-merror:0.019048 eval-merror:0.022222 [5] train-merror:0.019048 eval-merror:0.022222 [6] train-merror:0.019048 eval-merror:0.022222 [7] train-merror:0.019048 eval-merror:0.022222 [8] train-merror:0.019048 eval-merror:0.022222 [9] train-merror:0.019048 eval-merror:0.022222 [10] train-merror:0.019048 eval-merror:0.022222 [11] train-merror:0.019048 eval-merror:0.022222 [12] train-merror:0.019048 eval-merror:0.022222 [13] train-merror:0.019048 eval-merror:0.022222 [14] train-merror:0.019048 eval-merror:0.022222 [15] train-merror:0.019048 eval-merror:0.022222 [16] train-merror:0.019048 eval-merror:0.022222 [17] train-merror:0.019048 eval-merror:0.022222 [18] train-merror:0.019048 eval-merror:0.022222 [19] train-merror:0.009524 eval-merror:0.022222 [20] train-merror:0.019048 eval-merror:0.022222 [21] train-merror:0.009524 eval-merror:0.022222 [22] train-merror:0.009524 eval-merror:0.022222 [23] train-merror:0 eval-merror:0.022222 [24] train-merror:0 eval-merror:0.022222 [25] train-merror:0 eval-merror:0.022222 [26] train-merror:0.009524 eval-merror:0.022222 [27] train-merror:0 eval-merror:0.022222 [28] train-merror:0.009524 eval-merror:0.022222 [29] train-merror:0 eval-merror:0.022222 [30] train-merror:0 eval-merror:0.022222 [31] train-merror:0 eval-merror:0.022222 [32] train-merror:0 eval-merror:0.022222 [33] train-merror:0 eval-merror:0.022222 [34] train-merror:0 eval-merror:0.022222 [35] train-merror:0 eval-merror:0.022222 [36] train-merror:0 eval-merror:0.022222 [37] train-merror:0 eval-merror:0.022222 [38] train-merror:0 eval-merror:0.022222 [39] train-merror:0 eval-merror:0.022222 [40] train-merror:0 eval-merror:0.022222 [41] train-merror:0 eval-merror:0.022222 [42] train-merror:0 eval-merror:0.022222 [43] train-merror:0 eval-merror:0.022222 [44] train-merror:0 eval-merror:0.022222 [45] train-merror:0 eval-merror:0.022222 [46] train-merror:0 eval-merror:0.022222 [47] train-merror:0 eval-merror:0.022222 [48] train-merror:0 eval-merror:0.022222 [49] train-merror:0 eval-merror:0.022222 [50] train-merror:0 eval-merror:0.022222 [51] train-merror:0 eval-merror:0.022222 [52] train-merror:0 eval-merror:0.022222 [53] train-merror:0 eval-merror:0.022222 [54] train-merror:0 eval-merror:0.022222 [55] train-merror:0 eval-merror:0.022222 [56] train-merror:0 eval-merror:0.022222 [57] train-merror:0 eval-merror:0.022222 [58] train-merror:0 eval-merror:0.022222 [59] train-merror:0 eval-merror:0.022222 [60] train-merror:0 eval-merror:0.022222 [61] train-merror:0 eval-merror:0.022222 [62] train-merror:0 eval-merror:0.022222 [63] train-merror:0 eval-merror:0.022222 [64] train-merror:0 eval-merror:0.022222 [65] train-merror:0 eval-merror:0.022222 [66] train-merror:0 eval-merror:0.022222 [67] train-merror:0 eval-merror:0.022222 [68] train-merror:0 eval-merror:0.022222 [69] train-merror:0 eval-merror:0.022222 [70] train-merror:0 eval-merror:0.022222 [71] train-merror:0 eval-merror:0.022222 [72] train-merror:0 eval-merror:0.022222 [73] train-merror:0 eval-merror:0.022222 [74] train-merror:0 eval-merror:0.022222 [75] train-merror:0 eval-merror:0.022222 [76] train-merror:0 eval-merror:0.022222 [77] train-merror:0 eval-merror:0.022222 [78] train-merror:0 eval-merror:0.022222 [79] train-merror:0 eval-merror:0.022222 [80] train-merror:0 eval-merror:0.022222 [81] train-merror:0 eval-merror:0.022222 [82] train-merror:0 eval-merror:0.022222 [83] train-merror:0 eval-merror:0.022222 [84] train-merror:0 eval-merror:0.022222 [85] train-merror:0 eval-merror:0.022222 [86] train-merror:0 eval-merror:0.022222 [87] train-merror:0 eval-merror:0.022222 [88] train-merror:0 eval-merror:0.022222 [89] train-merror:0 eval-merror:0.022222 [90] train-merror:0 eval-merror:0.022222 [91] train-merror:0 eval-merror:0.022222 [92] train-merror:0 eval-merror:0.022222 [93] train-merror:0 eval-merror:0.022222 [94] train-merror:0 eval-merror:0.022222 [95] train-merror:0 eval-merror:0.022222 [96] train-merror:0 eval-merror:0.022222 [97] train-merror:0 eval-merror:0.022222 [98] train-merror:0 eval-merror:0.022222 [99] train-merror:0 eval-merror:0.022222
以上是通过网格参数取得了最佳参数后,代入xgb.train()得出的结果,和用XGBClassifier其实是一样的,只不过两者的参数命名略有不同:
xgb1 = XGBClassifier( learning_rate=0.1, n_estimators=4, max_depth=4, min_child_weight=1, seed=0, subsample=0.8, colsample_bytree=0.8, gamma=0.1, reg_alpha=0.05, reg_lambda=0.05) xgb1.fit(train_x,train_y) ypred1=xgb1.predict(test_x) print(metrics.accuracy_score(test_y, ypred1))