I er interesseret i at beregne arealet under kurven (AUC) eller c-statistikken i hånden for en binær logistisk regressionsmodel.
For eksempel i valideringsdatasættet, jeg har den sande værdi for den afhængige variabel, retention (1 = bevaret; 0 = ikke bevaret), samt en forudsagt retentionsstatus for hver observation genereret af min regressionsanalyse ved hjælp af en model, der blev bygget ved hjælp af træningen sæt (dette vil variere fra 0 til 1).
Mine første tanker var at identificere det “korrekte” antal modelklassifikationer og blot dele antallet af “korrekte” observationer med antallet af samlede observationer at beregne c-statistikken. Ved “korrekt”, hvis den sande tilbageholdelsesstatus for en observation = 1 og den forudsagte tilbageholdelsesstatus er> 0,5, er det en “korrekt” klassifikation. Hvis den ægte tilbageholdelsesstatus for en observation = 0 og den forudsagte tilbageholdelsesstatus er < 0,5, er det derudover også en “korrekt” klassifikation. Jeg antager, at en “tie” ville forekomme, når den forudsagte værdi = 0,5, men dette fænomen forekommer ikke i mit valideringsdatasæt. På den anden side ville “forkerte” klassifikationer være, hvis den sande tilbageholdelsesstatus for en observation = 1 og den forudsagte tilbageholdelsesstatus er < 0,5, eller hvis den sande tilbageholdelsesstatus for et resultat = 0 og den forudsagte tilbageholdelsesstatus er> 0,5. Jeg er opmærksom på TP, FP, FN, TN, men er ikke opmærksom på, hvordan man beregner c-statistikken givet disse oplysninger.
Svar
Jeg vil anbefale Hanleys & McNeils 1982-papir Betydningen og brugen af området under en modtagerfunktionskarakteristik (ROC ) kurve .
Eksempel
De har følgende tabel med sygdomsstatus og testresultat (svarende til for eksempel den estimerede risiko fra en logistisk model). Det første tal til højre er antallet af patienter med sand sygdomsstatus normal og det andet tal er antallet af patienter med sand sygdomsstatus unormal:
(1) Absolut normal: 33/3
(2) Sandsynligvis normal: 6/2
(3) Tvivlsom: 6/2
(4) Sandsynligvis unormal: 11/11
(5) Absolut unormal: 2/33
Så der er i alt 58 normale patienter og 51 unormale patienter. Vi ser, at når forudsigeren er 1, Absolut normal, er patienten normalt normal (sand for 33 af de 36 patienter), og når det er 5, Absolut unormalt er patienterne normalt unormale (sandt for 33 af 35 patienter), så forudsigeren giver mening. Men hvordan skal vi bedømme en patient med en score på 2, 3 eller 4? Hvad vi sætter vores cutoff for at bedømme en patient som unormal eller normal for at bestemme følsomheden og specificiteten af den resulterende test.
Følsomhed og specificitet
Vi kan beregne den estimerede følsomhed og specificitet for forskellige cutoffs. (Jeg skriver bare følsomhed og specificitet fra nu af, så de anslåede værdier kan være implicitte.)
Hvis vi vælger vores afskæring, så vi klassificerer alle patienterne som unormale, uanset hvad deres testresultater siger (dvs. vi vælger cutoff 1+), får vi en følsomhed på 51/51 = 1. Specificiteten vil være 0/58 = 0. Gør det ikke lyder så godt.
OK, så lad os vælge en mindre streng afskæring. Vi klassificerer kun patienter som unormale, hvis de har et testresultat på 2 eller højere. Vi savner derefter 3 unormale patienter og har en følsomhed på 48/51 = 0,94. Men vi har en meget øget specificitet på 33/58 = 0,57.
Vi kan nu fortsætte dette ved at vælge forskellige cutoffs (3, 4, 5,> 5). (I det sidste tilfælde klassificerer vi ikke nogen patienter som unormale, selvom de har den højest mulige testscore på 5.)
ROC-kurven
Hvis vi gør dette for alle mulige cutoffs, og plottet følsomheden over for 1 minus specificiteten, får vi ROC-kurven. Vi kan bruge følgende R-kode:
# 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)) )
Outputtet er:
testres truestat 1 2 3 4 5 0 33 6 6 11 2 1 3 2 2 11 33
Vi kan beregne forskellige statistikker:
( 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
Og ved hjælp af dette kan vi plotte den (anslåede) ROC-kurve:
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)
Manuel beregning af AUC
Vi kan meget let beregne arealet under ROC-kurven ved hjælp af formlen for arealet af et trapezformat:
height = (sens[-1]+sens[-length(sens)])/2 width = -diff(omspec) # = diff(rev(omspec)) sum(height*width)
Resultatet er 0.8931711.
En konkordansforanstaltning
AUC kan også ses som en konkordansforanstaltning.Hvis vi tager alle mulige par patienter, hvor den ene er normal og den anden er unormal, kan vi beregne, hvor ofte det er den unormale, der har det højeste (mest unormale udseende) testresultat (hvis de har den samme værdi, vi tæller, at dette som en halv sejr):
o = outer(abnorm, norm, "-") mean((o>0) + .5*(o==0))
Svaret er igen 0.8931711, området under ROC-kurven. Dette vil altid være tilfældet.
Et grafisk billede af overensstemmelse
Som Harrell påpegede i hans svar, har dette også en grafisk fortolkning. Lad os plotte testscore (risikovurderet) på y -aksen og ægte sygdomsstatus på x -aksen (her med noget rystende for at vise overlappende punkter):
plot(jitter(truestat,.2), jitter(testres,.8), las=1, xlab="True disease status", ylab="Test score")
Lad os nu tegne en linje mellem hvert punkt til venstre (en normal patient) og hvert punkt til højre (en unormal patient). Andelen af linjer med en positiv hældning (dvs. andelen af concordant par) er concordanceindekset (flade linjer tæller som 50% concordance ).
Det er lidt vanskeligt at visualisere de faktiske linjer til dette eksempel på grund af antallet af bånd (lige risikoscore), men med en vis rystelse og gennemsigtighed kan vi få et rimeligt plot:
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))
Vi ser, at de fleste af linierne skråner opad, så konkordansindekset vil være højt. Vi ser også bidraget til indekset fra hver type observationspar. Det meste af det kommer fra normale patienter med en risikoscore på 1 parret med unormale patienter med en risikoscore på 5 (1-5 par), men en hel del kommer også fra 1–4 par og 4-5 par. Og det er meget let at beregne det faktiske konkordansindeks baseret på hældningsdefinitionen:
d = transform(d, slope=(y_norm-y_abnorm)/(x_norm-x_abnorm)) mean((d$slope > 0) + .5*(d$slope==0))
Svaret er igen 0.8931711, dvs. AUC.
Wilcoxon – Mann – Whitney-testen
Der er en tæt sammenhæng mellem konkordansmål og Wilcoxon – Mann – Whitney prøve. Faktisk tester sidstnævnte, om sandsynligheden for overensstemmelse (dvs. at det er den unormale patient i et tilfældigt normalt – unormalt par, der vil have det mest unormale udseende testresultat) er nøjagtigt 0,5. Og dens teststatistik er bare en simpel transformation af den estimerede sandsynlighed for overensstemmelse:
> ( 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
Teststatistikken (W = 2642
) tæller antallet af konkordante par. Hvis vi deler det med antallet af mulige par, får vi et kendt nummer:
w = wi$statistic w/(length(abnorm)*length(norm))
Ja, det er 0,8931711, området under ROC-kurven.
Lettere måder at beregne AUC (i R)
Men lad os gøre livet lettere for os selv. Der er forskellige pakker, der automatisk beregner AUC for os.
Epi-pakken
Epi
-pakken skaber en dejlig ROC-kurve med forskellige statistik (inklusive AUC) integreret:
library(Epi) ROC(testres, truestat) # also try adding plot="sp"
pROC-pakken
Jeg kan også godt lide pROC
-pakken, da den kan udjævne ROC-estimatet (og beregne et AUC-estimat baseret på det udjævnede ROC):
(Den røde linje er den oprindelige ROC, og den sorte linje er den glatte ROC. Bemærk også standardformatet 1: 1. Det giver mening at bruge dette, da både følsomhed og specificitet har et 0-1 interval.)
Den estimerede AUC fra udjævnet ROC er 0,9107, svarende til, men lidt større end AUC fra den uudjævnede ROC (hvis du ser en figuren kan du let se, hvorfor den er større). (Selvom vi virkelig har for få mulige forskellige testresultatværdier til at beregne en jævn AUC).
rms-pakken
Harrells rms
-pakke kan beregne forskellige relaterede konkordansstatistikker ved hjælp af rcorr.cens()
-funktionen. C Index
i dens output er AUC:
> library(rms) > rcorr.cens(testres,truestat)[1] C Index 0.8931711
caTools-pakken
Endelig har vi caTools
-pakken og dens colAUC()
-funktion. Det har et par fordele i forhold til andre pakker (hovedsagelig hastighed og evnen til at arbejde med multidimensionelle data – se ?colAUC
), der kan nogle gange være nyttige.Men det giver selvfølgelig det samme svar, som vi har beregnet igen og igen:
library(caTools) colAUC(testres, truestat, plotROC=TRUE) [,1] 0 vs. 1 0.8931711
Afsluttende ord
Mange synes at tro, at AUC fortæller os, hvor god en test er. Og nogle mennesker tror, at AUC er sandsynligheden for, at testen korrekt klassificerer en patient. Det er ikke . Som du kan se fra ovenstående eksempel og beregninger, fortæller AUC os noget om en familie af test, en test for hver mulig afskæring.
Og AUC beregnes ud fra afskæringer man aldrig ville bruge i praksis. Hvorfor skal vi være opmærksomme på følsomheden og specificiteten af meningsløse afskæringsværdier? Alligevel er det, hvad AUC er (delvist) baseret på. (Selvfølgelig, hvis AUC er meget tæt på 1, vil næsten enhver mulig test have stor diskriminerende kraft, og vi ville alle være meget glade.)
Den tilfældige normale –Normal parfortolkning af AUC er pæn (og kan f.eks. Udvides til at overleve modeller, hvor vi ser, om det er personen med den højeste (relative) fare, der dør tidligst). Men man ville aldrig bruge det i praksis. Det er et sjældent tilfælde, hvor man ved man har en sund og en syg person, ikke ved, hvilken person der er syg, og skal beslutte, hvilken af dem de skal behandle. (Under alle omstændigheder er beslutningen let; behandle den med den højeste estimerede risiko.)
Så jeg tror, at studere den faktiske ROC-kurve vil være mere nyttig end bare at se på AUC sammenfattende foranstaltning. Og hvis du bruger ROC sammen med (estimater af) omkostninger for falske positive og falske negativer sammen med basisraterne for det, du studerer, kan du komme et sted.
Bemærk også, at AUC kun måler forskelsbehandling og ikke kalibrering. Det vil sige, det måler, om du kan skelne mellem to personer (en syg og en sund) baseret på risikoscore. Til dette ser det kun på relative risikoværdier (eller rangerer, hvis du vil, jf. Wilcoxon – Mann – Whitney-testfortolkningen), ikke de absolutte, som du skal være interesseret i. Hvis du for eksempel deler hvert risikostimat fra din logistikmodel med 2, får du nøjagtig den samme AUC (og ROC).
Når du vurderer en risikomodel, kalibrering er også meget vigtig. For at undersøge dette vil du se på alle patienter med en risikoscore på omkring f.eks. 0,7 og se om ca. 70% af disse faktisk var syge. Gør dette for hver mulig risikoscore (muligvis ved hjælp af en slags udjævning / lokal regression). Plot resultaterne, og du får et grafisk mål for kalibrering .
Hvis du har en model med både god kalibrering og god diskrimination, så begynder at have en god model. 🙂
Kommentarer
Svar
Se på dette spørgsmål: Forståelse af ROC-kurve
Sådan bygger du en ROC-kurve (ud fra dette spørgsmål):
Tegning af ROC-kurve
givet et datasæt behandlet af din ranking klassificering
- eksempler på rangtest ved faldende score
- start i $ (0, 0) $
- for hvert eksempel $ x $ (i faldende rækkefølge)
- hvis $ x $ er positiv, flyt $ 1 / \ text {pos} $ op
- hvis $ x $ er negativ, flyt $ 1 / \ text {neg} $ til højre
hvor $ \ text {pos} $ og $ \ text {neg} $ er brøkene af henholdsvis positive og negative eksempler.
Du kan bruge denne idé til manuel beregning af AUC ROC ved hjælp af følgende algoritme:
auc = 0.0 height = 0.0 for each training example x_i, y_i if y_i = 1.0: height = height + tpr else auc = auc + height * fpr return auc
Dette dejlige gif-animerede billede skal illustrere dette procesklarere
Kommentarer
- Tak @Alexey Grigorev, dette er et fantastisk billede, og det vil sandsynligvis vise sig nyttigt i fremtiden! +1
- Kan du forklare lidt om ” fraktioner af positive og negative eksempler “, mener du mindste enhedsværdi af to akser?
- @Allan Ruin:
pos
betyder her antallet af positive data. Lad os sige, at du har 20 datapunkter, hvor 11 point er 1. Når vi tegner diagrammet, har vi et rektangel 11×9 (højde x bredde). Alexey Grigorev skalerede, men lad det bare være som det ‘ s, hvis du vil. Flyt nu bare 1 på diagrammet ved hvert trin.
Svar
Karls indlæg har meget med fremragende information. Men jeg har endnu ikke set de sidste 20 år et eksempel på en ROC-kurve, der ændrede nogens tænkning i en god retning. Den eneste værdi af en ROC-kurve efter min ydmyge opfattelse er, at dens område tilfældigvis har en meget anvendelig konkordanssandsynlighed. Selve ROC-kurven frister læseren til at bruge cutoffs, hvilket er dårlig statistisk praksis.
For så vidt manuel beregning af $ c $ -indekset, lav et plot med $ Y = 0,1 $ på $ x $ -aks og den kontinuerlige forudsigelse eller forudsagte sandsynlighed for, at $ Y = 1 $ på $ y $ -aksen. Hvis du forbinder hvert punkt med $ Y = 0 $ med hvert punkt med $ Y = 1 $, er andelen af linierne, der har en positiv hældning, sandsynligheden for overensstemmelse.
Eventuelle mål, der har en nævner på $ n $ i denne indstilling er ukorrekte regler for nøjagtighedsscore og bør undgås. Dette inkluderer proportion klassificeret korrekt, følsomhed og specificitet.
For funktionen R Hmisc
rcorr.cens
skal du udskrive hele resultatet for at se mere information, især en standardfejl.
Kommentarer
- Tak, @Frank Harell, jeg sætter pris på dit perspektiv. Jeg bruger simpelthen c-statistikken som en overensstemmelse med sandsynligheden, da jeg ikke ‘ ikke kan lide afskæringer. Tak igen!
Svar
Her er et alternativ til den naturlige måde at beregne AUC på ved blot at bruge den trapezformede regel for at få området under ROC-kurven.
AUC er lig sandsynligheden for, at en tilfældig stikprøvet positiv observation har en forudsagt sandsynlighed (for at være positiv) større end en tilfældig stikprøvet negativ observation. Du kan bruge dette til at beregne AUC ganske let på ethvert programmeringssprog ved at gennemgå alle de parvise kombinationer af positive og negative observationer. Du kunne også tilfældigt prøve observationer, hvis stikprøvestørrelsen var for stor. Hvis du vil beregne AUC ved hjælp af pen og papir, er dette muligvis ikke den bedste metode, medmindre du har en meget lille prøve / meget tid. For eksempel i R:
n <- 100L x1 <- rnorm(n, 2.0, 0.5) x2 <- rnorm(n, -1.0, 2) y <- rbinom(n, 1L, plogis(-0.4 + 0.5 * x1 + 0.1 * x2)) mod <- glm(y ~ x1 + x2, "binomial") probs <- predict(mod, type = "response") combinations <- expand.grid(positiveProbs = probs[y == 1L], negativeProbs = probs[y == 0L]) mean(combinations$positiveProbs > combinations$negativeProbs) [1] 0.628723
Vi kan verificere ved hjælp af pROC
-pakken:
library(pROC) auc(y, probs) Area under the curve: 0.6287
Brug af tilfældig prøveudtagning:
mean(sample(probs[y == 1L], 100000L, TRUE) > sample(probs[y == 0L], 100000L, TRUE)) [1] 0.62896
Svar
- Du har ægte værdi for observationer.
- Beregn bageste sandsynlighed, og rangér derefter observationer efter denne sandsynlighed.
- Under forudsætning af afskæringssandsynligheden for $ P $ og antal observationer $ N $:
$$ \ frac {\ text {Summen af ægte rækker} -0.5PN (PN + 1)} { PN (N-PN)} $$
Kommentarer
- @ user73455 … 1) Ja, jeg har den sande værdi til observationer. 2) Er bageste sandsynlighed synonym med forudsagte sandsynligheder for hver af observationer? 3) forstået; hvad er dog ” Summen af sande rækker ” og hvordan beregner man denne værdi? Måske kan et eksempel hjælpe dig med at forklare dette svar mere grundigt? Tak!
sens=c(sens,0); omspec=c(omspec,0)
, skal ‘ t væresens=c(0, sens); omspec=c(0, omspec)
? Det plotter korrekt med det førende0
men ikke som det er i øjeblikket i svaret.sens
ogomspec
inden plottet).