2011-02-04 17 views
34

Dato un vettore di punteggi e un vettore di etichette di classi effettive, come si calcola una metrica AUC a numero singolo per un classificatore binario in linguaggio R o in inglese semplice?Calcolare l'AUC in R?

Pagina 9 di "AUC: a Better Measure..." sembra richiedere conoscere le etichette di classe, ed è qui dove an example in MATLAB Non capisco

R(Actual == 1)) 

Perché R (da non confondere con il linguaggio R) è definito un vettore, ma usato come una funzione?

+6

Per chiunque altro che non sa, a quanto pare AUC è il "Area sotto la [receiver operating characteristic] (http://en.wikipedia.org/wiki/Receiver_operating_characteristic) Curve" – Justin

risposta

29

Come detto da altri, è possibile calcolare l'AUC utilizzando il pacchetto ROCR. Con il pacchetto ROCR è inoltre possibile tracciare la curva ROC, la curva di sollevamento e altre misure di selezione del modello.

È possibile calcolare l'AUC direttamente senza utilizzare alcun pacchetto utilizzando il fatto che l'AUC è uguale alla probabilità che un vero risultato positivo sia maggiore di un vero negativo.

Ad esempio, se pos.scores è un vettore contenente un punteggio degli esempi positivi, e neg.scores è un vettore contenente gli esempi negativi allora l'AUC è approssimata da:

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

darà un'approssimazione della AUC . È anche possibile stimare la varianza della AUC del bootstrapping:

> aucs = replicate(1000,mean(sample(pos.scores,1000,replace=T) > sample(neg.scores,1000,replace=T))) 
+0

Per il mio set di dati di test il tuo valore replicato è molto simile a quello di @ jonw (è 0.8504, il tuo 0.850591) eccetto che non ho bisogno di installare pROC. Grazie – Andrew

+5

@Andrew @eric Questa è una risposta terribile. * NON * stimare la variazione dell'AUC - si stima solo la varianza del processo di ricampionamento. Per convincere te stesso, prova a cambiare la dimensione del campione in 'sample' ... dividi per 10, la tua varianza viene moltiplicata per 10. Moltiplicala per 10 e la tua varianza è divisa per 10. Questo non è certamente il comportamento desiderato per calcolare il varianza della AUC. – Calimo

+0

Inoltre, la risposta dovrebbe notare che la stima è valida quanto il numero di repliche. Vai all'infinito e ottieni l'effettiva AUC. – Calimo

32

The ROCR package calcolerà l'AUC tra le altre statistiche:

auc.tmp <- performance(pred,"auc"); auc <- as.numeric([email protected]) 
+0

ho usato ROCR per tracciare le prestazioni, ma non vedo come calcola una "metrica AUC a numero singolo" (dalla domanda originale). – Andrew

+9

'auc.tmp <- performance (pred," auc "); auc <- as.numeric ([email protected]) ' – Itamar

26

Con il pacchetto pROC è possibile utilizzare la funzione di auc() come in questo esempio dalla pagina di aiuto:

> data(aSAH) 
> 
> # Syntax (response, predictor): 
> auc(aSAH$outcome, aSAH$s100b) 
Area under the curve: 0.7314 

link to pROC

1

Di solito uso la funzione ROC dal pacchetto DiagnosisMed. Mi piace il grafico che produce. L'AUC viene restituita insieme al suo intervallo di confidenza e viene anche menzionata nel grafico.

ROC(classLabels,scores,Full=TRUE) 
+1

A partire dal 20 luglio 2016 questo link https://cran.r-project.org/web/packages/DiagnosisMed/index.html dice" Pacchetto " DiagnosisMed 'è stato rimosso dal repository CRAN. – arun

+0

Anche a me è dispiaciuto. –

2

Lungo le linee di risposta di Erik, si dovrebbe anche essere in grado di calcolare il ROC direttamente confrontando tutte le possibili coppie di valori da pos.scores e neg. punteggi:

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) 

Certamente meno efficienti rispetto all'approccio campione o il proc :: AUC, ma più stabile di quella precedente e che richiedono meno l'installazione di quest'ultimo.

Correlato: quando ho provato questo ha dato risultati simili al valore di pROC, ma non esattamente lo stesso (spento di 0.02 o giù di lì); il risultato è stato più vicino all'approccio di esempio con un N. molto alto. Se qualcuno ha idee sul perché questo potrebbe essere interessato.

+3

Una fonte di inesattezza riguarda i legami. Tecnicamente dovresti prendere la probabilità che il punteggio del caso positivo sia strettamente maggiore del punteggio negativo + 1/2 * prob che siano uguali. Se tutti i punteggi sono unici, questo non sarà un problema. –

13

Senza alcuni pacchetti aggiuntivi:

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") 

enter image description here

+0

Se si copia e incolla questo codice e si riceve 'Errore in plot.window (...): sono necessari valori 'xlim' finiti, probabilmente perché le etichette sono 0-1, mentre @AGS utilizza le etichette 1-2. – gentimouton

+1

Non fornisce la vera AUC se due osservazioni hanno la stessa probabilità e l'ordine dell'osservazione non è casuale. Altrimenti codice bello e veloce. – MatthieuBizien

+0

Non so perché questa soluzione non funziona sui miei dati, i miei probs non sono normalizzati entro [0,1] –

1

Combinando codice ISL 9.6.3 ROC Curves, insieme con @J. Ha vinto la risposta a questa domanda e alcuni altri luoghi, il seguente traccia la curva ROC e stampa l'AUC in basso a destra sulla trama.

Sotto probs è un vettore numerico di probabilità previste per la classificazione binaria e test$label contiene le etichette reali dei dati di test.

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") 

Questo dà una trama simile a questo:

enter image description here

3

ho trovato alcune delle soluzioni qui per essere lento e/o confusione (e alcuni di loro non gestiscono correttamente i legami) così Ho scritto la mia funzione data.table basata su auc_roc() nel mio pacchetto 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 
+1

Questa soluzione è molto più veloce del metodo auc() nel pacchetto pROC! il metodo auc() nel pacchetto pROC è piuttosto lento se si devono calcolare i punteggi AUC per problemi di regressione di uscita multi-classe o multipla. –

1

Attualmente la risposta più votata non è corretta perché non tiene conto dei legami. Quando i punteggi positivi e negativi sono uguali, l'AUC dovrebbe essere 0,5. Di seguito è riportato l'esempio corretto.

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)) 
}