使用caret+XGBoost处理不平衡数据集时遇重采样性能指标缺失问题
问题解决方案
核心错误排查
- 重复传递
classProbs参数:在trainControl和train函数中同时设置了classProbs=TRUE,导致参数冲突,直接触发formal argument "classProbs" matched by multiple actual arguments报错。 - 自定义F1函数存在两处错误:
- 正类标签不匹配:数据中阳性类别是
"one",但函数内写的是positive = "pass",导致精度、召回率无法计算,最终F1值全为NA。 - 参数拼写错误:计算召回率时的
postive应为positive。
- 正类标签不匹配:数据中阳性类别是
- 训练集索引逻辑错误:
(1:ind)[-vi]语法有误,正确的训练集索引应直接指定为1:700000。
修正后的完整代码
mytrainvalid <- read.csv("mytrainvalid.csv") library(xgboost) library(dplyr) library(caret) # 转换目标变量为因子类型 mytrainvalid$DEFAULT <- ifelse(mytrainvalid$DEFAULT != 0, "one", "zero") mytrainvalid$DEFAULT <- as.factor(mytrainvalid$DEFAULT) # 提取特征矩阵 input_x <- as.matrix(select(mytrainvalid, -DEFAULT)) # 明确划分训练/测试集索引 train_idx <- 1:700000 test_idx <- 700001:850000 # 修正后的F1评估函数 f1 <- function(data, lev = NULL, model = NULL) { # 基于实际阳性类别"one"计算精度和召回率 precision <- posPredValue(data$pred, data$obs, positive = "one") recall <- sensitivity(data$pred, data$obs, positive = "one") # 处理精度+召回率为0的边界情况,避免NaN f1_val <- ifelse(precision + recall == 0, 0, (2 * precision * recall) / (precision + recall)) names(f1_val) <- c("F1") f1_val } # 修正训练控制参数:移除重复的classProbs,调整索引设置 data.ctrl <- trainControl( method = "cv", number = 1, allowParallel = TRUE, returnData = FALSE, index = list(Fold1 = train_idx), sampling = "smote", classProbs = TRUE, summaryFunction = f1, savePredictions = "final", verboseIter = TRUE, search = "random" ) # 修正训练函数:移除重复的classProbs参数 xgb_model <- caret::train( input_x, mytrainvalid$DEFAULT, method = "xgbTree", trControl = data.ctrl, verbose = FALSE, metric = "F1", tuneLength = 2 )
额外优化提示
- 若仅需固定划分的训练/测试验证,可将
trainControl的method设为"none",无需走CV流程,提升运行效率。 - 若要使用自定义调参网格,取消注释
tuneGrid=grid_default,同时将search设为"grid",替代随机搜索。 - 对于极度不平衡的数据,除了SMOTE采样,还可尝试在XGBoost中设置
scale_pos_weight参数(计算方式为负类样本数/正类样本数),进一步优化模型偏向性。
内容的提问来源于stack exchange,提问作者ebrahimi
相关产品推荐
相关产品推荐

