无需模型概率输出 基于数据框手动生成ROC曲线的实现方法
首先明确:你的场景完全可以生成ROC曲线。ROC的本质是所有可实现的二分类阈值对应的真阳性率(TPR)、假阳性率(FPR)的连线,只需要有一个可用于排序的连续指标(这里就是time字段)和真实标签即可,不需要机器学习模型输出的概率。
不需要手动写循环遍历阈值,R生态有成熟的实现方案,也可以用tidyverse的向量化操作完成,两种常用方案如下:
方案1:使用pROC包(最简便)
pROC是专门用于ROC分析的包,内部已经封装了阈值计算、指标统计的逻辑,一行代码即可完成计算:
library(pROC) library(dplyr) # 你的示例数据,不需要提前生成predicted字段 set.seed(3) df <- data.frame( time = c(2.5 + rnorm(5), 3.5 + rnorm(5)), truth = rep(c("cleaned", "final"), each = 5) ) # 直接计算ROC对象 # levels参数:第一个为阴性类,第二个为阳性类 # direction="<"表示预测指标(time)的值越小,越可能属于阳性类(cleaned) roc_obj <- roc(truth ~ time, data = df, levels = c("final", "cleaned"), direction = "<") # 直接绘制带AUC和推荐阈值的ROC图 plot(roc_obj, print.auc = TRUE, print.thres = TRUE)
如果需要提取各阈值对应的指标,可以直接从生成的roc_obj中取:
- 所有阈值:
roc_obj$thresholds - 对应TPR:
roc_obj$sensitivities - 对应特异度:
roc_obj$specificities,FPR = 1 - 特异度
方案2:tidyverse向量化实现(无额外ROC包依赖)
如果不想引入第三方ROC包,用dplyr的向量化操作也可以完成计算,完全不需要循环:
library(dplyr) library(ggplot2) roc_df <- df %>% # 按耗时从小到大排序,每一行对应一个阈值(当前行的time值) arrange(time) %>% mutate( total_pos = sum(truth == "cleaned"), total_neg = sum(truth == "final"), # 累积统计当前阈值下的阳性、阴性分类数量 cum_pos = cumsum(truth == "cleaned"), cum_neg = cumsum(truth == "final"), # 计算TPR和FPR tpr = cum_pos / total_pos, fpr = cum_neg / total_neg ) # 绘制ROC曲线 ggplot(roc_df, aes(x = fpr, y = tpr)) + geom_line(linewidth = 1) + geom_abline(slope = 1, intercept = 0, linetype = "dashed", color = "gray50") + labs(x = "假阳性率 (FPR)", y = "真阳性率 (TPR)", title = "响应耗时阈值ROC曲线") + theme_minimal()
补充说明:不需要手动生成100个测试阈值,所有能改变分类结果的阈值就是每个样本的time值,中间插值的阈值不会改变分类结果,直接用样本的time值作为阈值点既准确又高效。
内容的提问来源于stack exchange,提问作者deschen
相关产品推荐
相关产品推荐

