如何在同一张图中绘制两个XGBoost模型的精美ROC曲线
问题解答
1. 获取ROC曲线所需的truth和Prediction Scores
- Truth(真实标签):
是对应数据集的目标特征标签,优先使用测试集的标签——用训练集标签绘制的ROC曲线会高估模型性能,无法反映泛化能力;如果只是观察训练集拟合效果,才用训练集的目标标签。 - Prediction Scores(预测分数/概率):
XGBoost模型需要输出连续的预测值(不是类别标签),获取方式分两种情况:- 原生
xgboost包训练的模型:# 假设test_data是测试集特征,test_labels是测试集真实标签 # 输出logit分数,可转换为概率 scores1 <- predict(model1, newdata = xgb.DMatrix(test_data)) scores1_prob <- 1 / (1 + exp(-scores1)) # 转换为正类概率 caret/mlr等封装包训练的模型:# 直接获取正类概率(第二列是类别1的概率) scores1 <- predict(model1, newdata = test_df, type = "prob")[,2] truth1 <- test_df$target_column # 测试集真实标签
- 原生
2. 代码修正与完整实现
现有代码的错误点
data.frame = (fpr = ...)语法错误,多了冗余的等号,正确写法是data.frame(fpr = ...)- 使用
geom_smooth会对ROC曲线做平滑拟合,导致曲线失真,ROC曲线应该用折线绘制 - 第一个
annotate("text")缺失y参数,第二个标注的字符串未闭合 - 缺少ROC图必备的随机猜测基准线(对角线)
修正后的完整代码
# 加载所需包 library(pROC) library(ggplot2) library(tibble) # ---------------------- # 第一步:获取truth和scores # ---------------------- # 示例:假设用caret训练模型,test_df是测试集,target列是y truth1 <- test_df$y scores1 <- predict(model1, newdata = test_df, type = "prob")[,2] truth2 <- test_df$y scores2 <- predict(model2, newdata = test_df, type = "prob")[,2] # ---------------------- # 第二步:计算ROC对象 # ---------------------- roc1 <- roc(truth1, scores1) roc2 <- roc(truth2, scores2) # ---------------------- # 第三步:转换为绘图用数据框 # ---------------------- D1 <- data.frame(fpr = 1 - roc1$specificities, tpr = roc1$sensitivities) D2 <- data.frame(fpr = 1 - roc2$specificities, tpr = roc2$sensitivities) # 箭头标注数据 arrows_df <- tibble(x1 = c(0.5, 0.13), x2 = c(0.32, 0.2), y1 = c(0.52, 0.83), y2 = c(0.7, 0.7)) # ---------------------- # 第四步:绘制ROC曲线 # ---------------------- ggplot() + # 添加随机猜测基准线(虚线) geom_abline(intercept = 0, slope = 1, color = "gray50", linetype = "dashed") + # 绘制两个模型的ROC折线 geom_line(data = D1, aes(x = fpr, y = tpr), color = "#1f77b4", linewidth = 1) + geom_line(data = D2, aes(x = fpr, y = tpr), color = "#ff4b5c", linewidth = 1) + # 绘制标注箭头 geom_segment(data = arrows_df, aes(x = x1, y = y1, xend = x2, yend = y2), arrow = arrow(length = unit(0.2, "cm")), color = "black") + # 添加AUC分数标注 annotate("text", x = 0.5, y = 0.475, label = paste0("Model 1 AUC: ", round(roc1$auc, 2))) + annotate("text", x = 0.13, y = 0.9, label = paste0("Model 2 AUC: ", round(roc2$auc, 2))) + # 图表标签与主题设置 labs(x = "False Positive Rate (FPR)", y = "True Positive Rate (TPR)", title = "ROC Curves: Model 1 vs Model 2") + theme_minimal() + theme(plot.title = element_text(hjust = 0.5, size = 14, face = "bold"), axis.title = element_text(size = 12), legend.position = "bottom")
代码说明
- 用
geom_line替代geom_smooth,保证ROC曲线是真实的阶梯状(如果需要平滑效果,可保留geom_smooth并设置method = "loess",但不推荐) - 添加了灰色虚线的基准线,用于对比模型与随机猜测的性能
- 标注中加入了AUC分数,直观展示模型性能
- 使用
theme_minimal优化图表样式,提升美观度
内容的提问来源于stack exchange,提问作者Kev
相关产品推荐
相关产品推荐

