{caret}xgTree:重新采样的性能指标中存在缺失值

{caret}xgTree: There were missing values in resampled performance measures

我正尝试在 this dataset 上 运行 一个 5 倍 XGBoost 模型。当我运行以下代码时:

  train_control<- trainControl(method="cv", 
                           search = "random", 
                           number=5,
                           verboseIter=TRUE)

  # Train Models 
  xgb.mod<- train(Vote_perc~.,
              data=forkfold, 
              trControl=train_control, 
              method="xgbTree", 
              family=binomial())

我收到以下警告:

Warning message:
In nominalTrainWorkflow(x = x, y = y, wts = weights, info = trainInfo,  :
  There were missing values in resampled performance measures.

此外,"predict"函数运行s,但所有预测都是相同的数字。我怀疑这是一个仅拦截模型,但我不确定。此外,当我删除

search="random"

参数,运行正确。我想 运行 随机搜索,以便我可以隔离哪些超参数可能最有效,但每次尝试时,我都会收到警告。我错过了什么?谢谢!

这是您可以对数据执行的一种方法:

加载数据:

forkfold  <- read.csv("forkfold.csv", row.names = 1)

这里的问题是,在 97% 的情况下,结果变量为 0,而在其余 3% 的情况下,它非常接近于零。

length(forkfold$Vote_perc)
#output
7069

sum(forkfold$Vote_perc != 0)
#output 
212

您将其描述为分类问题,我将通过将其转换为二元问题来对待它:

forkfold$Vote_perc <- ifelse(forkfold$Vote_perc != 0,
                             "one",
                             "zero")

由于集合高度不平衡,使用 Accuracy 作为选择指标是不可能的。在这里,我将尝试通过定义自定义评估函数来最大化 Sensitivity + Specificity,如 here 所述:

fourStats <- function (data, lev = levels(data$obs), model = NULL) {
  out <- c(twoClassSummary(data, lev = levels(data$obs), model = NULL))
  coords <- matrix(c(1, 1, out["Spec"], out["Sens"]), 
                   ncol = 2, 
                   byrow = TRUE)
  colnames(coords) <- c("Spec", "Sens")
  rownames(coords) <- c("Best", "Current")
  c(out, Dist = dist(coords)[1])
}

我会在trainControl中指定这个函数:

train_control <- trainControl(method = "cv", 
                              search = "random", 
                              number = 5,
                              verboseIter=TRUE,
                              classProbs = T,
                              savePredictions = "final",
                              summaryFunction = fourStats)

set.seed(1)
xgb.mod <- train(Vote_perc~.,
                 data = forkfold, 
                 trControl = train_control, 
                 method = "xgbTree", 
                 tuneLength = 50,
                 metric = "Dist",
                 maximize = FALSE,
                 scale_pos_weight = sum(forkfold$Vote_perc == "zero")/sum(forkfold$Vote_perc == "one"))

我将在 fourStats 汇总函数中使用之前定义的 Dist 指标。该指标应最小化,因此 maximize = FALSE。我将对曲调 space 使用随机搜索,并将测试 50 组随机超参数值 (tuneLength = 50)。

我还设置了 xgboost 函数的 scale_pos_weight 参数。来自?xgboost的帮助:

scale_pos_weight, [default=1] Control the balance of positive and negative weights, useful for unbalanced classes. A typical value to consider: sum(negative cases) / sum(positive cases) See Parameters Tuning for more discussion. Also see Higgs Kaggle competition demo for examples: R, py1, py2, py3

我按照推荐定义的sum(negative cases) / sum(positive cases)

模型训练后,它会选择一些炒作参数来最小化 Dist

评估保留预测的混淆矩阵:

caret::confusionMatrix(xgb.mod$pred$pred, xgb.mod$pred$obs)

Confusion Matrix and Statistics

          Reference
Prediction  one zero
      one   195  430
      zero   17 6427

               Accuracy : 0.9368          
                 95% CI : (0.9308, 0.9423)
    No Information Rate : 0.97            
    P-Value [Acc > NIR] : 1               

                  Kappa : 0.4409          
 Mcnemar's Test P-Value : <2e-16          

            Sensitivity : 0.91981         
            Specificity : 0.93729         
         Pos Pred Value : 0.31200         
         Neg Pred Value : 0.99736         
             Prevalence : 0.02999         
         Detection Rate : 0.02759         
   Detection Prevalence : 0.08841         
      Balanced Accuracy : 0.92855         

       'Positive' Class : one 

我会说还不错。

如果调整预测的截止阈值,您可以做得更好,描述了如何在调整过程中执行此操作 here。您还可以使用折叠外预测来调整截止阈值。在这里我将展示如何使用 pROC 库:

library(pROC)

plot(roc(xgb.mod$pred$obs, xgb.mod$pred$one),
     print.thres = TRUE)

图像上显示的阈值最大化 Sens + Spec:

使用此阈值评估折叠性能:

caret::confusionMatrix(ifelse(xgb.mod$pred$one > 0.369, "one", "zero"),
                       xgb.mod$pred$obs)
#output
Confusion Matrix and Statistics

          Reference
Prediction  one zero
      one   200  596
      zero   12 6261

               Accuracy : 0.914           
                 95% CI : (0.9072, 0.9204)
    No Information Rate : 0.97            
    P-Value [Acc > NIR] : 1               

                  Kappa : 0.3668          
 Mcnemar's Test P-Value : <2e-16          

            Sensitivity : 0.94340         
            Specificity : 0.91308         
         Pos Pred Value : 0.25126         
         Neg Pred Value : 0.99809         
             Prevalence : 0.02999         
         Detection Rate : 0.02829         
   Detection Prevalence : 0.11260         
      Balanced Accuracy : 0.92824         

       'Positive' Class : one 

因此,在 212 个非零实体中,您检测到 200 个。

为了更好地执行,您可以尝试预处理数据。或者使用更好的超参数搜索例程,如 mlrMBO package intended for use with mlr。或者也许改变学习者(我怀疑你能在这里超越 xgboost)。

请注意,如果获得高灵敏度不是最重要的,也许使用 "Kappa" 作为选择指标可能会提供更令人满意的模型。

作为最后的说明,让我们使用已选择的参数检查默认 scale_pos_weight = 1 模型的性能:

set.seed(1)
xgb.mod2 <- train(Vote_perc~.,
                  data = forkfold, 
                  trControl = train_control, 
                  method = "xgbTree", 
                  tuneGrid = data.frame(nrounds = 498,
                                        max_depth = 3,
                                        eta = 0.008833468,
                                        gamma = 4.131242,
                                        colsample_bytree = 0.4233169,
                                        min_child_weight = 3,
                                        subsample = 0.6212512),
                  metric = "Dist",
                  maximize = FALSE,
                  scale_pos_weight = 1)

caret::confusionMatrix(xgb.mod2$pred$pred, xgb.mod2$pred$obs)
#output
Confusion Matrix and Statistics

          Reference
Prediction  one zero
      one    94   21
      zero  118 6836

               Accuracy : 0.9803          
                 95% CI : (0.9768, 0.9834)
    No Information Rate : 0.97            
    P-Value [Acc > NIR] : 3.870e-08       

                  Kappa : 0.5658          
 Mcnemar's Test P-Value : 3.868e-16       

            Sensitivity : 0.44340         
            Specificity : 0.99694         
         Pos Pred Value : 0.81739         
         Neg Pred Value : 0.98303         
             Prevalence : 0.02999         
         Detection Rate : 0.01330         
   Detection Prevalence : 0.01627         
      Balanced Accuracy : 0.72017         

       'Positive' Class : one  

在默认阈值 0.5 下更糟。

最佳阈值:

plot(roc(xgb.mod2$pred$obs, xgb.mod2$pred$one),
     print.thres = TRUE)

0.037 与我们按照建议设置 scale_pos_weight 时获得的 0.369 相比。然而,在最佳阈值的情况下,两种方法都会产生相同的预测。