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

猜你喜欢

转载自www.cnblogs.com/liuyicai/p/10657111.html
今日推荐