CSDN:http://blog.csdn.net/kicilove/article/
Github:https://github.com/zhaohuicici?tab=repositories
原文链接:https://www.analyticsvidhya.com/blog/2016/03/complete-guide-parameter-tuning-xgboost-with-codes-python/
如果其他的预测模型无法满足你的预测需求时,请使用XGboost。 XGBoost算法已经成为许多数据科学家的终极武器。 这是一个足够强大的可以应对各种不寻常数据的高大上的算法。
使用XGBoost构建模型很容易。 但是,使用XGBoost改进模型很困难(至少于我来说还是很挣扎的)。 这个算法使用了很多个参数。 要想对模型进行改进,就必须对参数做出调整。 很多实际的问题,比如说你应该调整哪一个参数集合?要得到最优的输出结果参数的理想值是多少?,这些实际问题都是很难得到答案的。
本文适合与刚接触XGBoost的新人。 在本文中,我们将学习参数调优的技术以及有关XGBoost的一些有用信息。 此外,我们将使用Python中的数据集练习该算法。
* XGBoost(eXtreme Gradient Boosting)*是梯度增强算法(GBM)的高级实现。 由于我在之前的文章 Complete Guide to Parameter Tuning in Gradient Boosting (GBM) in Python中详细介绍了Gradient Boosting Machine,所以强烈建议您先阅读本文。 这将有助于您加强对GBM的一般升级和参数调优的理解。
特别感谢:就个人而言,我要感谢Sudalai Rajkumar先生(又名SRK)提供的永久支持,目前是AV Rank 2。如果没有他的帮助,这篇文章是不可能的诞生的啦。 他正帮助着成千上万的数据科学家。 非常感谢SRK!
我一直钦佩在一个预测型的模型中这种算法注入了提升(boosting)的能力。 当我探索它的表现性能以及高准确性背后的科学道路时,发现了它身上有诸多的优点:
我希望现在你明白了XGBoost的绝对优势。 请注意,这些只是XGBoost的部分要点。 还待你发现更多?
您可以参考以下网页以获得更深入的了解:
XGBoost的作者把参数整体分为3类:
强烈建议阅读这篇与GBM对比的文章。
下面介绍这些参数
下面这些参数指导XGBoost的整体过程。
还有另外两个参数是由XGBoost自动设置的,下面继续探索Booster参数。
虽然有两种类型的Booster,这里只讨论树式Booster。
gamma [default=0]
max_delta_step [default=0]
这些参数用于定义优化的目标,在一步计算的度量。
如果使用Scikit-Learn,这些参数名称可能不太熟悉。 可喜的是,python中的xgboost模块有一个名为XGBClassifier的sklearn封装。 有些参数名称变化如下:
好像我们已经定义了在XGBoost与GBM中相似的所有参数,除了GBM中的 ‘n_estimators’ 参数。 其实它出现在XGBClassifier的参数中,在标准xgboost中拟合函数的时候,以 “num_boosting_rounds ”的形式传递。
建议您通过xgboost指南更好地了解参数和代码:
我们将从Data Hackathon 3.x AV hackathon中获取数据集,与GBM文章中的数据集相同。 细节可以在此页面找到。 您可以从这里下载数据集。 执行步骤如下:
开始,导入所需的库并加载数据:
#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'
请注意,我已经导入了2种形式的XGBoost:
先定义一个函数,帮助我们创建XGBoost模型并执行交叉验证。这个也可以用在你自己的模型中。
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')
这个代码与用于GBM的代码略有不同。 本文的重点是涵盖概念而不是编码。 注意,xgboost的sklearn封装没有“feature_importances”指标,它使用get_fscore()函数做相同的事情。
我们将使用类似于GBM的方法。 几个步骤如下:
让我们来看一个更详细的一步一步的实现方法。
为了确定boosting参数,我们需要设置其他参数的初始值。 让我们取下列值:
请注意,以上只是设定初始值,后面会进行参数调优。 这里默认学习率为0.1,使用xgboost的cv函数检查最优树的颗数,上面定义的函数可以实现这个功能。
#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)
正如你所看到的,在学习率为0.1的情况下,得到140为最优的估计量个数。 请注意,根据你运行系统的情况,此值可能太高。 在这种情况下,您可以增加学习率并重新运行命令以获得减少的估计量数。
注意:这里输出结果中testAUC可视为′AUCScore(Test)′。但是,如果您尝试在系统上运行命令,因为数据未公开,则不会出现此错误。它在这里提供仅供参考。生成此输出的代码部分已在此处删除。
首先调整对模型输出结果影响最大的参数。 首先,我们先设置较宽的范围,然后再用较小范围执行另一次迭代。
重要提示:我将在本节中进行运行压力较大的网格搜索,根据您的系统,可能需要15-30分钟甚至更多时间才能运行。 您可以根据系统来更改您要测试的值。
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_
这里,我们已经运行12个组合。 max_depth的理想值为5,min_child_weight的理想值为5。 让我们深入一步,寻找最佳值。 我们将搜索间隔为1上下的最佳值,因为之前间隔都是2。
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_
这一次,我们得到最佳值为4为max_depth和为6的min_child_weight。 此外,我们可以看到CV得分增加较轻。 请注意,随着模型性能的提高,要想在哪怕是边缘性能的提升都是指数级的困难。 你会注意到,这里我们得到6作为min_child_weight的最优值,但是我们还没有尝试超过6的值。我们可以这样做:
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_
我们看到6还是最佳值。
现在可以使用上面已调整的参数来调整gamma值。 Gamma这里尝试5个值。 也可以使用更精确的数值。
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_
这表明我们的原始伽玛值,即0是最佳值。 在继续之前,一个好想法是重新校准更新参数的 boosting rounds 。
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)
在这里,我们可以看到得分有所改善。 所以最终的参数是:
下一步将尝试不同的subsample和colsample_bytree值。 让我们分两个阶段完成,取0.6,0.7,0.8,0.9为他们的初始值。
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=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_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_
这里,我们发现0.8为subsample和colsample_bytree的最优值。 现在我们应该尝试在0.05间隔周围的值。
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])
这一次得到的最优值和上面相同,因此最优值为:
下一步是应用正则化来减少过度拟合。 尽管许多人不太使用这些参数,因为gamma提供了一种控制复杂性的实质方法。 但我们应该尝试使用它。 我会在这里调整“reg_alpha”值,并留给你尝试不同的’reg_lambda’值。
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_
我们可以看到CV得分小于之前的情况。 但是尝试的值非常广,我们应该尝试更接近于最优的值(0.01),看看是否得到更好的结果。
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_
可以看到我们得到一个更好的CV。 现在我们可以在模型中应用这种正则化,看看影响:
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)
再次,我们可以看到得分略有改善。
最后,我们应该降低学习率,增加更多的树。 让我们用XGBoost的cv函数再次做这个工作。
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)
现在我们可以看到性能的显着提高,参数调整后的效果更加明显。
最后,我想分享两个关键的想法:
您还可以从我的GitHub帐户下载所有这些代码的iPython notebook。 对于R中的实现代码,可以参考这篇文章。
本文实现了端到端的基于XGBoost模型的参数调优。 我们首先讨论为什么XGBoost比GBM具有更好的性能,然后详细讨论了所涉及的各种参数。 我们还定义了一个通用函数,可以重新用于其他模型。
最后,我们讨论了解决XGBoost问题的一般方法,并通过该方法制定了AV Data Hackathon 3.x问题。
我希望你发现这很有用并更有信心应用XGBoost来解决数据科学问题。