xgboost 参数调优指南

一、XGBoost的优势

XGBoost算法可以给预测模型带来能力的提升。当我对它的表现有更多了解的时候,当我对它的高准确率背后的原理有更多了解的时候,我发现它具有很多优势:

1 正则化

  • 标准GBDT 的实现没有像XGBoost这样的正则化步骤。正则化对减少过拟合也是有帮助的。
  • 实际上,XGBoost以“正则化提升(regularized boosting)”技术而闻名。

2 并行处理

  • XGBoost可以实现并行处理,相比GBDT有了速度的飞跃。
  • 不过,众所周知,Boosting算法是顺序处理的,它怎么可能并行呢?每一课树的构造都依赖于前一棵树,那具体是什么让我们能用多核处理器去构造一个树呢?其实 XGBoost并行指代的是更低粒度的并行,是在特征层面的并行。
  • XGBoost 也支持Hadoop实现。

3 高度的灵活性

  • XGBoost 允许用户定义自定义优化目标和评价标准
  • 它对模型增加了一个全新的维度,所以我们的处理不会受到任何限制。

4 缺失值处理

  • XGBoost内置处理缺失值的规则。
  • 用户需要提供一个和其它样本不同的值,然后把它作为一个参数传进去,以此来作为缺失值的取值。XGBoost在不同节点遇到缺失值时采用不同的处理方法,并且会学习未来遇到缺失值时的处理方法。

5 剪枝

  • 当分裂时遇到一个负损失时,GBM会停止分裂。因此GBM实际上是一个贪心算法。
  • XGBoost会一直分裂到指定的最大深度(max_depth),然后回过头来剪枝。如果某个节点之后不再有正值,它会去除这个分裂。
  • 这种做法的优点,当一个负损失(如-2)后面有个正损失(如+10)的时候,就显现出来了。GBM会在-2处停下来,因为它遇到了一个负值。但是XGBoost会继续分裂,然后发现这两个分裂综合起来会得到+8,因此会保留这两个分裂。

6 内置交叉验证

  • XGBoost允许在每一轮boosting迭代中使用交叉验证。因此,可以方便地获得最优boosting迭代次数。
  • 而GBM使用网格搜索,只能检测有限个值。

7 在已有的模型基础上继续

  • XGBoost可以在上一轮的结果上继续训练。这个特性在某些特定的应用上是一个巨大的优势。
  • sklearn中的GBM的实现也有这个功能,两种算法在这一点上是一致的。

 

二、XGBoost的参数

XGBoost的作者把所有的参数分成了三类:

  1. 通用参数:宏观函数控制。
  2. Booster参数:控制每一步的booster(tree/regression)。
  3. 学习目标参数:控制训练目标的表现。
  4. 除了以上参数还可能有其它参数,在命令行中使用

1 通用参数

1)booster[默认gbtree]
  • 选择每次迭代的模型,有两种选择: 
    gbtree:基于树的模型 
    gbliner:线性模型
2)silent[默认0]
  • 当这个参数值为1时,静默模式开启,不会输出任何信息。
  • 一般这个参数就保持默认的0,因为这样能帮我们更好地理解模型。
3)nthread[默认值为最大可能的线程数]
  • 这个参数用来进行多线程控制,应当输入系统的核数。
  • 如果你希望使用CPU全部的核,那就不要输入这个参数,算法会自动检测它。

还有两个参数,XGBoost会自动设置,目前你不用管它。

4)num_feature [set automatically by xgboost, no need to be set by user] 

boosting过程中用到的特征维数,设置为特征个数。XGBoost会自动设置,不需要手工设置。

 

 

2 booster参数

尽管有两种booster可供选择,我这里只介绍tree booster,因为它的表现远远胜过linear booster,所以linear booster很少用到。

1)eta[默认0.3]
  • 和GBM中的 learning rate 参数类似。
  • 通过减少每一步的权重,可以提高模型的鲁棒性。
  • 典型值为0.01-0.2。
2)min_child_weight[默认1]
  • 决定最小叶子节点样本权重和。
  • 和GBM的 min_child_leaf 参数类似,但不完全一样。XGBoost的这个参数是最小样本权重的和,而GBM参数是最小样本总数
  • 这个参数用于避免过拟合。当它的值较大时,可以避免模型学习到局部的特殊样本。
  • 但是如果这个值过高,会导致欠拟合。这个参数需要使用CV来调整。
3)max_depth[默认6]
  • 和GBM中的参数相同,这个值为树的最大深度。
  • 这个值也是用来避免过拟合的。max_depth越大,模型会学到更具体更局部的样本。
  • 需要使用CV函数来进行调优。
  • 典型值:3-10
4)max_leaf_nodes
  • 树上最大的节点或叶子的数量。
  • 可以替代max_depth的作用。因为如果生成的是二叉树,一个深度为n的树最多生成n2n2个叶子。
  • 如果定义了这个参数,GBM会忽略max_depth参数。
5)gamma[默认0]
  • 在节点分裂时,只有分裂后损失函数的值下降了,才会分裂这个节点。Gamma指定了节点分裂所需的最小损失函数下降值。
  • 这个参数的值越大,算法越保守。这个参数的值和损失函数息息相关,所以是需要调整的。
  • 模型在默认情况下,对于一个节点的划分只有在其loss function 得到结果大于0的情况下才进行,而gamma 给定了所需的最低loss function的值
  • gamma值使得算法更conservation,且其值依赖于loss function ,在模型中应该进行调参
6)max_delta_step[默认0]
  • 这参数限制每棵树权重改变的最大步长。如果这个参数的值为0,那就意味着没有约束。如果它被赋予了某个正值,那么它会让这个算法更加保守。
  • 通常,这个参数不需要设置。但是当各类别的样本十分不平衡时,它对逻辑回归是很有帮助的。
  • 这个参数一般用不到,但是你可以挖掘出来它更多的用处。
7)subsample[默认1]
  • 和GBM中的subsample参数一模一样。这个参数控制对于每棵树,随机采样的比例。
  • 减小这个参数的值,算法会更加保守,避免过拟合。但是,如果这个值设置得过小,它可能会导致欠拟合。
  • 典型值:0.5-1
8)colsample_bytree[默认1]
  • 和GBM里面的max_features参数类似。用来控制每棵随机采样的列数的占比(每一列是一个特征)。
  • 典型值:0.5-1
9)colsample_bylevel[默认1]
  • 用来控制树的每一级的每一次分裂,对列数的采样的占比。
  • 我个人一般不太用这个参数,因为subsample参数和colsample_bytree参数可以起到相同的作用。但是如果感兴趣,可以挖掘这个参数更多的用处。
10)lambda[默认1]
  • 权重的L2正则化项。(和Ridge regression类似)。
  • 这个参数是用来控制XGBoost的正则化部分的。
11)alpha[默认1]
  • 权重的L1正则化项。(和Lasso regression类似)。
  • 可以应用在很高维度的情况下,使得算法的速度更快。
12)scale_pos_weight[默认1]
  • 在各类别样本十分不平衡时,把这个参数设定为一个正值,可以使算法更快收敛。
  • 大于0的取值可以处理类别不平衡的情况。帮助模型更快收敛。

 

另外:Parameter for Linear Booster
    • lambda [default=0] 
      • L2 正则的惩罚系数
      • 用于处理XGBoost的正则化部分。通常不使用,但可以用来降低过拟合
    • alpha [default=0] 
      • L1 正则的惩罚系数
      • 当数据维度极高时可以使用,使得算法运行更快。
    • lambda_bias 
      • 在偏置上的L2正则。缺省值为0(在L1上没有偏置项的正则,因为L1时偏置不重要)

3 学习目标参数

这个参数用来控制理想的优化目标和每一步结果的度量方法。

1)objective[默认reg:linear]
  • 这个参数定义需要被最小化的损失函数。最常用的值有:  定义学习任务及相应的学习目标,可选的目标函数如下:
    • “reg:linear” –线性回归。
    • “reg:logistic” –逻辑回归。
    • “binary:logistic” –二分类的逻辑回归问题,输出为概率。
    • “binary:logitraw” –二分类的逻辑回归问题,输出的结果为wTx。
    • “count:poisson” –计数问题的poisson回归,输出结果为poisson分布。
    • 在poisson回归中,max_delta_step的缺省值为0.7。(used to safeguard optimization)
    • “multi:softmax” –让XGBoost采用softmax目标函数处理多分类问题,同时需要设置参数num_class(类别个数)
    • “multi:softprob” –和softmax一样,但是输出的是ndata * nclass的向量,可以将该向量reshape成ndata行nclass列的矩阵。每行数据表示样本所属于每个类别的概率。
    • “rank:pairwise” –set XGBoost to do ranking task by minimizing the pairwise loss
2)eval_metric[默认值取决于objective参数的取值]
  • 对于有效数据的度量方法。
  • 对于回归问题,默认值是rmse,对于分类问题,默认值是error。
  • 典型值有: 
    • rmse 均方根误差 
    • mae 平均绝对误差 
    • logloss 负对数似然函数值
    • error 二分类错误率(阈值为0.5)
    • merror 多分类错误率
    • mlogloss 多分类logloss损失函数
    • auc 曲线下面积
3)seed(默认0)
  • 随机数的种子
  • 设置它可以复现随机数据的结果,也可以用于调整参数

如果你比较习惯scikit-learn的参数形式,那么XGBoost的Python 版本也提供了sklearn形式的接口 XGBClassifier。

它使用sklearn形式的参数命名方式,对应关系如下:

 

1、eta -> learning_rate 
2、lambda -> reg_lambda 
3、alpha -> reg_alpha

 

另外:Console Parameters

The following parameters are only used in the console version of xgboost 
* use_buffer [ default=1 ] 
- 是否为输入创建二进制的缓存文件,缓存文件可以加速计算。缺省值为1 
* num_round 
- boosting迭代计算次数。 
* data 
- 输入数据的路径 
* test:data 
- 测试数据的路径 
* save_period [default=0] 
- 表示保存第i*save_period次迭代的模型。例如save_period=10表示每隔10迭代计算XGBoost将会保存中间结果,设置为0表示每次计算的模型都要保持。 
* task [default=train] options: train, pred, eval, dump 
- train:训练模型
- pred:对测试数据进行预测 
- eval:通过eval[name]=filenam定义评价指标 
- dump:将学习模型保存成文本格式 
* model_in [default=NULL] 
- 指向模型的路径在test, eval, dump都会用到,如果在training中定义XGBoost将会接着输入模型继续训练 
* model_out [default=NULL] 
- 训练完成后模型的保存路径,如果没有定义则会输出类似0003.model这样的结果,0003是第三次训练的模型结果。 
* model_dir [default=models] 
- 输出模型所保存的路径。 
* fmap 
- feature map, used for dump model 
* name_dump [default=dump.txt] 
- name of model dump file 
* name_pred [default=pred.txt] 
- 预测结果文件 
* pred_margin [default=0] 
- 输出预测的边界,而不是转换后的概率

 

你肯定在疑惑为啥咱们没有介绍和GBM中的n_estimators类似的参数。XGBClassifier中确实有一个类似的参数,但是,是在标准XGBoost实现中调用拟合函数时,把它作为num_boosting_rounds参数传入。 
XGBoost Guide 的一些部分是我强烈推荐大家阅读的,通过它可以对代码和参数有一个更好的了解:

XGBoost Parameters (official guide) 
XGBoost Demo Codes (xgboost GitHub repository) 
Python API Reference (official guide)

 

三、调参示例

我们从Data Hackathon 3.x AV版的hackathon中获得数据集,和GBM 介绍文章中是一样的。更多的细节可以参考competition page 
数据集可以从这里下载。我已经对这些数据进行了一些处理:

  • City变量,因为类别太多,所以删掉了一些类别。
  • DOB变量换算成年龄,并删除了一些数据。
  • 增加了 EMI_Loan_Submitted_Missing 变量。如果EMI_Loan_Submitted变量的数据缺失,则这个参数的值为1。否则为0。删除了原先的EMI_Loan_Submitted变量。
  • EmployerName变量,因为类别太多,所以删掉了一些类别。
  • 因为Existing_EMI变量只有111个值缺失,所以缺失值补充为中位数0。
  • 增加了 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 变量。
  • 删除了LoggedInSalary_Account 两个变量
  • 增加了 Processing_Fee_Missing 变量。如果 Processing_Fee 变量的数据缺失,则这个参数的值为1。否则为0。删除了原先的 Processing_Fee 变量。
  • Source前两位不变,其它分成不同的类别。
  • 进行了离散化和独热编码(一位有效编码)。

如果你有原始数据,可以从资源库里面下载data_preparationIpython notebook 文件,然后自己过一遍这些步骤。

首先,import必要的库,然后加载数据。

 

 

注意我import了两种XGBoost:

  • xgb - 直接引用xgboost。接下来会用到其中的“cv”函数。
  • XGBClassifier - 是xgboost的sklearn包。这个包允许我们像GBM一样使用Grid Search 和并行处理。

在向下进行之前,我们先定义一个函数,它可以帮助我们建立XGBoost models 并进行交叉验证。好消息是你可以直接用下面的函数,以后再自己的models中也可以使用它。

 

 

这个函数和GBM中使用的有些许不同。注意xgboost的sklearn包没有“feature_importance”这个量度,但是get_fscore()函数有相同的功能。

 

四、参数调优的一般方法

我们会使用和GBM中相似的方法。需要进行如下步骤:

  1. 选择较高的学习速率(learning rate)。一般情况下,学习速率的值为0.1。但是,对于不同的问题,理想的学习速率有时候会在0.05到0.3之间波动。选择对应于此学习速率的理想决策树数量。XGBoost有一个很有用的函数“cv”,这个函数可以在每一次迭代中使用交叉验证,并返回理想的决策树数量。

  2. 对于给定的学习速率和决策树数量,进行决策树特定参数调优(max_depth, min_child_weight, gamma, subsample, colsample_bytree)。在确定一棵树的过程中,我们可以选择不同的参数,待会儿我会举例说明。

  3. xgboost的正则化参数的调优。(lambda, alpha)。这些参数可以降低模型的复杂度,从而提高模型的表现。

  4. 降低学习速率,确定理想参数。

咱们一起详细地一步步进行这些操作。

具体步骤,详见代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
#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
 
from  matplotlib.pylab  import  rcParams
rcParams[ 'figure.figsize' =  12 4
 
train  =  pd.read_csv( 'train_modified.csv' )
#去除这两个列
target  =  'Disbursed'
IDcol  =  'ID'
 
 
 
#定义函数,进行交叉验证
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)
         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.feature_importances_).sort_values(ascending = False )
     #将原来的pd.Series(alg.booster().get_fscore()).sort_values(ascending=False)
     #替换为:pd.Series(alg.feature_importances_).sort_values(ascending=False)
     feat_imp.plot(kind = 'bar' , title = 'Feature Importances' )
     plt.ylabel( 'Feature Importance Score' )
     plt.show()
 
#### 第一步:确定学习速率和tree_based 参数调优的估计器数目
 
# 为了确定boosting参数,我们要先给其它参数一个初始值。咱们先按如下方法取值:
 
# 1、max_depth = 5 :这个参数的取值最好在3-10之间。我选的起始值为5,但是你也可以选择其它的值。起始值在4-6之间都是不错的选择。
 
# 2、min_child_weight = 1:在这里选了一个比较小的值,因为这是一个极不平衡的分类问题。因此,某些叶子节点下的值会比较小。
 
# 3、gamma = 0: 起始值也可以选其它比较小的值,在0.1到0.2之间就可以。这个参数后继也是要调整的。
 
# 4、subsample, colsample_bytree = 0.8: 这个是最常见的初始值了。典型值的范围在0.5-0.9之间。
 
# 5、scale_pos_weight = 1: 这个值是因为类别十分不平衡。
# 注意,上面这些参数的值只是一个初始的估计值,后继需要调优。
# 这里把学习速率就设成默认的0.1。然后用xgboost中的cv函数来确定最佳的决策树数量。前文中的函数可以完成这个工作。
 
predictors  =  [x  for  in  train.columns  if  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)
 
####  第二步: max_depth 和 min_weight 参数调优
 
# 我们先对这两个参数调优,是因为它们对最终结果有很大的影响。首先,我们先大范围地粗调参数,然后再小范围地微调。
# 注意:在这一节我会进行高负荷的栅格搜索(grid search),
# 这个过程大约需要15-30分钟甚至更久,具体取决于你系统的性能。你也可以根据自己系统的性能选择不同的值。
 
param_test1  =  {
  'max_depth' : list ( range ( 3 , 10 , 2 )),
  'min_child_weight' : list ( range ( 1 , 6 , 2 ))
}
#注意python3 和Python2 range()函数的区别
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])
print (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])
print (gsearch2.grid_scores_, gsearch2.best_params_, gsearch2.best_score_)
 
 
# 至此,我们得到max_depth的理想取值为4,min_child_weight的理想取值为6。同时,我们还能看到cv的得分有了小小一点提高。
# 需要注意的一点是,随着模型表现的提升,进一步提升的难度是指数级上升的,尤其是你的表现已经接近完美的时候。
# 当然啦,你会发现,虽然min_child_weight的理想取值是6,但是我们还没尝试过大于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)
 
print (gsearch2b.grid_scores_, gsearch2b.best_params_, gsearch2b.best_score_)
 
#我们可以看出,6确确实实是理想的取值了。
 
 
##### 第三步:gamma参数调优
 
# 在已经调整好其它参数的基础上,我们可以进行gamma参数的调优了。
# Gamma参数取值范围可以很大,我这里把取值范围设置为5了。你其实也可以取更精确的gamma值。
 
param_test3  =  {
  'gamma' :[i / 10.0  for  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])
print (gsearch3.grid_scores_, gsearch3.best_params_, gsearch3.best_score_)
 
# 从这里可以看出来,我们在第一步调参时设置的初始gamma值就是比较合适的。
# 也就是说,理想的gamma值为0。在这个过程开始之前,最好重新调整boosting回合,因为参数都有变化。
 
 
# 从这里,可以看出,得分提高了。所以,最终得到的参数是:
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 参数
 
# 下一步是尝试不同的subsample 和 colsample_bytree 参数。
# 我们分两个阶段来进行这个步骤。这两个步骤都取0.6,0.7,0.8,0.9作为起始值。
 
param_test4  =  {
  'subsample' :[i / 10.0  for  in  range ( 6 , 10 )],
  'colsample_bytree' :[i / 10.0  for  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])
print  (gsearch4.grid_scores_, gsearch4.best_params_, gsearch4.best_score_)
 
 
#从这里可以看出来,subsample 和 colsample_bytree 参数的理想取值都是0.8。现在,我们以0.05为步长,在这个值附近尝试取值。
 
param_test5  =  {
  'subsample' :[i / 100.0  for  in  range ( 75 , 90 , 5 )],
  'colsample_bytree' :[i / 100.0  for  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 )
 
print (gsearch5.fit(train[predictors],train[target]))
 
# 我们得到的理想取值还是原来的值。因此,最终的理想取值是:
 
# subsample: 0.8
# colsample_bytree: 0.8
 
 
#### 第五步:正则化参数调优
 
# 下一步是应用正则化来降低过拟合。由于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])
print (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])
print (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)
 
#然后我们发现性能有了小幅度提高。
 
#### 第6步:降低学习速率
 
# 最后,我们使用较低的学习速率,以及使用更多的决策树。我们可以用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)

  

至此,你可以看到模型的表现有了大幅提升,调整每个参数带来的影响也更加清楚了。 
在文章的末尾,我想分享两个重要的思想: 
1、仅仅靠参数的调整和模型的小幅优化,想要让模型的表现有个大幅度提升是不可能的。
GBM的最高得分是0.8487,XGBoost的最高得分是0.8494。确实是有一定的提升,但是没有达到质的飞跃。 
2、要想让模型的表现有一个质的飞跃,需要依靠其他的手段,诸如,特征工程(feature egineering) ,
模型组合(ensemble of model),以及堆叠(stacking)等。

 

总结:
这篇文章主要讲了如何提升XGBoost模型的表现。
首先,我们介绍了相比于GBM,为何XGBoost可以取得这么好的表现。
紧接着,我们介绍了每个参数的细节。我们定义了一个可以重复使用的构造模型的函数。 
最后,我们讨论了使用XGBoost解决问题的一般方法,在AV Data Hackathon 3.x problem数据上实践了这些方法。

1
2
3
4
5
6
7
简单调参方法:
 
首先调整max_depth ,通常max_depth 这个参数与其他参数关系不大,初始值设置为 10 ,找到一个最好的误差值,然后就可以调整参数与这个误差值进行对比。比如调整到 8 ,如果此时最好的误差变高了,那么下次就调整到 12 ;如果调整到 12 ,误差值比 10  的低,那么下次可以尝试调整到 15.
在找到了最优的max_depth之后,可以开始调整subsample,初始值设置为 1 ,然后调整到 0.8  如果误差值变高,下次就调整到 0.9 ,如果还是变高,就保持为 1.0
接着开始调整min_child_weight , 方法与上面同理
再接着调整colsample_bytree
经过上面的调整,已经得到了一组参数,这时调整eta 到 0.05 ,然后让程序运行来得到一个最佳的num_round,(在 误差值开始上升趋势的时候为最佳 )

  

 

 

参考:https://blog.csdn.net/wzmsltw/article/details/50994481

https://blog.csdn.net/han_xiaoyang/article/details/52665396

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值