Как рассчитать среднюю чувствительность и специфичность при указанном пороге в пакете ROCR?

Я использую пакет ROCR для рисования кривой ROC. Код выглядит следующим образом:

pred <- prediction(my.pred, my.label)
perf <- performance(my.pred, 'tpr', 'fpr')
plot(perf,avg="threshold")

Мой объект pred и perf — это не вектор, а список, поэтому я могу получить среднюю кривую ROC. Может ли кто-нибудь сказать мне, как рассчитать среднюю чувствительность и специфичность при указанном пороге в упаковке ROCR?


r roc
person user22062    schedule 25.08.2013    source источник
comment
Такой подход полностью противоречит принятию оптимальных решений, в которых используются предсказанные риски и функции полезности.   -  person Frank Harrell    schedule 25.08.2013


Ответы (1)


На самом деле, ROCR — это перебор для этой задачи. Функция performance функции ROCR возвращает показатели производительности для каждой оценки, присутствующей во входных данных. Итак, теоретически вы можете сделать следующее:

library(ROCR)
set.seed(123)
N <- 1000
POSITIVE_CASE <- 'case A'
NEGATIVE_CASE <- 'case B'
CUTOFF <- 0.456

scores <- rnorm(n=N)
labels <- ifelse(runif(N) > 0.5, POSITIVE_CASE, NEGATIVE_CASE)



pred <- prediction(scores, labels)
perf <- performance(pred, 'sens', 'spec')

На данный момент perf содержит много полезной информации:

  > str(perf)
  Formal class 'performance' [package "ROCR"] with 6 slots
  ..@ x.name      : chr "Specificity"
  ..@ y.name      : chr "Sensitivity"
  ..@ alpha.name  : chr "Cutoff"
  ..@ x.values    :List of 1
  .. ..$ : num [1:1001] 1 1 0.998 0.996 0.996 ...
  ..@ y.values    :List of 1
  .. ..$ : num [1:1001] 0 0.00202 0.00202 0.00202 0.00405 ...
  ..@ alpha.values:List of 1
  .. ..$ : num [1:1001] Inf 3.24 2.69 2.68 2.58 ...

Теперь вы можете найти пороговое значение оценки в [email protected] и найти соответствующие значения чувствительности и специфичности. Если вы не найдете точное значение отсечки в [email protected], вам придется выполнить некоторую интерполяцию:

ix <- which.min(abs([email protected][[1]] - CUTOFF)) #good enough in our case
sensitivity <- [email protected][[1]][ix] #note the order of arguments to `perfomance` and of x and y in `perf`
specificity <- [email protected][[1]][ix]

Что дает вам:

> sensitivity
[1] 0.3319838
> specificity
[1] 0.6956522

Но есть гораздо более простой и быстрый способ: просто преобразуйте строку метки в двоичный вектор и вычислите показатели напрямую:

binary.labels <- labels == POSITIVE_CASE
tp <- sum( (scores > threshold) & binary.labels )
sensitivity <- tp / sum(binary.labels)
tn <- sum( (scores <= threshold) & (! binary.labels))
specificity <- tn / sum(!binary.labels)

Что дает вам:

> sensitivity
[1] 0.3319838
> specificity
[1] 0.6956522
person Boris Gorelik    schedule 20.11.2013