2016-01-28 164 views
13

我一直在探索R中的xgboost軟件包,並通過了幾個演示以及教程,但這仍令我困惑:使用xgb.cv後交叉驗證,最佳參數如何傳遞到xgb.train?或者我應該根據xgb.cv的輸出計算理想參數(如nround,max.depth)?xgboost in R:xgb.cv如何將最佳參數傳遞到xgb.train

param <- list("objective" = "multi:softprob", 
       "eval_metric" = "mlogloss", 
       "num_class" = 12) 
cv.nround <- 11 
cv.nfold <- 5 
mdcv <-xgb.cv(data=dtrain,params = param,nthread=6,nfold = cv.nfold,nrounds = cv.nround,verbose = T) 

md <-xgb.train(data=dtrain,params = param,nround = 80,watchlist = list(train=dtrain,test=dtest),nthread=6) 

回答

40

看起來像你誤解了xgb.cv,它不是一個參數搜索功能。它做了k-fold交叉驗證,僅此而已。

在您的代碼中,它不會更改param的值。

要找到R的XGBoost中的最佳參數,有一些方法。這2種方法,

(1)使用mlr包,http://mlr-org.github.io/mlr-tutorial/release/html/

有一個XGBoost + MLR example code在Kaggle保誠的挑戰,

但是,代碼是迴歸,而不是分類。據我所知,在mlr包中沒有mlogloss公制,所以你必須自己編寫mlogloss測量。 CMIIW。

(2)方法二,通過手動設置參數然後重複,例如,

param <- list(objective = "multi:softprob", 
     eval_metric = "mlogloss", 
     num_class = 12, 
     max_depth = 8, 
     eta = 0.05, 
     gamma = 0.01, 
     subsample = 0.9, 
     colsample_bytree = 0.8, 
     min_child_weight = 4, 
     max_delta_step = 1 
    ) 
cv.nround = 1000 
cv.nfold = 5 
mdcv <- xgb.cv(data=dtrain, params = param, nthread=6, 
       nfold=cv.nfold, nrounds=cv.nround, 
       verbose = T) 

然後,找到最佳(最小)mlogloss,

min_logloss = min(mdcv[, test.mlogloss.mean]) 
min_logloss_index = which.min(mdcv[, test.mlogloss.mean]) 

min_logloss是最小值的mlogloss,而min_logloss_index是指數(回合)。

您必須重複上述過程幾次,每次手動更改參數(mlr重複您)。直到最後你得到最好的全球最低min_logloss

注意:您可以在100或200次迭代的循環中做到這一點,其中爲每次迭代隨機設置參數值。這樣,您必須將最好的[parameters_list, min_logloss, min_logloss_index]保存在變量或文件中。

注:更好地通過set.seed()重複性結果集隨機種子。不同隨機種子產生不同的結果。因此,您必須將[parameters_list, min_logloss, min_logloss_index, seednumber]保存在變量或文件中。

再說說最後你得到3個結果在3次迭代/重複:

min_logloss = 2.1457, min_logloss_index = 840 
min_logloss = 2.2293, min_logloss_index = 920 
min_logloss = 1.9745, min_logloss_index = 780 

然後,你必須使用第三個參數(它有全球最小的1.9745min_logloss)。你最好的索引(nrounds)是780

一旦你得到最佳的參數,在訓練中使用它,

# best_param is global best param with minimum min_logloss 
# best_min_logloss_index is the global minimum logloss index 
nround = 780 
md <- xgb.train(data=dtrain, params=best_param, nrounds=nround, nthread=6) 

我不認爲你需要watchlist在訓練,因爲你已經完成了交叉驗證。但是如果你仍然想使用watchlist,那就好了。

更好的是,您可以使用xgb.cv提前停止。

mdcv <- xgb.cv(data=dtrain, params=param, nthread=6, 
       nfold=cv.nfold, nrounds=cv.nround, 
       verbose = T, early.stop.round=8, maximize=FALSE) 

有了這個代碼,當mlogloss值不會在8個步驟減小時,xgb.cv將停止。你可以節省時間。您必須將maximize設置爲FALSE,因爲您期望最低mlogloss。

下面是一個示例代碼,包含100次迭代循環和隨機選擇的參數。

best_param = list() 
best_seednumber = 1234 
best_logloss = Inf 
best_logloss_index = 0 

for (iter in 1:100) { 
    param <- list(objective = "multi:softprob", 
      eval_metric = "mlogloss", 
      num_class = 12, 
      max_depth = sample(6:10, 1), 
      eta = runif(1, .01, .3), 
      gamma = runif(1, 0.0, 0.2), 
      subsample = runif(1, .6, .9), 
      colsample_bytree = runif(1, .5, .8), 
      min_child_weight = sample(1:40, 1), 
      max_delta_step = sample(1:10, 1) 
     ) 
    cv.nround = 1000 
    cv.nfold = 5 
    seed.number = sample.int(10000, 1)[[1]] 
    set.seed(seed.number) 
    mdcv <- xgb.cv(data=dtrain, params = param, nthread=6, 
        nfold=cv.nfold, nrounds=cv.nround, 
        verbose = T, early.stop.round=8, maximize=FALSE) 

    min_logloss = min(mdcv[, test.mlogloss.mean]) 
    min_logloss_index = which.min(mdcv[, test.mlogloss.mean]) 

    if (min_logloss < best_logloss) { 
     best_logloss = min_logloss 
     best_logloss_index = min_logloss_index 
     best_seednumber = seed.number 
     best_param = param 
    } 
} 

nround = best_logloss_index 
set.seed(best_seednumber) 
md <- xgb.train(data=dtrain, params=best_param, nrounds=nround, nthread=6) 

使用此代碼,每次使用隨機參數運行交叉驗證100次。然後你得到最好的參數集,即在迭代中最小值爲min_logloss

如果您發現它太小(太早停止),請增加early.stop.round的值。您還需要根據您的數據特徵更改隨機參數值的限制。

而且,對於100或200次迭代,我認爲您想將verbose更改爲FALSE。

附註:這是隨機方法的例子,您可以調整它,例如通過貝葉斯優化獲得更好的方法。如果您有Python版本的XGBoost,則XGBoost有一個很好的超參數腳本,https://github.com/mpearmain/BayesBoost可以使用貝葉斯優化搜索最佳參數集。

編輯:我想在Kaggle forum中添加第三種手動方法,由「Davut Polat」一位Kaggle大師發佈。

編輯:如果你知道Python和sklearn,你也可以使用GridSearchCV與xgboost.XGBClassifier或xgboost.XGBRegressor

沿
+0

謝謝你的詳細解答,就像讀一本教科書!所以在這種情況下,cv的唯一目的是爲你選擇nrounds,這是否正確? – snowneji

+0

@snowneji,是的,它可以這樣說,根據設定的某些參數選擇最佳的結果。因爲太小的缺陷是不合適的,太大的合適的過度配合。順便說一句,如果你發現我的答案是有用的,請接受它,謝謝。 – silo

+0

好的,謝謝! – snowneji