从数据框中手动创建 ROC 曲线
Posted
技术标签:
【中文标题】从数据框中手动创建 ROC 曲线【英文标题】:Create ROC curve manually from data frame 【发布时间】:2021-11-09 08:27:02 【问题描述】:我有以下概念性问题,我无法理解。
以下是调查数据示例,其中我有一个时间列,指示某人需要多长时间才能回答某个问题。
现在,我感兴趣的是清洁量将如何根据此阈值发生变化,即如果我增加阈值会发生什么,如果我降低它会发生什么。
所以我的想法是创建一条 ROC 曲线(或其他模型指标),以获得关于潜在阈值的视觉提示。问题是我没有类似机器学习的模型来给我分类概率。所以我想知道是否有任何方法可以使用这种类型的数据创建 ROC 曲线。我的想法是在大约 100 个不同的阈值处循环遍历我的数据,计算每个阈值的假阳性率和真阳性率,然后做一个简单的线图,但我希望有一个更优雅的解决方案,不需要我循环.
有什么想法吗?
示例数据:
time
列表示每个案例所需的时间
truth
列表示我想要比较的当前决定
predicted
列表示我是否会在时间阈值2.5s
进行切割时的清洁决定。这是我需要更改/循环的内容。
set.seed(3)
df <- data.frame(time = c(2.5 + rnorm(5), 3.5 + rnorm(5)),
truth = rep(c("cleaned", "final"), each = 5)) %>%
mutate(predicted = if_else(time < 2.5, "cleaned", "final"))
【问题讨论】:
因为您需要计算每个阈值的 ROC 点,所以除了循环的某些变体之外,我没有看到其他选择。 【参考方案1】:所以我的想法是创建一条 ROC 曲线
创建 ROC 曲线很简单
library(pROC)
set.seed(3)
data.frame(time = c(2.5 + rnorm(5), 3.5 + rnorm(5)),
truth = rep(c("cleaned", "final"), each = 5)) |>
roc(truth, time) |>
plot()
问题是我没有类似机器学习的模型来提供类概率。
抱歉,我不明白这个问题是什么机器学习。
我的想法是在大约 100 个不同的阈值处循环遍历我的数据
如果您有 10 个观察值,则循环超过 100 个可能的阈值是没有意义的。合理的截止值是位于您的time
值之间的九个。你可以从roc
得到那些:
df <- data.frame(time = c(2.5 + rnorm(5), 3.5 + rnorm(5)),
truth = rep(c("cleaned", "final"), each = 5))
thresholds <- roc(df, truth, time)$thresholds
print(thresholds)
或
> print(thresholds)
[1] -Inf 1.195612 1.739608 1.968531 2.155908 2.329745 2.561073
[8] 3.093424 3.969994 4.586341 Inf
“循环”一词的确切含义以及您是否只想排除 for
和 while
循环或您认为是循环的任何内容都需要一些精确的定义。 c(1, 2, 3, 4) * 5
是循环吗?引擎盖下会有一个循环运行。
【讨论】:
有趣。但是,我有点惊讶该函数如何确定不同阈值的清理/最终类,即预测类。该函数没有关于做什么的任何信息,例如在阈值 1.968531(阈值示例中的第 4 个值)。 至于数据本身,只是一个例子,有10个案例。在现实生活中可能是100k。对于“类似机器学习”,我的意思是我需要将真实情况与某个预测的“类”进行比较,这通常在机器学习的训练/测试设置中完成。 ROC 隐含预测方法:如果我们假设低于阈值的值为cleaned
,高于阈值的值为final
,那么给定样本内的敏感性和特异性是多少。为每个可能的阈值画一条线。 @Shibaprasadb 使用的函数甚至对沿线的阈值进行颜色编码。将数据划分为训练和测试数据集并不是 ROC 固有的。那是你最初想做的吗?
“函数如何确定不同阈值下的清理/最终类”完全由 ROC 算法定义。
感谢您的回复(尽管我接受了另一个带有 ROCR 包的回复)。我还看到我对包将如何确定预测类别的概念误解。所以我猜它只是使用数字时间列并在不同的位置进行切割,并假设“真相”列的设置方式是它只“清理”低于某个阈值而其他一切都是“最终的”,那么它可以只需计算如果阈值发生变化会发生什么。【参考方案2】:
您也可以为此使用ROCR
library(ROCR)
set.seed(3)
df <- data.frame(time = c(2.5 + rnorm(5), 3.5 + rnorm(5)),
truth = rep(c("cleaned", "final"), each = 5)) %>%
mutate(predicted = if_else(time < 2.5, "cleaned", "final"))
pred <- prediction(df$time, df$truth)
perf <- performance(pred,"tpr","fpr")
plot(perf,colorize=TRUE)
您也可以查看AUC值:
auc <- performance(pred, measure = "auc")
auc@y.values[[1]]
[1] 0.92
与pROC
交叉检查AUC值
library(pROC)
roc(df$truth, df$time)
Call:
roc.default(response = df$truth, predictor = df$time)
Data: df$time in 5 controls (df$truth cleaned) < 5 cases (df$truth final).
Area under the curve: 0.92
这两种情况都是一样的!
【讨论】:
感谢您的回答。我喜欢 ROCR 包的 plot 版本,所以我会接受这是我的首选答案,尽管我通常喜欢是否可以在 tidyverse 管道中调用包函数(而且我还没有设法将 pred/perf 计算放入我的烟斗。以上是关于从数据框中手动创建 ROC 曲线的主要内容,如果未能解决你的问题,请参考以下文章