Рассчитать AUC в R?

Имея вектор оценок и вектор фактических меток классов, как рассчитать одночисловую метрику AUC для бинарного классификатора на языке R или на простом английском языке?

Страница 9 "AUC: лучшая мера..." кажется требуют знания меток классов, и вот пример в MATLAB, где я не понимаю

R(Actual == 1))

Потому что R (не путать с языком R) определяется как вектор, но используется как функция?


person Andrew    schedule 04.02.2011    source источник
comment
Для всех, кто не знает, очевидно, что AUC — это площадь под рабочей характеристикой приемника   -  person Justin    schedule 05.02.2011


Ответы (11)


Как упоминалось другими, вы можете вычислить AUC с помощью пакета ROCR. С пакетом ROCR вы также можете построить кривую ROC, кривую подъема и другие параметры выбора модели.

Вы можете вычислить AUC напрямую, без использования какого-либо пакета, используя тот факт, что AUC равна вероятности того, что истинное положительное значение будет выше, чем истинно отрицательное.

Например, если pos.scores — это вектор, содержащий оценку положительных примеров, а neg.scores — это вектор, содержащий отрицательные примеры, то AUC аппроксимируется следующим образом:

> mean(sample(pos.scores,1000,replace=T) > sample(neg.scores,1000,replace=T))
[1] 0.7261

даст приблизительное значение AUC. Вы также можете оценить дисперсию AUC путем начальной загрузки:

> aucs = replicate(1000,mean(sample(pos.scores,1000,replace=T) > sample(neg.scores,1000,replace=T)))
person erik    schedule 05.02.2011
comment
Для моего набора тестовых данных ваше реплицированное значение очень похоже на значение @jonw (0,8504, ваше 0,850591), за исключением того, что мне не нужно устанавливать pROC. Спасибо - person Andrew; 07.02.2011
comment
@Andrew @eric Это ужасный ответ. Вы НЕ оцениваете дисперсию AUC — вы только оцениваете дисперсию процесса повторной выборки. Чтобы убедиться в этом, попробуйте изменить размер выборки в sample... разделите его на 10, ваша дисперсия умножится на 10. Умножьте на 10, и ваша дисперсия разделится на 10. Это определенно нежелательное поведение для вычисления дисперсии АУК. - person Calimo; 14.02.2014
comment
Кроме того, в ответе следует отметить, что оценка так же хороша, как и количество повторов. Перейдите к бесконечности, и вы получите фактический AUC. - person Calimo; 14.02.2014
comment
Согласитесь с @Calimo, это не бутстрап. Для начальной загрузки вам необходимо выполнить повторную выборку N точек данных с заменой M раз, где N — общий размер исходного набора данных, а M может быть любым (обычно пара сотен или более). N не является произвольным. Если N не установлен на полный размер набора данных, вы получите предвзятую статистику. - person Will High; 19.04.2014
comment
Я немного не понимаю показанный базовый метод R. Можно ли его рассчитать исключительно из матрицы путаницы? Какими будут pos.scores и neg.scores в контексте данной матрицы путаницы? - person Mobeus Zoom; 13.05.2020

Пакет ROCR рассчитает AUC среди других статистических данных:

auc.tmp <- performance(pred,"auc"); auc <- as.numeric([email protected])
person semaj    schedule 04.02.2011
comment
Я использовал ROCR для построения графиков производительности, но не понимаю, как он вычисляет показатель AUC с одним числом (из исходного вопроса). - person Andrew; 07.02.2011

С пакетом pROC вы можете использовать функцию auc(), как в этом примере со страницы справки:

> data(aSAH)
> 
> # Syntax (response, predictor):
> auc(aSAH$outcome, aSAH$s100b)
Area under the curve: 0.7314
person J. Win.    schedule 04.02.2011

Без дополнительных пакетов:

true_Y = c(1,1,1,1,2,1,2,1,2,2)
probs = c(1,0.999,0.999,0.973,0.568,0.421,0.382,0.377,0.146,0.11)

getROC_AUC = function(probs, true_Y){
    probsSort = sort(probs, decreasing = TRUE, index.return = TRUE)
    val = unlist(probsSort$x)
    idx = unlist(probsSort$ix)  

    roc_y = true_Y[idx];
    stack_x = cumsum(roc_y == 2)/sum(roc_y == 2)
    stack_y = cumsum(roc_y == 1)/sum(roc_y == 1)    

    auc = sum((stack_x[2:length(roc_y)]-stack_x[1:length(roc_y)-1])*stack_y[2:length(roc_y)])
    return(list(stack_x=stack_x, stack_y=stack_y, auc=auc))
}

aList = getROC_AUC(probs, true_Y) 

stack_x = unlist(aList$stack_x)
stack_y = unlist(aList$stack_y)
auc = unlist(aList$auc)

plot(stack_x, stack_y, type = "l", col = "blue", xlab = "False Positive Rate", ylab = "True Positive Rate", main = "ROC")
axis(1, seq(0.0,1.0,0.1))
axis(2, seq(0.0,1.0,0.1))
abline(h=seq(0.0,1.0,0.1), v=seq(0.0,1.0,0.1), col="gray", lty=3)
legend(0.7, 0.3, sprintf("%3.3f",auc), lty=c(1,1), lwd=c(2.5,2.5), col="blue", title = "AUC")

введите здесь описание изображения

person AGS    schedule 28.09.2013
comment
Если вы скопируете и вставите этот код и получите Error in plot.window(...) : need finite 'xlim' values, возможно, это потому, что ваши метки 0–1, а @AGS использует метки 1–2. - person gentimouton; 30.11.2013
comment
Это не дает истинного AUC, если два наблюдения имеют одинаковую вероятность, а порядок наблюдения не является случайным. В остальном хороший и быстрый код. - person MatthieuBizien; 13.01.2015
comment
Не знаю, почему это решение не работает с моими данными, мои проблемы не нормализованы, чтобы быть в пределах [0,1] - person Good Will; 18.06.2017

Я нашел некоторые решения здесь медленными и/или запутанными (а некоторые из них неправильно обрабатывают связи), поэтому я написал свою собственную функцию на основе data.table auc_roc() в моем пакете R mltools.

library(data.table)
library(mltools)

preds <- c(.1, .3, .3, .9)
actuals <- c(0, 0, 1, 1)

auc_roc(preds, actuals)  # 0.875

auc_roc(preds, actuals, returnDT=TRUE)
   Pred CountFalse CountTrue CumulativeFPR CumulativeTPR AdditionalArea CumulativeArea
1:  0.9          0         1           0.0           0.5          0.000          0.000
2:  0.3          1         1           0.5           1.0          0.375          0.375
3:  0.1          1         0           1.0           1.0          0.500          0.875
person Ben    schedule 19.09.2016
comment
Это решение намного быстрее, чем метод auc() в пакете pROC! Метод auc() в пакете pROC довольно медленный, если нужно вычислить оценки auc для задачи регрессии с несколькими классами или множественными выходами. - person Good Will; 18.06.2017

Вы можете узнать больше об AUROC в этой записи блога Мирона Курсы:

https://mbq.me/blog/augh-roc/

Он обеспечивает быструю функцию для AUROC:

# By Miron Kursa https://mbq.me
auroc <- function(score, bool) {
  n1 <- sum(!bool)
  n2 <- sum(bool)
  U  <- sum(rank(score)[!bool]) - n1 * (n1 + 1) / 2
  return(1 - U / n1 / n2)
}

Давайте проверим это:

set.seed(42)
score <- rnorm(1e3)
bool  <- sample(c(TRUE, FALSE), 1e3, replace = TRUE)

pROC::auc(bool, score)
mltools::auc_roc(score, bool)
ROCR::performance(ROCR::prediction(score, bool), "auc")@y.values[[1]]
auroc(score, bool)

0.51371668847094
0.51371668847094
0.51371668847094
0.51371668847094

auroc() в 100 раз быстрее, чем pROC::auc() и computeAUC().

auroc() в 10 раз быстрее, чем mltools::auc_roc() и ROCR::performance().

print(microbenchmark(
  pROC::auc(bool, score),
  computeAUC(score[bool], score[!bool]),
  mltools::auc_roc(score, bool),
  ROCR::performance(ROCR::prediction(score, bool), "auc")@y.values,
  auroc(score, bool)
))

Unit: microseconds
                                                             expr       min
                                           pROC::auc(bool, score) 21000.146
                            computeAUC(score[bool], score[!bool]) 11878.605
                                    mltools::auc_roc(score, bool)  5750.651
 ROCR::performance(ROCR::prediction(score, bool), "auc")@y.values  2899.573
                                               auroc(score, bool)   236.531
         lq       mean     median        uq        max neval  cld
 22005.3350 23738.3447 22206.5730 22710.853  32628.347   100    d
 12323.0305 16173.0645 12378.5540 12624.981 233701.511   100   c 
  6186.0245  6495.5158  6325.3955  6573.993  14698.244   100  b  
  3019.6310  3300.1961  3068.0240  3237.534  11995.667   100 ab  
   245.4755   253.1109   251.8505   257.578    300.506   100 a   
person Kamil Slowikowski    schedule 06.05.2018
comment
Для больших размеров выборки bigstatsr::AUC() работает еще быстрее (реализовано на C++). Отказ от ответственности: я автор. - person F. Privé; 12.04.2019

Комбинируя код из кривых ROC ISL 9.6.3, вместе с @J. Ответ Won. на этот вопрос и еще несколько мест: на следующем графике показана кривая ROC, а в правом нижнем углу графика напечатано значение AUC.

Ниже probs представлен числовой вектор предсказанных вероятностей для бинарной классификации, а test$label содержит истинные метки тестовых данных.

require(ROCR)
require(pROC)

rocplot <- function(pred, truth, ...) {
  predob = prediction(pred, truth)
  perf = performance(predob, "tpr", "fpr")
  plot(perf, ...)
  area <- auc(truth, pred)
  area <- format(round(area, 4), nsmall = 4)
  text(x=0.8, y=0.1, labels = paste("AUC =", area))

  # the reference x=y line
  segments(x0=0, y0=0, x1=1, y1=1, col="gray", lty=2)
}

rocplot(probs, test$label, col="blue")

Это дает такой сюжет:

введите описание изображения здесь

person arun    schedule 20.07.2016

Обычно я использую функцию ROC из DiagnosisMed. упаковка. Мне нравится график, который он создает. AUC возвращается вместе с доверительным интервалом и также упоминается на графике.

ROC(classLabels,scores,Full=TRUE)
person George Dontas    schedule 05.02.2011
comment
По состоянию на 20 июля 2016 г. эта ссылка cran.r-project.org/ web/packages/DiagnosisMed/index.html говорит Package ‘DiagnosisMed’ was removed from the CRAN repository. - person arun; 20.07.2016

В соответствии с ответом Эрика вы также должны иметь возможность рассчитать ROC напрямую, сравнив все возможные пары значений из pos.scores и neg.scores:

score.pairs <- merge(pos.scores, neg.scores)
names(score.pairs) <- c("pos.score", "neg.score")
sum(score.pairs$pos.score > score.pairs$neg.score) / nrow(score.pairs)

Определенно менее эффективен, чем демонстрационный подход или pROC::auc, но более стабилен, чем первый, и требует меньше установки, чем последний.

Связано: когда я попробовал это, он дал результаты, аналогичные значению pROC, но не совсем такие же (отклонение на 0,02 или около того); результат был ближе к выборочному подходу с очень высоким N. Если у кого-то есть идеи, почему это может быть, мне было бы интересно.

person Max Ghenis    schedule 15.01.2013
comment
Один из источников неточности связан со связями. Технически вы должны принять вероятность того, что положительная оценка строго больше, чем отрицательная оценка + 1/2 * вероятность того, что они равны. Если все оценки уникальны, это не будет проблемой. - person ; 25.10.2013

В настоящее время ответ с наибольшим количеством голосов неверен, потому что он не учитывает ничьих. Когда положительные и отрицательные оценки равны, тогда AUC должна быть 0,5. Ниже приведен исправленный пример.

computeAUC <- function(pos.scores, neg.scores, n_sample=100000) {
  # Args:
  #   pos.scores: scores of positive observations
  #   neg.scores: scores of negative observations
  #   n_samples : number of samples to approximate AUC

  pos.sample <- sample(pos.scores, n_sample, replace=T)
  neg.sample <- sample(neg.scores, n_sample, replace=T)
  mean(1.0*(pos.sample > neg.sample) + 0.5*(pos.sample==neg.sample))
}
person Jussi Kujala    schedule 04.01.2017

Вычислить AUC с помощью пакета Metrics очень легко и просто:

library(Metrics)

actual <- c(0, 0, 1, 1)
predicted <- c(.1, .3, .3, .9)

auc(actual, predicted)

0.875
person Chaos Manor    schedule 12.12.2020