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

mlr3中ROC曲线提取标准差/95%CI及绘图定制技术问询

关于mlr3嵌套交叉验证基准测试的三个问题

我需要提取多模型在任务基准测试中结果的标准差和/或95%置信区间(95%CI),保证结果完整性。之前查过mlr3 k折交叉验证的标准差提取方法,但不确定后续是否有新实现。以下是我的代码、基准测试(bmr)结果及绘图:

代码实现

resampling_outer = rsmp("cv", folds = 5)
resampling_inner = rsmp("cv", folds = 3)

set.seed(372)
resampling_outer$instantiate(task_wilcox)
resampling_inner$instantiate(task_wilcox)

at_xgboost = auto_tuner(tuner=tnr("mbo"), learner = xgboost,resampling = resampling_inner, measure = msr("classif.auc"),term_evals = 20,store_tuning_instance = TRUE,store_models = TRUE)
at_ranger = auto_tuner(tuner=tnr("mbo"), learner = ranger,resampling = resampling_inner, measure = msr("classif.auc"),term_evals = 20,store_tuning_instance = TRUE,store_models = TRUE)
at_svm = auto_tuner(tuner=tnr("mbo"), learner = svm,resampling = resampling_inner, measure = msr("classif.auc"),term_evals = 20,store_tuning_instance = TRUE,store_models = TRUE)
at_knn = auto_tuner(tuner=tnr("mbo"), learner = knn,resampling = resampling_inner, measure = msr("classif.auc"),term_evals = 20,store_tuning_instance = TRUE,store_models = TRUE)

learners <- c(at_xgboost, at_svm, at_ranger, at_knn)

measures = msrs(c("classif.auc", "classif.bacc", "classif.bbrier"))

# Benchmarking
set.seed(372)
design = benchmark_grid(tasks = task_wilcox, learners = learners, resamplings = resampling_outer)
bmr = benchmark(design, store_models = TRUE)
results <- bmr$aggregate(measures)
print(results)
autoplot(bmr, measure = msr("classif.auc"))
autoplot(bmr, type = "roc")

绘图结果

AUC箱线图

箱线图结果

ROC曲线

ROC曲线结果

输出结果

聚合结果(results)

nr     task_id                learner_id resampling_id iters classif.auc classif.bacc classif.bbrier
1:  1 data_wilcox       scale.xgboost.tuned            cv     5   0.6112939    0.5767294      0.2326787
2:  2 data_wilcox           scale.svm.tuned            cv     5   0.5226407    0.5010260      0.1893202
3:  3 data_wilcox scale.random_forest.tuned            cv     5   0.6200084    0.5614843      0.2229120
4:  4 data_wilcox           scale.knn.tuned            cv     5   0.5731675    0.5002955      0.1917721

内层调优结果

extract_inner_tuning_results(bmr)[,list(learner_id, classif.auc)]
                   learner_id classif.auc
 1:       scale.xgboost.tuned   0.6231350
 2:       scale.xgboost.tuned   0.6207103
 3:       scale.xgboost.tuned   0.6175323
 4:       scale.xgboost.tuned   0.6195693
 5:       scale.xgboost.tuned   0.6222398
 6:           scale.svm.tuned   0.5891432
 7:           scale.svm.tuned   0.5837583
 8:           scale.svm.tuned   0.5767444
 9:           scale.svm.tuned   0.6027165
10:           scale.svm.tuned   0.6082825
11: scale.random_forest.tuned   0.6287649
12: scale.random_forest.tuned   0.6165179
13: scale.random_forest.tuned   0.6288599
14: scale.random_forest.tuned   0.6259322
15: scale.random_forest.tuned   0.6234295
16:           scale.knn.tuned   0.5931790
17:           scale.knn.tuned   0.5926835
18:           scale.knn.tuned   0.5931790
19:           scale.knn.tuned   0.5929156
20:           scale.knn.tuned   0.5929156

问题

  1. ROC曲线上的彩色透明边际是标准差/置信区间,但不知道如何提取这些数据;推测需要从外层重采样结果提取,但暂无直接方法。
  2. 每个模型AUC的箱线图构建依据是什么?结果似乎和外层循环(resampling_outer)的测试集结果不符。
  3. 如何在mlr3中定制ROC曲线?比如添加AUC值、移除曲线边际等。

问题解答

1. 提取标准差/95%置信区间数据

ROC曲线的边际是外层5折交叉验证中每折ROC曲线的置信区间,要提取这些数据,需按以下步骤操作:

步骤1:获取外层每折的预测结果

# 提取所有外层重采样的预测数据
preds = bmr$score()$prediction

# 按学习者分组,拆分每折的预测
preds_list = split(preds, preds$learner_id)

步骤2:计算每折的ROC曲线点

library(precrec)

# 定义函数计算单折ROC数据
compute_roc = function(pred) {
  roc_obj = evalmod(scores = pred$prob[,2], labels = pred$truth)
  return(data.frame(
    fpr = roc_obj$curves[[1]]$x,
    tpr = roc_obj$curves[[1]]$y,
    learner = pred$learner_id[1]
  ))
}

# 计算所有折的ROC数据
all_roc_data = lapply(preds_list, function(learner_preds) {
  do.call(rbind, lapply(learner_preds, compute_roc))
})
all_roc_data = do.call(rbind, all_roc_data)

步骤3:计算标准差/95%置信区间

library(data.table)
setDT(all_roc_data)

# 按学习者和FPR分组,计算TPR的均值、标准差和95%CI
roc_stats = all_roc_data[, .(
  tpr_mean = mean(tpr),
  tpr_sd = sd(tpr),
  tpr_lower = quantile(tpr, 0.025),
  tpr_upper = quantile(tpr, 0.975)
), by = .(learner, fpr)]

roc_stats中包含了每个学习者在不同FPR下TPR的均值、标准差和95%置信区间,与ROC图里的边际完全对应。

如果要提取外层验证指标(如AUC)的标准差,直接从bmr$score()结果计算即可:

score_data = bmr$score(measures = msr("classif.auc"))
auc_stats = score_data[, .(
  auc_mean = mean(classif.auc),
  auc_sd = sd(classif.auc),
  auc_ci_lower = quantile(classif.auc, 0.025),
  auc_ci_upper = quantile(classif.auc, 0.975)
), by = learner_id]

2. AUC箱线图的构建依据

默认的AUC箱线图不是外层交叉验证的测试集结果,而是内层调优过程中产生的性能数据:

  • 每个外层折会运行一次内层3折调优(你设置了20次MBO迭代),每次迭代会评估内层3折的AUC均值
  • autoplot(bmr, measure = msr("classif.auc"))默认展示的是所有调优迭代的AUC分布,也就是每个学习者对应5个外层折 × 20次迭代 = 100个AUC值

如果想要绘制外层测试集的AUC箱线图,需要手动提取数据绘图:

library(ggplot2)
score_data = bmr$score(msr("classif.auc"))
ggplot(score_data, aes(x = learner_id, y = classif.auc)) +
  geom_boxplot() +
  labs(title = "外层交叉验证AUC箱线图", x = "模型", y = "AUC")

3. 定制ROC曲线

mlr3的autoplot基于ggplot2,可通过修改ggplot对象实现各种定制:

移除曲线边际(置信区间)

直接在autoplot中设置se = FALSE:

autoplot(bmr, type = "roc", se = FALSE)

添加AUC值

先计算每个模型的AUC均值,再通过annotate添加标签:

# 计算每个模型的AUC均值
auc_means = bmr$aggregate(msr("classif.auc"))[, .(learner_id, classif.auc)]

# 绘制ROC曲线并添加AUC标签
p = autoplot(bmr, type = "roc")
for (i in 1:nrow(auc_means)) {
  p = p + annotate("text", x = 0.7, y = 0.3 - (i-1)*0.1, 
                   label = paste0(auc_means$learner_id[i], "\nAUC: ", round(auc_means$classif.auc[i], 3)),
                   color = scales::hue_pal()(nrow(auc_means))[i])
}
print(p)

其他定制(主题、颜色、标题等)

直接使用ggplot2的函数扩展:

p = autoplot(bmr, type = "roc", se = FALSE) +
  ggtitle("定制ROC曲线") +
  xlab("假阳性率(FPR)") +
  ylab("真阳性率(TPR)") +
  theme_minimal() +
  scale_color_brewer(palette = "Set1")
print(p)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 08:32:02