Ich würde Hanleys & McNeils Arbeit von 1982 " Die Bedeutung und Verwendung der Fläche unter einer Empfänger-Betriebskennlinie (ROC) " empfehlen .
Beispiel
Sie haben die folgende Tabelle mit Krankheitsstatus und Testergebnissen (die beispielsweise dem geschätzten Risiko aus einem Logistikmodell entsprechen). Die erste Zahl rechts ist die Anzahl der Patienten mit dem wahren Krankheitsstatus "normal" und die zweite Zahl ist die Anzahl der Patienten mit dem wahren Krankheitsstatus "abnormal":
(1) Auf jeden Fall normal: 33/3
(2) Wahrscheinlich normal: 6/2
(3) Fraglich: 6/2
(4) Wahrscheinlich abnormal: 11/11
(5) Auf jeden Fall abnormal: 2/33
Es gibt also insgesamt 58 "normale" und "51" abnormale Patienten. Wir sehen, dass wenn der Prädiktor 1 ist, "Definitiv normal", der Patient normalerweise normal ist (wahr für 33 der 36 Patienten), und wenn er 5 ist, "Definitiv abnormal", ist der Patient normalerweise abnormal (wahr für 33 der 36 Patienten) 35 Patienten), so macht der Prädiktor Sinn. Aber wie sollen wir einen Patienten mit einer Punktzahl von 2, 3 oder 4 beurteilen? Was wir für die Beurteilung eines Patienten als abnormal oder normal festgelegt haben, um die Empfindlichkeit und Spezifität des resultierenden Tests zu bestimmen.
Sensitivität und Spezifität
Wir können die geschätzte Empfindlichkeit und Spezifität für verschiedene Grenzwerte berechnen . (Ab jetzt schreibe ich nur noch "Sensitivität" und "Spezifität" und lasse die geschätzte Natur der Werte implizit sein.)
Wenn wir unseren Cutoff so wählen, dass wir alle Patienten als abnormal einstufen , unabhängig von den Testergebnissen (dh wir wählen den Cutoff 1+), erhalten wir eine Sensitivität von 51/51 = 1. Die Spezifität ist 0 / 58 = 0. Klingt nicht so gut.
OK, also wählen wir einen weniger strengen Cutoff. Wir stufen Patienten nur dann als abnormal ein, wenn sie ein Testergebnis von 2 oder höher haben. Wir vermissen dann 3 abnormale Patienten und haben eine Empfindlichkeit von 48/51 = 0,94. Wir haben jedoch eine stark erhöhte Spezifität von 33/58 = 0,57.
Nun können wir fortfahren und verschiedene Grenzwerte auswählen (3, 4, 5,> 5). (Im letzten Fall werden keine Patienten als abnormal eingestuft, auch wenn sie die höchstmögliche Testnote von 5 haben.)
Die ROC-Kurve
Wenn wir dies für alle möglichen Grenzwerte tun und die Empfindlichkeit gegen 1 abzüglich der Spezifität grafisch darstellen, erhalten wir die ROC-Kurve. Wir können den folgenden R-Code verwenden:
# Data
norm = rep(1:5, times=c(33,6,6,11,2))
abnorm = rep(1:5, times=c(3,2,2,11,33))
testres = c(abnorm,norm)
truestat = c(rep(1,length(abnorm)), rep(0,length(norm)))
# Summary table (Table I in the paper)
( tab=as.matrix(table(truestat, testres)) )
Die Ausgabe ist:
testres
truestat 1 2 3 4 5
0 33 6 6 11 2
1 3 2 2 11 33
Wir können verschiedene Statistiken berechnen:
( tot=colSums(tab) ) # Number of patients w/ each test result
( truepos=unname(rev(cumsum(rev(tab[2,])))) ) # Number of true positives
( falsepos=unname(rev(cumsum(rev(tab[1,])))) ) # Number of false positives
( totpos=sum(tab[2,]) ) # The total number of positives (one number)
( totneg=sum(tab[1,]) ) # The total number of negatives (one number)
(sens=truepos/totpos) # Sensitivity (fraction true positives)
(omspec=falsepos/totneg) # 1 − specificity (false positives)
sens=c(sens,0); omspec=c(omspec,0) # Numbers when we classify all as normal
Und damit können wir die (geschätzte) ROC-Kurve zeichnen:
plot(omspec, sens, type="b", xlim=c(0,1), ylim=c(0,1), lwd=2,
xlab="1 − specificity", ylab="Sensitivity") # perhaps with xaxs="i"
grid()
abline(0,1, col="red", lty=2)
Manuelle Berechnung der AUC
Wir können die Fläche unter der ROC-Kurve sehr einfach berechnen, indem wir die Formel für die Fläche eines Trapezes verwenden:
height = (sens[-1]+sens[-length(sens)])/2
width = -diff(omspec) # = diff(rev(omspec))
sum(height*width)
Das Ergebnis ist 0.8931711.
Eine Konkordanzmaßnahme
Die AUC kann auch als Konkordanzmaß angesehen werden. Wenn wir alle möglichen nehmen Paare von Patienten , bei denen eine normal ist und das andere ist abnormal, können wir berechnen , wie häufig ist es der anormale derjenige, der die höchste ( die meisten ‚abnormal schau‘) Testergebnis hat (wenn sie den gleichen Wert haben , wir zähle dies als "halben Sieg"):
o = outer(abnorm, norm, "-")
mean((o>0) + .5*(o==0))
Die Antwort ist wieder 0,8931711, die Fläche unter der ROC-Kurve. Dies wird immer der Fall sein.
Eine grafische Ansicht der Konkordanz
Wie Harrell in seiner Antwort hervorhob, hat dies auch eine grafische Interpretation. Zeichnen Sie die Testergebnisse (Risikoschätzung) auf der y- Achse und den wahren Krankheitsstatus auf der x- Achse (hier mit etwas Jittering, um überlappende Punkte anzuzeigen):
plot(jitter(truestat,.2), jitter(testres,.8), las=1,
xlab="True disease status", ylab="Test score")
Zeichnen wir nun eine Linie zwischen jedem Punkt auf der linken Seite (ein "normaler" Patient) und jedem Punkt auf der rechten Seite (ein "abnormaler" Patient). Der Anteil der Linien mit einer positiven Steigung (dh der Anteil der Konkordantenpaare ) ist der Konkordanzindex (flache Linien zählen als „50% Konkordanz“).
Es ist ein bisschen schwierig, die tatsächlichen Linien für dieses Beispiel zu visualisieren, da die Anzahl der Verbindungen (gleiche Risikobewertung), aber mit etwas Jitter und Transparenz können wir eine vernünftige Darstellung erhalten:
d = cbind(x_norm=0, x_abnorm=1, expand.grid(y_norm=norm, y_abnorm=abnorm))
library(ggplot2)
ggplot(d, aes(x=x_norm, xend=x_abnorm, y=y_norm, yend=y_abnorm)) +
geom_segment(colour="#ff000006",
position=position_jitter(width=0, height=.1)) +
xlab("True disease status") + ylab("Test\nscore") +
theme_light() + theme(axis.title.y=element_text(angle=0))
Wir sehen, dass die meisten Linien nach oben geneigt sind, sodass der Konkordanzindex hoch ist. Wir sehen auch den Beitrag zum Index von jeder Art von Beobachtungspaar. Das meiste davon stammt von normalen Patienten mit einem Risikowert von 1, gepaart mit abnormalen Patienten mit einem Risikowert von 5 (1–5 Paare), aber ziemlich viel kommt auch von 1–4 Paaren und 4–5 Paaren. Und es ist sehr einfach, den tatsächlichen Konkordanzindex basierend auf der Steigungsdefinition zu berechnen:
d = transform(d, slope=(y_norm-y_abnorm)/(x_norm-x_abnorm))
mean((d$slope > 0) + .5*(d$slope==0))
Die Antwort ist wieder 0,8931711, dh die AUC.
Der Wilcoxon-Mann-Whitney-Test
Es besteht ein enger Zusammenhang zwischen dem Konkordanzmaß und dem Wilcoxon-Mann-Whitney-Test. Letztere prüft tatsächlich, ob die Wahrscheinlichkeit einer Übereinstimmung (dh, dass es der abnormale Patient in einem zufälligen Normal-Abnormal-Paar ist, der das am „abnormalsten aussehende“ Testergebnis hat) genau 0,5 ist. Und seine Teststatistik ist nur eine einfache Transformation der geschätzten Konkordanzwahrscheinlichkeit:
> ( wi = wilcox.test(abnorm,norm) )
Wilcoxon rank sum test with continuity correction
data: abnorm and norm
W = 2642, p-value = 1.944e-13
alternative hypothesis: true location shift is not equal to 0
Die Teststatistik ( W = 2642
) zählt die Anzahl der übereinstimmenden Paare. Wenn wir es durch die Anzahl der möglichen Paare teilen, erhalten wir eine vertraute Zahl:
w = wi$statistic
w/(length(abnorm)*length(norm))
Ja, es ist 0,8931711, der Bereich unter der ROC-Kurve.
Einfachere Berechnung der AUC (in R)
Aber machen wir uns das Leben leichter. Es gibt verschiedene Pakete, die die AUC für uns automatisch berechnen.
Das Epi-Paket
Das Epi
Paket erstellt eine schöne ROC-Kurve mit verschiedenen eingebetteten Statistiken (einschließlich der AUC):
library(Epi)
ROC(testres, truestat) # also try adding plot="sp"
Das pROC-Paket
Ich mag das pROC
Paket auch, da es die ROC-Schätzung glätten kann (und eine AUC-Schätzung basierend auf der geglätteten ROC berechnet):
(Die rote Linie ist der ursprüngliche ROC, und die schwarze Linie ist der geglättete ROC. Beachten Sie auch das Standard-Seitenverhältnis von 1: 1. Es ist sinnvoll, dies zu verwenden, da sowohl die Empfindlichkeit als auch die Spezifität einen Bereich von 0 bis 1 haben.)
Die geschätzte AUC aus dem geglätteten ROC beträgt 0,9107, ähnlich der AUC aus dem ungeglätteten ROC, ist jedoch etwas größer (wenn Sie sich die Abbildung ansehen, können Sie leicht erkennen, warum sie größer ist). (Obwohl wir wirklich zu wenige mögliche eindeutige Testergebniswerte haben, um eine glatte AUC zu berechnen).
Das RMS-Paket
Harrells rms
Paket kann mit der rcorr.cens()
Funktion verschiedene zugehörige Konkordanzstatistiken berechnen . Das C Index
in seiner Ausgabe ist die AUC:
> library(rms)
> rcorr.cens(testres,truestat)[1]
C Index
0.8931711
Das caTools-Paket
Schließlich haben wir das caTools
Paket und seine colAUC()
Funktion. Es hat einige Vorteile gegenüber anderen Paketen (hauptsächlich Geschwindigkeit und die Fähigkeit, mit mehrdimensionalen Daten zu arbeiten - siehe ?colAUC
), die manchmal hilfreich sein können. Aber es gibt natürlich die gleiche Antwort, die wir immer wieder berechnet haben:
library(caTools)
colAUC(testres, truestat, plotROC=TRUE)
[,1]
0 vs. 1 0.8931711
Letzte Worte
Viele Leute scheinen zu glauben, dass die AUC uns sagt, wie 'gut' ein Test ist. Und einige Leute denken, dass die AUC die Wahrscheinlichkeit ist, dass der Test einen Patienten richtig klassifiziert. Es ist nicht . Wie Sie aus dem obigen Beispiel und Berechnungen sehen können, sagt die AUC uns etwas über eine Familie von Tests, ein Test für jede mögliche Cutoff.
Und die AUC wird basierend auf Grenzwerten berechnet, die man in der Praxis niemals verwenden würde. Warum sollten wir uns für die Empfindlichkeit und Spezifität von "unsinnigen" Grenzwerten interessieren? Dennoch basiert die AUC (teilweise) darauf. (Wenn die AUC sehr nahe bei 1 liegt, hat natürlich fast jeder mögliche Test eine große Unterscheidungskraft, und wir würden uns alle sehr freuen.)
Die "zufällige Normal-Abnormal-Paarinterpretation" der AUC ist nett (und kann zum Beispiel auf Überlebensmodelle ausgedehnt werden, bei denen wir sehen, ob es sich um die Person mit dem höchsten (relativen) Risiko handelt, die am frühesten stirbt). Aber man würde es niemals in der Praxis anwenden. Es ist ein seltener Fall, in dem man weiß, dass man eine gesunde und eine kranke Person hat, nicht weiß, welche Person die kranke ist und entscheiden muss, welche von ihnen zu behandeln ist. (In jedem Fall ist die Entscheidung einfach; behandeln Sie denjenigen mit dem höchsten geschätzten Risiko.)
Daher denke ich, dass das Studieren der tatsächlichen ROC-Kurve nützlicher ist, als nur die AUC-Zusammenfassung zu betrachten. Und wenn Sie die ROC zusammen mit (Schätzungen der) Kosten für falsch-positive und falsch-negative Ergebnisse sowie den Basisraten für das, was Sie studieren, verwenden, können Sie irgendwohin gelangen.
Beachten Sie auch, dass die AUC nur die Diskriminierung und nicht die Kalibrierung misst . Das heißt, es wird gemessen, ob Sie zwei Personen (eine kranke und eine gesunde) anhand der Risikobewertung unterscheiden können. Dabei werden nur relative Risikowerte (oder Ränge, wenn Sie so wollen, vgl. Die Wilcoxon-Mann-Whitney-Testinterpretation) betrachtet, nicht die absoluten, die Sie interessieren sollten . Zum Beispiel, wenn Sie jedes Risiko aufteilen Schätzen Sie aus Ihrem Logistikmodell um 2, erhalten Sie genau die gleiche AUC (und ROC).
Bei der Bewertung eines Risikomodells ist auch die Kalibrierung von großer Bedeutung. Um dies zu untersuchen, werden Sie alle Patienten mit einem Risikowert von etwa 0,7 untersuchen und feststellen, ob ungefähr 70% dieser Patienten tatsächlich krank waren. Tun Sie dies für jede mögliche Risikobewertung (möglicherweise mit einer Art Glättung / lokaler Regression). Zeichnen Sie die Ergebnisse ein und Sie erhalten ein grafisches Kalibrierungsmaß .
Wenn ein Modell mit haben beide Kalibrierung gut und eine gute Unterscheidung, dann starten Sie gutes Modell haben. :)