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. 降低學習速率,確定理想參數。

咱們一起詳細地一步步進行這些操作。

具體步驟,詳見代碼:

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

####  第二步: 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 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])
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 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])
print (gsearch4.grid_scores_, gsearch4.best_params_, gsearch4.best_score_)


#從這里可以看出來,subsample 和 colsample_bytree 參數的理想取值都是0.8。現在,我們以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)

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數據上實踐了這些方法。

簡單調參方法:

首先調整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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM