【问题标题】:xgboost always predict 1 level with imbalance datasetxgboost 总是使用不平衡数据集预测 1 级
【发布时间】:2018-03-27 06:46:23
【问题描述】:

我正在使用 xgboost 构建模型。数据集只有 200 行和 10000 列。

我尝试 chi-2 得到 100 列,但我的混淆矩阵如下所示:

    1 0
1 190 0
0  10 0

我尝试使用 10000 个属性,随机选择 100 个属性,根据 chi-2 选择 100 个属性,但我从来没有得到 0 案例预测。是因为数据集,还是因为我使用 xgboost 的方式?

我的 factor(pred.cv) 总是只显示 1 个级别,而 factor(y+1) 有 1 或 2 个级别。

param <- list("objective" = "binary:logistic",
          "eval_metric" = "error",
          "nthread" = 2,
          "max_depth" = 5,
          "eta" = 0.3,
          "gamma" = 0,
          "subsample" = 0.8,
          "colsample_bytree" = 0.8,
          "min_child_weight" = 1,
          "max_delta_step"= 5,
          "learning_rate" =0.1,
          "n_estimators" = 1000,
          "seed"=27,
          "scale_pos_weight" = 1
          )
nfold=3
nrounds=200
pred.cv = matrix(bst.cv$pred, nrow=length(bst.cv$pred)/1, ncol=1)
pred.cv = max.col(pred.cv, "last")
factor(y+1) # this is the target in train, level 1 and 2
factor(pred.cv) # this is the issue, it is always only 1 level

【问题讨论】:

  • 因子(y+1)中1/2水平的比例是多少?如果不平衡,可以尝试更改 scale_pos_weight。
  • @missuse 只有 10%,我先试试!
  • @missuse 我想我有一些线索。从网上说要这样做:“pred.cv = matrix(bst.cv$pred, nrow=length(bst.cv$pred)/num.class, ncol=num.class)”,但是当我这样做时, num.class= 2,我的confusionMatrix(factor(y+1), factor(pred.cv)) 返回错误“所有参数必须具有相同的长度”。因为 factor(y+1) 是 980,但是 factor(pred.cv) 是 980/2。你知道怎么解决吗?
  • 试试pred.cv = ifelse(bst$pred &lt; 0.5, 0, 1)table(pred.cv, y)
  • @missuse 我实际上在 5 分钟前就知道了,我没有转换概率。是或否:/谢谢!

标签: r xgboost


【解决方案1】:

我发现插入符号很慢,并且它无法在不构建自定义模型的情况下调整 xgboost 模型的所有参数,这比使用自己的自定义函数进行评估要复杂得多。

但是,如果您要进行一些向上/向下采样或 smote/rose 插入符号,则可以采用这种方式,因为它可以在模型评估阶段(在重新采样期间)正确地合并它们。见:https://topepo.github.io/caret/subsampling-for-class-imbalances.html

但是,我发现这些技术对结果的影响非常小,而且通常情况更糟,至少在我训练的模型中是这样。

scale_pos_weight 赋予某个类更高的权重,如果少数类的丰度为 10%,那么在5 - 10 周围使用scale_pos_weight 应该是有益的。

调整正则化参数对 xgboost 非常有益:这里有几个参数:alphabetagamma - 我发现有效值是 0 - 3。添加直接正则化的其他有用参数(通过添加不确定性)是subsamplecolsample_bytreecolsample_bylevel。我发现使用colsample_bylevel 也可以对模型产生积极的影响。 subsamplecolsample_bytree 你已经在使用了。

我会测试一个更小的 eta 和更多的树,看看模型是否有好处。在这种情况下,early_stopping_rounds 轮次可以加快进程。

其他eval_metric 可能会比准确性更有益。试试loglossauc 甚至mapndcg

这是一个超参数网格搜索的功能。它使用auc 作为评估指标,但可以轻松更改

xgb.par.opt=function(train, seed){
  require(xgboost)
  ntrees=2000
  searchGridSubCol <- expand.grid(subsample = c(0.5, 0.75, 1), 
                                  colsample_bytree = c(0.6, 0.8, 1),
                                  gamma = c(0, 1, 2),
                                  eta = c(0.01, 0.03),
                                  max_depth = c(4,6,8,10))
  aucErrorsHyperparameters <- apply(searchGridSubCol, 1, function(parameterList){

    #Extract Parameters to test
    currentSubsampleRate <- parameterList[["subsample"]]
    currentColsampleRate <- parameterList[["colsample_bytree"]]
    currentGamma <- parameterList[["gamma"]]
    currentEta =parameterList[["eta"]]
    currentMaxDepth =parameterList[["max_depth"]]
    set.seed(seed)

    xgboostModelCV <- xgb.cv(data = train, 
                             nrounds = ntrees,
                             nfold = 5,
                             objective = "binary:logistic",
                             eval_metric= "auc",
                             metrics = "auc",
                             verbose = 1,
                             print_every_n = 50,
                             early_stopping_rounds = 200,
                             stratified = T,
                             scale_pos_weight=sum(all_data[train,1]==0)/sum(all_data[train,1]==1),
                             max_depth = currentMaxDepth, 
                             eta = currentEta, 
                             gamma = currentGamma,
                             colsample_bytree = currentColsampleRate,
                             min_child_weight = 1,
                             subsample =  currentSubsampleRate
                             seed = seed) 


    xvalidationScores <- as.data.frame(xgboostModelCV$evaluation_log)

    auc = xvalidationScores[xvalidationScores$iter==xgboostModelCV$best_iteration,c(1,4,5)]
    auc = cbind(auc, currentSubsampleRate, currentColsampleRate, currentGamma, currentEta,  currentMaxDepth)
    names(auc) = c("iter", "test.auc.mean", "test.auc.std", "subsample", "colsample", "gamma", "eta", "max.depth")
    print(auc)
    return(auc)
  })
  return(aucErrorsHyperparameters)
}

可以在expand.grid 调用中添加其他参数。

我通常在一个 CV 重复上训练超参数,并在使用其他种子或验证集的额外重复上评估它们(但在验证集上执行此操作应谨慎使用以避免过度拟合)

【讨论】:

    【解决方案2】:

    测试

    param <- list("objective" = "binary:logistic",
          "eval_metric" = "error",
          "nthread" = 2,
          "max_depth" = 5,
          "eta" = 0.3,
          "gamma" = 0,
          "subsample" = 0.8,
          "colsample_bytree" = 0.8,
          "min_child_weight" = 1,
          "max_delta_step"= 5,
          "learning_rate" =0.1,
          "n_estimators" = 1000,
          "seed"=27,
          "scale_pos_weight" = 1
          )
    nfold=3
    nrounds=200
    pred.cv = matrix(bst.cv$pred, nrow=length(bst.cv$pred)/1, ncol=1)
    pred.cv = max.col(pred.cv, "last")
    factor(y+1) # this is the target in train, level 1 and 2
    factor(pred.cv) # this is the issue, it is always only 1 level
    

    【讨论】:

    • 如果问题中发布的内容与此答案之间存在差异,那么进行解释将非常有帮助。
    猜你喜欢
    • 2018-11-24
    • 2021-08-24
    • 2017-04-19
    • 2019-01-25
    • 2021-05-29
    • 2019-07-26
    • 2019-10-09
    • 2018-12-13
    • 1970-01-01
    相关资源
    最近更新 更多