You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于XGBoost的堆叠集成学习函数报错排查求助

堆叠集成模型错误排查与修正

错误根源分析

出现assert_factor(truth, min.len = 1L, n.levels = 2L, any.missing = FALSE) : argument "truth" is missing, with no default错误,核心原因有三点:

  • 目标列名称不匹配:训练集样例的目标列是target,但代码中创建任务时指定的目标是CR,导致任务无法识别真实标签,后续训练流程缺失truth参数。
  • 自定义度量命名冲突:自定义AUC度量的函数名和pROC包的auc函数重名,导致内部调用时逻辑混乱。
  • 元学习器参数冗余:makeStackedLearner的metalearner.control重复设置ntree,和之前给meta_lrn设置的参数冲突。

代码修正步骤

  1. 修正目标列名称:将创建任务时的target参数改为训练集实际的目标列名"target"
  2. 重命名自定义AUC度量:把自定义度量的id和函数名改为custom_auc,避免和pROC::auc冲突
  3. 移除冗余参数设置:删除stack_learner$par.vals中重复的ntree设置
  4. 统一测试集目标列处理:确保测试集的目标列名称与训练集一致

完整修正代码

super_train <- function(data_list, n_models = 10, cpus = 32) {
  # Prepare data
  train <- data_list[[1]]
  test <- data_list[[2]]
  train[,1] <- factor(train[,1])
  test[,1] <- factor(test[,1])
  # 修正目标列名称为实际的"target"
  task <- makeClassifTask(data = train, target = "target")
  print(task$type)
  
  # Create base learners
  base_learners <- list()
  for (i in 1:n_models) {
    ctrl <- makeTuneControlMBO()
    lrn <- makeLearner("classif.xgboost", predict.type = "prob")
    ps <- makeParamSet(
      makeDiscreteParam("booster", values = c("gbtree", "gblinear")), 
      makeNumericParam("eta", lower = 0.01, upper = 0.08), 
      makeIntegerParam("max_depth", lower = 2L, upper = 11L), 
      makeNumericParam("alpha", lower = 0L, upper = 8),
      makeNumericParam("lambda", lower = 0L, upper = 8),
      makeNumericParam("gamma", lower = 0L, upper = 8),
      makeNumericParam("min_child_weight", lower = 2L, upper = 8L), 
      makeNumericParam("subsample", lower = 0.5, upper = 1), 
      makeNumericParam("colsample_bytree", lower = 0.5, upper = 1),
      makeNumericParam("scale_pos_weight", lower = 1, upper = 10)
    )
    
    # 重命名自定义AUC度量,避免和pROC::auc冲突
    custom_auc <- makeMeasure(id = "custom_classif.auc", name = "Area under ROC curve", minimize = FALSE,
                       fun = function(truth, pred, lev = NULL, model = NULL) {
                         require(pROC)
                         response <- factor(truth, levels = lev)
                         prediction <- pred[, lev[2]]
                         roc_obj <- roc(response, prediction)
                         auc_obj <- pROC::auc(roc_obj) # 明确指定pROC::auc避免混淆
                         return(auc_obj)
                       })
    
    resampling_desc <- makeResampleDesc("CV", iters = 10)
    res <- tuneParams(lrn, task, resampling = resampling_desc, measures = list(custom_auc),
                      par.set = ps, control = ctrl)
    
    base_learners[[i]] <- res$learner
  }
  
  # Create meta-learner
  meta_lrn <- makeLearner("classif.randomForest", predict.type = "prob")
  meta_lrn$par.vals <- list(ntree = 100, mtry = sqrt(ncol(train)-1), importance = TRUE) # 减去目标列,避免mtry计算错误
  
  # Create stacked ensemble - 移除冗余的metalearner.control设置
  stack_learner <- makeStackedLearner(base_learners, metalearner = meta_lrn)
  
  # Train stacked ensemble
  stack_model <- train(stack_learner, task)
  
  # Evaluate on test set
  test_pred <- predict(stack_model, newdata = test)$data
  
  return(list(stack_model = stack_model, test_pred = test_pred))
}  

测试调用示例

使用提供的训练集样例进行测试:

# 构造数据列表(假设测试集和训练集结构一致)
train_data <- structure(list(target = structure(c(1L, 2L, 1L, 2L, 1L, 1L, 2L, 2L, 
1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L), levels = c("0", 
"1"), class = "factor"), Bone = c(0.68, 0.82, 0.6, 0.63, 
0.5, 0.72, 0.66, 0.58, 0.6, 0.6, 0.56, 0.7, 0.59, 0.55, 0.47, 
0.6, 0.64, 0.67, 0.62, 0.59), Blood = c(0.54, 0.65, 0.48, 
0.54, 0.22, 0.58, 0.51, 0.38, 0.46, 0.42, 0.3, 0.62, 0.4, 0.29, 
0.2, 0.48, 0.54, 0.55, 0.37, 0.46), Skin = c(0.77, 0.83, 
0.74, 0.75, 0.75, 0.78, 0.75, 0.76, 0.76, 0.76, 0.75, 0.76, 0.76, 
0.75, 0.74, 0.75, 0.76, 0.75, 0.75, 0.74), Brain = c(0.51, 
0.59, 0.46, 0.5, 0.33, 0.56, 0.49, 0.39, 0.45, 0.46, 0.37, 0.57, 
0.43, 0.37, 0.32, 0.47, 0.48, 0.55, 0.43, 0.47), Liver = c(0.58, 
0.62, 0.55, 0.58, 0.48, 0.58, 0.62, 0.5, 0.51, 0.55, 0.53, 0.65, 
0.54, 0.48, 0.46, 0.57, 0.57, 0.65, 0.59, 0.59), Stomach = c(0.58, 
0.65, 0.54, 0.59, 0.5, 0.61, 0.6, 0.51, 0.51, 0.55, 0.56, 0.61, 
0.55, 0.51, 0.47, 0.59, 0.55, 0.63, 0.57, 0.59), Heart = c(0.62, 
0.66, 0.55, 0.61, 0.44, 0.63, 0.58, 0.51, 0.55, 0.55, 0.46, 0.66, 
0.53, 0.47, 0.41, 0.56, 0.57, 0.64, 0.51, 0.56), T.cells = c(0.53, 
0.75, 0.5, 0.51, 0.47, 0.66, 0.52, 0.52, 0.53, 0.54, 0.47, 0.56, 
0.49, 0.48, 0.45, 0.51, 0.52, 0.55, 0.52, 0.53), B.cells = c(0.52, 
0.81, 0.46, 0.47, 0.39, 0.7, 0.49, 0.47, 0.5, 0.54, 0.41, 0.54, 
0.44, 0.43, 0.37, 0.48, 0.49, 0.53, 0.48, 0.52)), row.names = c("Pt1", 
"Pta101", "Pta106", "Ptc11", "Ptc17", "Ptc18", "Ptb2", "Ptm26", "Ptm28", 
"Pta29", "Pta3", "Pta34", "Ptb37", "Ptb38", "Ptb39", "Ptb4", "Ptc44", 
"Ptc46", "Ptb47", "Pta48"), class = "data.frame")

# 这里用训练集作为测试集示例,实际应替换为真实测试数据
data_list <- list(train_data, train_data)

# 调用函数(n_models设为2加快测试)
result <- super_train(data_list, n_models = 2)

额外优化说明

  • 元学习器的mtry参数计算时减去了目标列,避免包含标签列导致参数错误
  • 自定义AUC度量中明确指定pROC::auc,彻底消除命名冲突
  • 返回值增加了测试集预测结果,方便后续评估

内容的提问来源于stack exchange,提问作者Programming Noob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 07:07:01