介绍
如果事情不适合预测建模,请使用XGboost。XGBoost算法已成为许多数据科学家的终极武器。它是一种高度复杂的算法,功能强大,足以处理各种不规则的数据。
使用XGBoost构建模型很容易。但是,使用XGBoost改进模型很困难(至少我很挣扎)。该算法使用多个参数。要改进模型,必须进行参数调整。很难得到像实际问题的答案 - 你应该调整哪一组参数?获得最佳输出的这些参数的理想值是多少?
本文最适合XGBoost新手。在本文中,我们将学习参数调整的技巧以及有关XGBoost的一些有用信息。此外,我们将使用Python中的数据集来练习此算法。
你应该知道什么?
XGBoost(eXtreme Gradient Boosting)是梯度增强算法的高级实现。由于我在上一篇文章 - Gradient Boosting中的参数调整完整指南(GBM)中详细介绍了Gradient Boosting Machine ,我强烈建议在进一步阅读之前先仔细阅读。它将帮助您加强对GBM的增强和参数调整的理解。
特别感谢:就个人而言,我要感谢Sudalai Rajkumar先生 (又名SRK)提供的永恒支持,目前是 AV等级2。没有他的帮助,这篇文章是不可能的。他正在帮助我们指导数千名数据科学家。非常感谢SRK!
目录
- XGBoost优势
- 了解XGBoost参数
- 调整参数(带示例)
1. XGBoost优势
我一直很钦佩这种算法在预测模型中注入的增强功能。当我在高精度下探索更多有关其性能和科学的知识时,我发现了许多优点:
- 正则:
- 标准GBM实现没有像XGBoost那样的正则化,因此它也有助于减少过度拟合。
- 实际上,XGBoost也被称为“ 正则化增强 ”技术。
- 并行处理:
- 高灵活性
- XGBoost允许用户定义自定义优化目标和评估标准。
- 这为模型增加了一个全新的维度,我们可以做的事情没有限制。
- 处理缺失值
- XGBoost有一个内置的例程来处理缺失值。
- 用户需要提供与其他观察值不同的值,并将其作为参数传递。XGBoost会尝试不同的事情,因为它在每个节点上遇到缺失值,并了解将来丢失值的路径。
- 树修剪:
- 当GBM在分割中遇到负损失时,它将停止分割节点。因此,它更像是一种贪婪的算法。
- 另一方面,XGBoost分割到指定的max_depth,然后开始向后修剪树并删除没有正增益的分裂。
- 另一个优点是,有时负损失的分裂表示-2后可能会出现正损失+10的分裂。GBM会在遇到-2时停止。但是XGBoost会更深入,它会看到分裂的+8和两者的综合效果。
- 内置交叉验证
- XGBoost允许用户在每次增强过程的迭代中运行交叉验证,因此很容易在一次运行中获得精确的最佳增强迭代次数。
- 这与GBM不同,我们必须运行网格搜索,并且只能测试有限的值。
- 继续使用现有模型
- 用户可以从上一次运行的最后一次迭代开始训练XGBoost模型。这在某些特定应用中具有显着优势。
- sklearn的GBM实现也具有此功能,因此它们甚至在这一点上。
我希望你现在能理解XGBoost算法的强大功能。请注意,这些是我可以集合的要点。你知道更多吗?随意在下面发表评论,我会更新列表。
我有胃口吗?好。您可以参考以下网页以获得更深入的了解:
2. XGBoost参数
官方参数介绍看这里:
Parameters (official guide)
General Parameters(常规参数)
1.booster [default=gbtree]:选择基分类器,gbtree: tree-based models/gblinear: linear models
2.silent [default=0]:设置成1则没有运行信息输出,最好是设置为0.
3.nthread [default to maximum number of threads available if not set]:线程数
Booster Parameters(模型参数)
1.eta [default=0.3]:shrinkage参数,用于更新叶子节点权重时,乘以该系数,避免步长过大。参数值越大,越可能无法收敛。把学习率 eta 设置的小一些,小学习率可以使得后面的学习更加仔细。
2.min_child_weight [default=1]:这个参数默认是 1,是每个叶子里面 h 的和至少是多少,对正负样本不均衡时的 0-1 分类而言,假设 h 在 0.01 附近,min_child_weight 为 1 意味着叶子节点中最少需要包含 100 个样本。这个参数非常影响结果,控制叶子节点中二阶导的和的最小值,该参数值越小,越容易 overfitting。
3.max_depth [default=6]: 每颗树的最大深度,树高越深,越容易过拟合。
4.max_leaf_nodes:最大叶结点数,与max_depth作用有点重合。
5.gamma [default=0]:后剪枝时,用于控制是否后剪枝的参数。
6.max_delta_step [default=0]:这个参数在更新步骤中起作用,如果取0表示没有约束,如果取正值则使得更新步骤更加保守。可以防止做太大的更新步子,使更新更加平缓。
7.subsample [default=1]:样本随机采样,较低的值使得算法更加保守,防止过拟合,但是太小的值也会造成欠拟合。
8.colsample_bytree [default=1]:列采样,对每棵树的生成用的特征进行列采样.一般设置为: 0.5-1
9.lambda [default=1]:控制模型复杂度的权重值的L2正则化项参数,参数越大,模型越不容易过拟合。
10.alpha [default=0]:控制模型复杂程度的权重值的 L1 正则项参数,参数值越大,模型越不容易过拟合。
11.scale_pos_weight [default=1]:如果取值大于0的话,在类别样本不平衡的情况下有助于快速收敛。
Learning Task Parameters(学习任务参数)
1.objective [default=reg:linear]:定义最小化损失函数类型,常用参数:
binary:logistic –logistic regression for binary classification, returns predicted probability (not class)
multi:softmax –multiclass classification using the softmax objective, returns predicted class (not probabilities)
you also need to set an additional num_class (number of classes) parameter defining the number of unique classes
multi:softprob –same as softmax, but returns predicted probability of each data point belonging to each class.
2.eval_metric [ default according to objective ]:
The metric to be used for validation data.
The default values are rmse for regression and error for classification.
Typical values are:
rmse – root mean square error
mae – mean absolute error
logloss – negative log-likelihood
error – Binary classification error rate (0.5 threshold)
merror – Multiclass classification error rate
mlogloss – Multiclass logloss
auc: Area under the curve
3.seed [default=0]:
The random number seed. 随机种子,用于产生可复现的结果
Can be used for generating reproducible results and also for parameter tuning.
注意: python sklearn style参数名会有所变化
eta –> learning_rate
lambda –> reg_lambda
alpha –> reg_alpha
XGBoost作者将整体参数分为3类:
- 一般参数: 指导整体功能
- 助推器参数: 在每个步骤指导个体助推器(树/回归)
- 学习任务参数: 指导执行的优化
我将在这里对GBM进行类比,并强烈建议阅读本文 以从基础知识中学习。
一般参数
这些定义了XGBoost的整体功能。
- 助推器[默认= gbtree]
- 选择要在每次迭代时运行的模型类型。它有2个选项:
- gbtree:基于树的模型
- gblinear:线性模型
- 选择要在每次迭代时运行的模型类型。它有2个选项:
- 无声[default = 0]:
- 静音模式激活设置为1,即不会打印正在运行的消息。
- 保持0通常是好的,因为消息可能有助于理解模型。
- nthread [默认为未设置的最大线程数]
- 这用于并行处理,应输入系统中的核心数
- 如果您希望在所有核心上运行,则不应输入值,并且算法将自动检测
还有2个参数由XGBoost自动设置,您无需担心它们。让我们转到Booster参数。
助推器参数
虽然有两种类型的助推器,但我 在这里只考虑 树助推器,因为它总是优于线性助力器,因此后者很少使用。
- eta [默认= 0.3]
- 类似于GBM中的学习率
- 通过缩小每一步的权重,使模型更加健壮
- 使用的典型最终值:0.01-0.2
- min_child_weight [default = 1]
- 定义儿童所需观察的最小权重总和。
- 这类似于GBM中的min_child_leaf,但并不完全相同。这指的是观察的最小“权重总和”,而GBM具有最小“观察数”。
- 用于控制过度拟合。较高的值会阻止模型学习关系,这种关系可能对为树选择的特定样本高度特定。
- 太高的值会导致欠拟合,因此应使用CV进行调整。
- max_depth [default = 6]
- 树的最大深度,与GBM相同。
- 用于控制过度拟合,因为更高的深度将允许模型学习非常特定于特定样本的关系。
- 应该使用CV进行调整。
- 典型值:3-10
- max_leaf_nodes
- 树中终端节点或叶子的最大数量。
- 可以定义代替max_depth。由于创建了二叉树,因此深度'n'将产生最多2 ^ n个叶子。
- 如果已定义,则GBM将忽略max_depth。
- gamma [default = 0]
- 仅当结果分割给出损失函数的正减少时,才会分割节点。Gamma指定进行拆分所需的最小损失减少量。
- 使算法保守。值可能会根据损耗函数而有所不同,因此应进行调整。
- max_delta_step [default = 0]
- 在最大增量步长中,我们允许每棵树的权重估计。如果该值设置为0,则表示没有约束。如果将其设置为正值,则可以帮助使更新步骤更加保守。
- 通常不需要此参数,但当类非常不平衡时,它可能有助于逻辑回归。
- 这通常不使用,但如果您愿意,可以进一步探索。
- 子样本[default = 1]
- 与GBM的子样本相同。表示观察的比例是每棵树的随机样本。
- 较低的值使算法更加保守并防止过度拟合,但是太小的值可能导致不合适。
- 典型值:0.5-1
- colsample_bytree [default = 1]
- 与GBM中的max_features类似。表示每个树的随机样本列的分数。
- 典型值:0.5-1
- colsample_bylevel [default = 1]
- 表示每个级别中每个拆分的列的子采样率。
- 我不经常使用它,因为subsample和colsample_bytree将为您完成这项工作。但如果你有这种感觉,你可以进一步探索。
- lambda [default = 1]
- 关于权重的L2正则项(类似于岭回归)
- 这用于处理XGBoost的正则化部分。虽然许多数据科学家不经常使用它,但应该探索减少过度拟合。
- alpha [默认= 0]
- 关于权重的L1正则化项(类似于Lasso回归)
- 可以在非常高的维度的情况下使用,以便算法在实现时运行得更快
- scale_pos_weight [default = 1]
- 在高级别不平衡的情况下,应使用大于0的值,因为它有助于更快收敛。
学习任务参数
这些参数用于定义要在每个步骤计算的度量的优化目标。
- 客观[default = reg:linear]
- 这定义了要最小化的损失函数。最常用的值是:
- binary:logistic -logistic回归用于二进制分类,返回预测概率(不是类)
- multi:使用softmax目标的softmax -multiclass分类,返回预测类(不是概率)
- 您还需要设置一个额外的 num_class (类数)参数,用于定义唯一类的数量
- multi:softprob -same as softmax,但返回属于每个类的每个数据点的预测概率。
- 这定义了要最小化的损失函数。最常用的值是:
- eval_metric [默认根据目标]
- 用于验证数据的度量标准。
- 回归的默认值为rmse,分类的误差为rmse。
- 典型值为:
- rmse - 均方根误差
- mae - 平均绝对误差
- logloss - 负对数似然
- 错误 - 二进制分类错误率(0.5阈值)
- merror - 多类分类错误率
- mlogloss - 多类logloss
- auc: 曲线下面积
- 种子[默认= 0]
- 随机数种子。
- 可用于生成可重现的结果,也可用于参数调整。
如果您到目前为止一直在使用Scikit-Learn,那么这些参数名称可能看起来并不熟悉。一个好消息是python中的xgboost模块有一个名为XGBClassifier的sklearn包装器。它使用sklearn样式命名约定。将更改的参数名称为:
- eta - > learning_rate
- lambda - > reg_lambda
- alpha - > reg_alpha
您必须想知道我们已经定义了除GBM中“n_estimators”参数之外的所有内容。那么它作为XGBClassifier中的参数存在。但是,在标准xgboost实现中调用fit函数时,必须将其作为“num_boosting_rounds”传递。
我建议您阅读xgboost指南的以下部分,以便更好地理解参数和代码:
3.使用示例进行参数调整
我们将从Data Hackathon 3.x AV黑客马拉松中获取数据集,与GBM文章中的相同。问题的详细信息可以在竞赛页面上找到。您可以从此处下载数据集。我执行了以下步骤:
- 城市变量因类别太多而下降
- DOB转换为Age | DOB掉线了
- EMI_Loan_Submitted_Missing已创建,如果EMI_Loan_Submitted缺失则为1,否则为0 | 原始变量EMI_Loan_Submitted掉线
- 由于类别太多,EmployerName被删除
- Existing_EMI估算为0(中位数),因为只有111个值丢失
- 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丢失,则创建Processing_Fee_Missing为1,否则为0 | 原始变量Processing_Fee掉线
- 来源 - 前2名保持不变,所有其他人合并为不同类别
- 执行数字和单热编码
对于那些从竞争中获得原始数据的人,您可以从存储库中的data_preparation iPython笔记本中查看这些步骤。
让我们从导入所需的库并加载数据开始:
1 #Import libraries:
2 import pandas as pd
3 import numpy as np
4 import xgboost as xgb
5 from xgboost.sklearn import XGBClassifier
6 from sklearn import cross_validation, metrics #Additional scklearn functions
7 from sklearn.grid_search import GridSearchCV #Perforing grid search
8
9 import matplotlib.pylab as plt
10 %matplotlib inline
11 from matplotlib.pylab import rcParams
12 rcParams['figure.figsize'] = 12, 4
13
14 train = pd.read_csv('train_modified.csv')
15 target = 'Disbursed'
16 IDcol = 'ID'
请注意,我已导入2种形式的XGBoost:
- xgb - 这是直接的xgboost库。我将使用此库中的特定函数“cv”
- XGBClassifier - 这是XGBoost的sklearn包装器。这使得我们可以像对待GBM一样使用sklearn的网格搜索和并行处理
在继续之前,让我们定义一个函数,它将帮助我们创建XGBoost模型并执行交叉验证。最好的部分是您可以按原样使用此功能,稍后将其用于您自己的模型。
1 def modelfit(alg, dtrain, predictors,useTrainCV=True, cv_folds=5, early_stopping_rounds=50):
2
3 if useTrainCV:
4 xgb_param = alg.get_xgb_params()
5 xgtrain = xgb.DMatrix(dtrain[predictors].values, label=dtrain[target].values)
6 cvresult = xgb.cv(xgb_param, xgtrain, num_boost_round=alg.get_params()['n_estimators'], nfold=cv_folds,
7 metrics='auc', early_stopping_rounds=early_stopping_rounds, show_progress=False)
8 alg.set_params(n_estimators=cvresult.shape[0])
9
10 #Fit the algorithm on the data
11 alg.fit(dtrain[predictors], dtrain['Disbursed'],eval_metric='auc')
12
13 #Predict training set:
14 dtrain_predictions = alg.predict(dtrain[predictors])
15 dtrain_predprob = alg.predict_proba(dtrain[predictors])[:,1]
16
17 #Print model report:
18 print "\nModel Report"
19 print "Accuracy : %.4g" % metrics.accuracy_score(dtrain['Disbursed'].values, dtrain_predictions)
20 print "AUC Score (Train): %f" % metrics.roc_auc_score(dtrain['Disbursed'], dtrain_predprob)
21
22 feat_imp = pd.Series(alg.booster().get_fscore()).sort_values(ascending=False)
23 feat_imp.plot(kind='bar', title='Feature Importances')
24 plt.ylabel('Feature Importance Score')
参数调整的一般方法
第一步:确定学习速率和tree_based 参数调优的估计器数目
树的最大深度一般3-10
max_depth = 5
节点分裂所需的最小损失函数下降值0.1到0.2
gamma = 0
采样
subsample= 0.8,
colsample_bytree = 0.8
比较小的值,适用极不平衡的分类问题
min_child_weight = 1
类别十分不平衡
scale_pos_weight = 1
第二步: max_depth 和 min_weight 参数调优
第三步:gamma参数调优
第四步:调整subsample 和 colsample_bytree 参数
第五步:正则化参数调优
第六步:降低学习速率
网格搜索
可以先固定一个参数 最优化后继续调整
第一步:确定学习速率和tree_based 给个常见初始值 根据是否类别不平衡调节
max_depth,min_child_weight,gamma,subsample,scale_pos_weight
max_depth=3 起始值在4-6之间都是不错的选择。
min_child_weight比较小的值解决极不平衡的分类问题eg:1
subsample, colsample_bytree = 0.8: 这个是最常见的初始值了
scale_pos_weight = 1: 这个值是因为类别十分不平衡。
第二步: max_depth 和 min_weight 对最终结果有很大的影响
‘max_depth’:range(3,10,2),
‘min_child_weight’:range(1,6,2)
先大范围地粗调参数,然后再小范围地微调。
第三步:gamma参数调优
‘gamma’:[i/10.0 for i in range(0,5)]
第四步:调整subsample 和 colsample_bytree 参数
‘subsample’:[i/100.0 for i in range(75,90,5)],
‘colsample_bytree’:[i/100.0 for i in range(75,90,5)]
第五步:正则化参数调优
‘reg_alpha’:[1e-5, 1e-2, 0.1, 1, 100]
‘reg_lambda’
第六步:降低学习速率
learning_rate =0.01,
我们将在这里使用类似于GBM的方法。要执行的各个步骤是:
- 选择相对较高的学习率。通常学习率为0.1,但介于0.05到0.3之间,可能适用于不同的问题。确定此学习率的最佳树木数量。XGBoost有一个非常有用的函数叫做“cv”,它在每次增强迭代时执行交叉验证,从而返回所需的最佳树数。
- 调整树特定参数 (max_depth,min_child_weight,gamma,subsample,colsample_bytree)以确定学习速率和树木数量。请注意,我们可以选择不同的参数来定义树,我将在这里举一个例子。
- 调整 xgboost的正则化参数(lambda,alpha),这有助于降低模型复杂性并提高性能。
- 降低学习率并确定最佳参数。
让我们看一个更详细的一步一步的方法。
步骤1:修复学习率和用于调整基于树的参数的估计量的数量
第一步调整n_estimators的个数
为了决定提升参数,我们需要设置其他参数的一些初始值。让我们采取以下价值观:
- max_depth = 5 :这应该在3-10之间。我从5开始,但你也可以选择不同的数字。4-6可以是很好的起点。
- min_child_weight = 1 :选择较小的值是因为它是一个高度不平衡的类问题,并且叶节点可以具有较小的大小组。
- gamma = 0 :也可以选择较小的值如0.1-0.2来启动。无论如何,这将在以后进行调整。
- subsample,colsample_bytree = 0.8:这是一个常用的使用起始值。典型值介于0.5-0.9之间。
- scale_pos_weight = 1:由于高级别的不平衡。
请注意,以上所有内容仅为初步估算值,稍后会进行调整。让我们在这里采用默认的学习率0.1,并使用xgboost的cv函数检查树的最佳数量。上面定义的函数将为我们完成。
1 #Choose all predictors except target & IDcols
2 predictors = [x for x in train.columns if x not in [target, IDcol]]
3 xgb1 = XGBClassifier(
4 learning_rate =0.1,
5 n_estimators=1000,
6 max_depth=5,
7 min_child_weight=1,
8 gamma=0,
9 subsample=0.8,
10 colsample_bytree=0.8,
11 objective= 'binary:logistic',
12 nthread=4,
13 scale_pos_weight=1,
14 seed=27)
15 modelfit(xgb1, train, predictors)
正如您所看到的,我们在这里得到140作为0.1学习率的最佳估计。请注意,根据系统的功率,此值可能太高。在这种情况下,您可以提高学习率并重新运行命令以减少估算量。
注意:您将在此处的输出中看到测试AUC为“AUC分数(测试)”。但是,如果您尝试在系统上运行该命令,则不会出现这种情况,因为数据未公开。这里提供的仅供参考。生成此输出的代码部分已在此处删除。
第2步:调整max_depth和min_child_weight
我们先调整它们,因为它们对模型结果的影响最大。首先,让我们设置更宽的范围,然后我们将为更小的范围执行另一次迭代。
重要说明:我将在本节中搜索一些重型网格,这可能需要15-30分钟甚至更长的时间才能运行,具体取决于您的系统。您可以根据系统可以处理的内容来更改要测试的值的数量。
1 param_test1 = {
2 'max_depth':range(3,10,2),
3 'min_child_weight':range(1,6,2)
4 }
5 gsearch1 = GridSearchCV(estimator = XGBClassifier(learning_rate = 0.1,n_estimators = 140,max_depth = 5,
6 min_child_weight = 1,gamma = 0,subsample = 0.8,colsample_bytree = 0.8,
7 objective ='binary:logistic',nthread = 4,scale_pos_weight = 1,seed = 27),
8 param_grid = param_test1,scoring ='roc_auc',n_jobs = 4, iid = False,cv = 5)
9 gsearch1.fit(train [predictors],train [target])
10 gsearch1.grid_scores_,gsearch1.best_params_,gsearch1.best_score_
在这里,我们运行了12种组合,值之间的间隔更宽。理想值是5 MAX_DEPTH和5 min_child_weight。让我们更进一步,寻找最佳价值。我们将搜索高于和低于最佳值的值1,因为我们间隔为2。
1 param_test2 = {
2 'max_depth':[4,5,6],
3 'min_child_weight':[4,5,6]
4 }
5 gsearch2 = GridSearchCV(estimator = XGBClassifier(learning_rate = 0.1,n_estimators = 140,max_depth = 5,
6 min_child_weight = 2) ,gamma = 0,subsample = 0.8,colsample_bytree = 0.8,
7 objective ='binary:logistic',nthread = 4,scale_pos_weight = 1,seed = 27),
8 param_grid = param_test2,scoring ='roc_auc',n_jobs = 4,iid = False,cv = 5)
9 gsearch2.fit(train [predictors],train [target])
10 gsearch2.grid_scores_,gsearch2.best_params_,gsearch2.best_score_
在这里,我们得到的最佳值是4 MAX_DEPTH和6 min_child_weight。此外,我们可以看到CV分数略有增加。请注意,随着模型性能的提高,甚至难以实现性能上的边际收益。您会注意到我们在这里得到6作为min_child_weight的最佳值,但我们没有尝试超过6的值。我们可以这样做:
1 param_test2b = {
2 'min_child_weight':[6,8,10,12]
3 }
4 gsearch2b = GridSearchCV(estimator = XGBClassifier( learning_rate=0.1, n_estimators=140, max_depth=4,
5 min_child_weight=2, gamma=0, subsample=0.8, colsample_bytree=0.8,
6 objective= 'binary:logistic', nthread=4, scale_pos_weight=1,seed=27),
7 param_grid = param_test2b, scoring='roc_auc',n_jobs=4,iid=False, cv=5)
8 gsearch2b.fit(train[predictors],train[target])
9 modelfit(gsearch3.best_estimator_, train, predictors)
10 gsearch2b.grid_scores_, gsearch2b.best_params_, gsearch2b.best_score_
第3步:调整伽玛
现在让我们使用上面已调整的参数调整伽马值。Gamma可以采用各种值,但我会在这里检查5个值。您可以进入更精确的值。
1 param_test3 = {
2 'gamma':[i / 10.0 for i in range(0,5)]
3 }
4 gsearch3 = GridSearchCV(estimator = XGBClassifier(learning_rate = 0.1,n_estimators = 140,max_depth = 4,
5 min_child_weight = 6,gamma = 0, subsample = 0.8,colsample_bytree = 0.8,
6 objective ='binary:logistic',nthread = 4,scale_pos_weight = 1,seed = 27),
7 param_grid = param_test3,scoring ='roc_auc',n_jobs = 4,iid = False,cv = 5 )
8 gsearch3.fit(train [predictors],train [target])
9 gsearch3.grid_scores_,gsearch3.best_params_,gsearch3.best_score_
这表明我们的伽玛原始值,即0是最佳值。在继续之前,一个好主意是重新校准更新参数的增强轮数。
1 xgb2 = XGBClassifier(
2 learning_rate = 0.1,
3 n_estimators = 1000,
4 max_depth = 4,
5 min_child_weight = 6,
6 gamma = 0,
7 subsample = 0.8,
8 colsample_bytree = 0.8,
9 objective ='binary:logistic',
10 nthread = 4,
11 scale_pos_weight = 1,
12 seed = 27)
13 modelfit(xgb2,train,predictors)
在这里,我们可以看到得分的提高。所以最终的参数是:
- max_depth:4
- min_child_weight:6
- gamma:0
第4步:调整子样本和colsample_bytree
下一步是尝试不同的subsample和colsample_bytree值。让我们分两个阶段进行,并且两者的值均为0.6,0.7,0.8,0.9。
1 param_test4 = {
2 'subsample':[i / 10.0 for i in range(6,10)],
3 'colsample_bytree':[i / 10.0 for i in range(6,10)]
4 }
5 gsearch4 = GridSearchCV(estimator = XGBClassifier(learning_rate) = 0.1,n_estimators = 177,max_depth = 4,
6 min_child_weight = 6,gamma = 0,subsample = 0.8,colsample_bytree = 0.8,
7 objective ='binary:logistic',nthread = 4,scale_pos_weight = 1,seed = 27),
8 param_grid = param_test4,scoring ='roc_auc',n_jobs = 4,iid = False,cv = 5)
9 gsearch4.fit(train [predictors],train [target])
10 gsearch4.grid_scores_,gsearch4.best_params_,gsearch4.best_score_
在这里,我们发现0.8是 subsample和colsample_bytree 的最佳值。现在我们应该围绕这些值尝试0.05区间的值。
1 param_test5 = {
2 'subsample':[i / 100.0 for i in range(75,90,5)],
3 'colsample_bytree':[i / 100.0 for i in range(75,90,5)]
4 }
5 gsearch5 = GridSearchCV(estimator) = XGBClassifier(learning_rate = 0.1,n_estimators = 177,max_depth = 4,
6 min_child_weight = 6,gamma = 0,subsample = 0.8,colsample_bytree = 0.8,
7 objective ='binary:logistic',nthread = 4,scale_pos_weight = 1,seed = 27 ),
8 param_grid = param_test5,scoring ='roc_auc',n_jobs = 4,iid = False,cv = 5)
9 gsearch5.fit(train [predictors],train [target])
我们再次得到与以前相同的值。因此,最佳值为:
- 子样本:0.8
- colsample_bytree:0.8
第5步:调整正则化参数
下一步是应用正则化来减少过度拟合。虽然很多人不会使用这些参数,因为伽玛提供了一种控制复杂性的实质方法。但我们应该总是尝试一下。我将在这里调整'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),看看我们是否能得到更好的东西。
1 param_test7 = {
2 'reg_alpha':[0, 0.001, 0.005, 0.01, 0.05]
3 }
4 gsearch7 = GridSearchCV(estimator = XGBClassifier( learning_rate =0.1, n_estimators=177, max_depth=4,
5 min_child_weight=6, gamma=0.1, subsample=0.8, colsample_bytree=0.8,
6 objective= 'binary:logistic', nthread=4, scale_pos_weight=1,seed=27),
7 param_grid = param_test7, scoring='roc_auc',n_jobs=4,iid=False, cv=5)
8 gsearch7.fit(train[predictors],train[target])
9 gsearch7.grid_scores_, gsearch7.best_params_, gsearch7.best_score_
你可以看到我们得到了更好的简历。现在我们可以在模型中应用此正则化并查看影响:
1 xgb3 = XGBClassifier(
2 learning_rate = 0.1,
3 n_estimators = 1000,
4 max_depth = 4,
5 min_child_weight = 6,
6 gamma = 0,
7 subsample = 0.8,
8 colsample_bytree = 0.8,
9 reg_alpha = 0.005,
10 objective ='binary:logistic',
11 nthread = 4,
12 scale_pos_weight = 1,
13 种子= 27)
14 modelfit(xgb3,train,predictors)
我们再次看到分数略有改善。
第6步:降低学习率
最后,我们应该降低学习率并增加更多树木。让我们使用XGBoost的cv函数再次完成工作。
1 xgb4 = XGBClassifier(
2 learning_rate = 0.01,
3 n_estimators = 5000,
4 max_depth = 4,
5 min_child_weight = 6,
6 gamma = 0,
7 subsample = 0.8,
8 colsample_bytree = 0.8,
9 reg_alpha = 0.005,
10 objective ='binary:logistic',
11 nthread = 4,
12 scale_pos_weight = 1,
13 种子= 27)
14 modelfit(xgb4,train,predictors)
现在我们可以看到性能的显着提升,参数调整的效果更加清晰。
在我们结束时,我想分享两个关键想法:
- 这是很难得到一个非常大的飞跃只要使用在性能参数整定或略好机型。GBM的最高得分为0.8487,而XGBoost得分为0.8494。这是一个不错的改进,但不是非常重要的事情。
- 通过特征工程,创建模型集合,堆叠等其他方法可以获得显着的跳跃
您也可以从我的GitHub帐户下载包含所有这些型号代码的iPython笔记本。对于R中的代码,您可以参考这篇文章。
=================================================================================
第一步:确定学习速率和tree_based 参数调优的估计器数目
树的最大深度一般3-10
max_depth = 5
节点分裂所需的最小损失函数下降值0.1到0.2
gamma = 0
采样
subsample= 0.8,
colsample_bytree = 0.8
比较小的值,适用极不平衡的分类问题
min_child_weight = 1
类别十分不平衡
scale_pos_weight = 1
from xgboost import XGBClassifier
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)
第二步: max_depth 和 min_weight 参数调优
grid_search参考
http://scikit-learn.org/stable/modules/generated/sklearn.grid_search.GridSearchCV.html
python并行调参——scikit-learn grid_search_Rachel-Zhang的博客-CSDN博客
网格搜索scoring=’roc_auc’只支持二分类,多分类需要修改scoring(默认支持多分类)
param_test1 = {
‘max_depth‘:range(3,10,2),
‘min_child_weight‘:range(1,6,2)
}
#param_test2 = {
‘max_depth‘:[4,5,6],
‘min_child_weight‘:[4,5,6]
}
from sklearn import svm, grid_search, datasets
from sklearn import grid_search
gsearch1 = grid_search.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_
#网格搜索scoring=‘roc_auc‘只支持二分类,多分类需要修改scoring(默认支持多分类)
第三步:gamma参数调优
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_
第四步:调整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=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_
第五步:正则化参数调优
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_
第六步:降低学习速率
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)
python示例
import xgboost as xgb
import pandas as pd
#获取数据
from sklearn import cross_validation
from sklearn.datasets import load_iris
iris = load_iris()
#切分数据集
X_train, X_test, y_train, y_test = cross_validation.train_test_split(iris.data, iris.target, test_size=0.33, random_state=42)
#设置参数
m_class = xgb.XGBClassifier(
learning_rate =0.1,
n_estimators=1000,
max_depth=5,
gamma=0,
subsample=0.8,
colsample_bytree=0.8,
objective= ‘binary:logistic‘,
nthread=4,
seed=27)
#训练
m_class.fit(X_train, y_train)
test_21 = m_class.predict(X_test)
print "Accuracy : %.2f" % metrics.accuracy_score(y_test, test_21)
#预测概率
#test_2 = m_class.predict_proba(X_test)
#查看AUC评价标准
from sklearn import metrics
print "Accuracy : %.2f" % metrics.accuracy_score(y_test, test_21)
##必须二分类才能计算
##print "AUC Score (Train): %f" % metrics.roc_auc_score(y_test, test_2)
#查看重要程度
feat_imp = pd.Series(m_class.booster().get_fscore()).sort_values(ascending=False)
feat_imp.plot(kind=‘bar‘, title=‘Feature Importances‘)
import matplotlib.pyplot as plt
plt.show()
#回归
#m_regress = xgb.XGBRegressor(n_estimators=1000,seed=0)
#m_regress.fit(X_train, y_train)
#test_1 = m_regress.predict(X_test)
整理
xgb原始
from sklearn.model_selection import train_test_split
from sklearn import metrics
from sklearn.datasets import make_hastie_10_2
import xgboost as xgb
#记录程序运行时间
import time
start_time = time.time()
X, y = make_hastie_10_2(random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)##test_size测试集合所占比例
#xgb矩阵赋值
xgb_train = xgb.DMatrix(X_train, label=y_train)
xgb_test = xgb.DMatrix(X_test,label=y_test)
##参数
params={
‘booster‘:‘gbtree‘,
‘silent‘:1 ,#设置成1则没有运行信息输出,最好是设置为0.
#‘nthread‘:7,# cpu 线程数 默认最大
‘eta‘: 0.007, # 如同学习率
‘min_child_weight‘:3,
# 这个参数默认是 1,是每个叶子里面 h 的和至少是多少,对正负样本不均衡时的 0-1 分类而言
#,假设 h 在 0.01 附近,min_child_weight 为 1 意味着叶子节点中最少需要包含 100 个样本。
#这个参数非常影响结果,控制叶子节点中二阶导的和的最小值,该参数值越小,越容易 overfitting。
‘max_depth‘:6, # 构建树的深度,越大越容易过拟合
‘gamma‘:0.1, # 树的叶子节点上作进一步分区所需的最小损失减少,越大越保守,一般0.1、0.2这样子。
‘subsample‘:0.7, # 随机采样训练样本
‘colsample_bytree‘:0.7, # 生成树时进行的列采样
‘lambda‘:2, # 控制模型复杂度的权重值的L2正则化项参数,参数越大,模型越不容易过拟合。
#‘alpha‘:0, # L1 正则项参数
#‘scale_pos_weight‘:1, #如果取值大于0的话,在类别样本不平衡的情况下有助于快速收敛。
#‘objective‘: ‘multi:softmax‘, #多分类的问题
#‘num_class‘:10, # 类别数,多分类与 multisoftmax 并用
‘seed‘:1000, #随机种子
#‘eval_metric‘: ‘auc‘
}
plst = list(params.items())
num_rounds = 100 # 迭代次数
watchlist = [(xgb_train, ‘train‘),(xgb_test, ‘val‘)]
#训练模型并保存
# early_stopping_rounds 当设置的迭代次数较大时,early_stopping_rounds 可在一定的迭代次数内准确率没有提升就停止训练
model = xgb.train(plst, xgb_train, num_rounds, watchlist,early_stopping_rounds=100,pred_margin=1)
#model.save_model(‘./model/xgb.model‘) # 用于存储训练出的模型
print "best best_ntree_limit",model.best_ntree_limit
y_pred = model.predict(xgb_test,ntree_limit=model.best_ntree_limit)
print (‘error=%f‘ % ( sum(1 for i in range(len(y_pred)) if int(y_pred[i]>0.5)!=y_test[i]) /float(len(y_pred))))
#输出运行时长
cost_time = time.time()-start_time
print "xgboost success!",‘\n‘,"cost time:",cost_time,"(s)......"
xgb使用sklearn接口(推荐)
官方
会改变的函数名是:
eta -> learning_rate
lambda -> reg_lambda
alpha -> reg_alpha
from sklearn.model_selection import train_test_split
from sklearn import metrics
from sklearn.datasets import make_hastie_10_2
from xgboost.sklearn import XGBClassifier
X, y = make_hastie_10_2(random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)##test_size测试集合所占比例
clf = XGBClassifier(
silent=0 ,#设置成1则没有运行信息输出,最好是设置为0.是否在运行升级时打印消息。
#nthread=4,# cpu 线程数 默认最大
learning_rate= 0.3, # 如同学习率
min_child_weight=1,
# 这个参数默认是 1,是每个叶子里面 h 的和至少是多少,对正负样本不均衡时的 0-1 分类而言
#,假设 h 在 0.01 附近,min_child_weight 为 1 意味着叶子节点中最少需要包含 100 个样本。
#这个参数非常影响结果,控制叶子节点中二阶导的和的最小值,该参数值越小,越容易 overfitting。
max_depth=6, # 构建树的深度,越大越容易过拟合
gamma=0, # 树的叶子节点上作进一步分区所需的最小损失减少,越大越保守,一般0.1、0.2这样子。
subsample=1, # 随机采样训练样本 训练实例的子采样比
max_delta_step=0,#最大增量步长,我们允许每个树的权重估计。
colsample_bytree=1, # 生成树时进行的列采样
reg_lambda=1, # 控制模型复杂度的权重值的L2正则化项参数,参数越大,模型越不容易过拟合。
#reg_alpha=0, # L1 正则项参数
#scale_pos_weight=1, #如果取值大于0的话,在类别样本不平衡的情况下有助于快速收敛。平衡正负权重
#objective= ‘multi:softmax‘, #多分类的问题 指定学习任务和相应的学习目标
#num_class=10, # 类别数,多分类与 multisoftmax 并用
n_estimators=100, #树的个数
seed=1000 #随机种子
#eval_metric= ‘auc‘
)
clf.fit(X_train,y_train,eval_metric=‘auc‘)
#设置验证集合 verbose=False不打印过程
clf.fit(X_train, y_train,eval_set=[(X_train, y_train), (X_val, y_val)],eval_metric=‘auc‘,verbose=False)
#获取验证集合结果
evals_result = clf.evals_result()
y_true, y_pred = y_test, clf.predict(X_test)
print"Accuracy : %.4g" % metrics.accuracy_score(y_true, y_pred)
#回归
#m_regress = xgb.XGBRegressor(n_estimators=1000,seed=0)
网格搜索
可以先固定一个参数 最优化后继续调整
第一步:确定学习速率和tree_based 给个常见初始值 根据是否类别不平衡调节
max_depth,min_child_weight,gamma,subsample,scale_pos_weight
max_depth=3 起始值在4-6之间都是不错的选择。
min_child_weight比较小的值解决极不平衡的分类问题eg:1
subsample, colsample_bytree = 0.8: 这个是最常见的初始值了
scale_pos_weight = 1: 这个值是因为类别十分不平衡。
第二步: max_depth 和 min_weight 对最终结果有很大的影响
‘max_depth’:range(3,10,2),
‘min_child_weight’:range(1,6,2)
先大范围地粗调参数,然后再小范围地微调。
第三步:gamma参数调优
‘gamma’:[i/10.0 for i in range(0,5)]
第四步:调整subsample 和 colsample_bytree 参数
‘subsample’:[i/100.0 for i in range(75,90,5)],
‘colsample_bytree’:[i/100.0 for i in range(75,90,5)]
第五步:正则化参数调优
‘reg_alpha’:[1e-5, 1e-2, 0.1, 1, 100]
‘reg_lambda’
第六步:降低学习速率
learning_rate =0.01,
from sklearn.model_selection import GridSearchCV
tuned_parameters= [{‘n_estimators‘:[100,200,500],
‘max_depth‘:[3,5,7], ##range(3,10,2)
‘learning_rate‘:[0.5, 1.0],
‘subsample‘:[0.75,0.8,0.85,0.9]
}]
tuned_parameters= [{‘n_estimators‘:[100,200,500,1000]
}]
clf = GridSearchCV(XGBClassifier(silent=0,nthread=4,learning_rate= 0.5,min_child_weight=1, max_depth=3,gamma=0,subsample=1,colsample_bytree=1,reg_lambda=1,seed=1000), param_grid=tuned_parameters,scoring=‘roc_auc‘,n_jobs=4,iid=False,cv=5)
clf.fit(X_train, y_train)
##clf.grid_scores_, clf.best_params_, clf.best_score_
print(clf.best_params_)
y_true, y_pred = y_test, clf.predict(X_test)
print"Accuracy : %.4g" % metrics.accuracy_score(y_true, y_pred)
y_proba=clf.predict_proba(X_test)[:,1]
print "AUC Score (Train): %f" % metrics.roc_auc_score(y_true, y_proba)
from sklearn.model_selection import GridSearchCV
parameters= [{‘learning_rate‘:[0.01,0.1,0.3],‘n_estimators‘:[1000,1200,1500,2000,2500]}]
clf = GridSearchCV(XGBClassifier(
max_depth=3,
min_child_weight=1,
gamma=0.5,
subsample=0.6,
colsample_bytree=0.6,
objective= ‘binary:logistic‘, #逻辑回归损失函数
scale_pos_weight=1,
reg_alpha=0,
reg_lambda=1,
seed=27
),
param_grid=parameters,scoring=‘roc_auc‘)
clf.fit(X_train, y_train)
print(clf.best_params_)
y_pre= clf.predict(X_test)
y_pro= clf.predict_proba(X_test)[:,1]
print "AUC Score : %f" % metrics.roc_auc_score(y_test, y_pro)
print"Accuracy : %.4g" % metrics.accuracy_score(y_test, y_pre)
输出特征重要性
import pandas as pd
import matplotlib.pylab as plt
feat_imp = pd.Series(clf.booster().get_fscore()).sort_values(ascending=False)
#新版需要转换成dict or list
#feat_imp = pd.Series(dict(clf.get_booster().get_fscore())).sort_values(ascending=False)
#plt.bar(feat_imp.index, feat_imp)
feat_imp.plot(kind=‘bar‘, title=‘Feature Importances‘)
plt.ylabel(‘Feature Importance Score‘)
plt.show()
xgboost相关API
DMatrix相关方法:
1.feature_names,直接点运算获得各列的特征名字;
2.feature_types,直接点运算获得各列特征的类型;
3.get_base_margin(),这个还不清楚。。。
4.get_float_info(field)
5.get_label(),获得样本标签列;
6.get_uint_info(field);
7.get_weight(),获得权重;
8.num_col(),列数统计;
9.num_row(),行数统计;
10.save_binary(fname, silent=True),将DMatrix对象存储为文件;
11.set_base_margin(margin);
12.set_float_info(field, data);
13.set_group(group);用于排序操作
14.set_label(label);设定标签
15.set_uint_info(field, data);
16.set_weight(weight);weight为数组形式,给每组数据赋予权值
17.slice(rindex);一个基于rindex的切片操作,返回新的DMatrix
Booster
class xgboost.Booster(params=None, cache=(), model_file=None)
这个Booster可以理解为xgb中的一颗树,相对应的操作就是基于树的结构、参数、特征分裂点等方面展开。
方法:
1.attr(key);获取由key指定的属性的值
2.attributes();获取完整的Booster的属性的值
3.boost(dtrain, grad, hess);手动单轮训练这个Booster
4.copy();对这个Booster的复制(本质上就是对树结构和分割点等信息的复制)
多线程预测注意事项
// 如果使用多线程,可以创建一个线程池, 然后可以使用该方法复制模型。将模型放入队列中,使用多个副本进行预测。
multithreading in linux · Issue #311 · dmlc/xgboost · GitHub
5.dump_model(fout, fmap=’’, with_stats=False);此方法能帮助我们看到基分类器的决策树如何选择特征进行分裂节点的;
6.eval(data, name=‘eval’, iteration=0);
7.eval_set(evals, iteration=0, feval=None);
8.get_dump(fmap=’’, with_stats=False);以string形式获得转储模型
9.get_fscore(fmap=’’);获得每个特征的特征重要度
10.get_score(fmap=’’, importance_type=‘weight’);
11.get_split_value_histogram(feature, fmap=’’, bins=None, as_pandas=True);获得特征分裂点的具体值
12.load_model(fname);载入模型
13.load_rabit_checkpoint();
14.predict(data, output_margin=False, ntree_limit=0, pred_leaf=False);相当于基于单树的预测
15.save_model(fname);存储模型
16.save_rabit_checkpoint();
17.save_raw();
18.set_attr(**kwargs);设定指定的属性值
19.set_param(params, value=None)设定参数
20.update(dtrain, iteration, fobj=None);