Eğri Altındaki Alan (AUC) veya c-istatistiği elle nasıl hesaplanır?


78

İkili bir lojistik regresyon modeli için eğri altındaki alanı (AUC) veya c-istatistiğini elle hesaplamak istiyorum.

Örneğin, doğrulama veri setinde, bağımlı değişken için gerçek değere sahibim, tutulum (1 = tutuldu; 0 = tutulmadı) ve regresyon analizim tarafından oluşturulan her gözlem için öngörülen tutma durumu için öngörülen tutma durumu Eğitim seti kullanılarak inşa edilmiştir (bu 0 ile 1 arasında değişecektir).

İlk düşüncelerim, "doğru" model sınıflandırma sayısını belirlemek ve basitçe "doğru" gözlem sayısını, c-istatistiğini hesaplamak için yapılan toplam gözlem sayısına bölmek oldu. "Doğru" olarak, bir gözlemin gerçek tutma durumu = 1 ise ve öngörülen tutma durumu> 0,5 ise, bu "doğru" bir sınıflandırmadır. Ek olarak, bir gözlemin gerçek tutma durumu = 0 ise ve öngörülen tutma durumu <0,5 ise, bu "doğru" bir sınıflandırmadır. Öngörülen değer = 0.5 olduğunda bir "bağ" oluşacağını kabul ediyorum, ancak bu fenomen doğrulama veri setimde oluşmuyor. Öte yandan, "yanlış" sınıflandırmalar, bir gözlemin gerçek tutma durumu = 1 ve öngörülen tutma durumu <0 ise olacaktır. 5 veya bir sonucun gerçek tutma durumu = 0 ise ve öngörülen tutma durumu> 0,5 ise. TP, FP, FN, TN'den haberdarım ancak bu bilgiyi verilen c-istatistiklerini nasıl hesaplayacağımı bilmiyorum.

Yanıtlar:


115

Hanley's & McNeil'in 1982 yazısını, “ Alıcının çalışma karakteristiği (ROC) eğrisi altındaki alanın anlamı ve kullanımı ” makalesini tavsiye ederim .

Örnek

Bunlar aşağıdaki hastalık durumu ve test sonucuna sahiptir (örneğin bir lojistik modelden tahmin edilen riske karşılık gelir). Sağdaki ilk sayı, gerçek hastalık durumu 'normal' olan hasta sayısı ve ikinci sayı gerçek hastalık durumu 'anormal' olan hasta sayısıdır :

(1) Kesinlikle normal: 33/3
(2) Muhtemelen normal: 6/2
(3) Şüpheli: 6/2
(4) Muhtemelen anormal: 11/11
(5) Kesinlikle anormal: 2/33

Yani toplam 58 'normal' hasta ve '51' anormal hasta var. Öngörücü 1, 'Kesinlikle normal' olduğunda, hastanın genellikle normal olduğunu (36 hastanın 33'ünde gerçek) ve 5 olduğunda, 'Kesinlikle anormal' durumunun hastaların genellikle anormal olduğunu (33 (35 hasta), yani tahmin edici mantıklı. Fakat skoru 2, 3 veya 4 olan bir hastayı nasıl yargılamalıyız? Ortaya çıkan testin duyarlılığını ve özgüllüğünü belirlemek için hastaları anormal veya normal olarak değerlendirmek için sınırlarımızı belirledik.

Hassasiyet ve özgüllük

Farklı kesikler için tahmini hassasiyet ve özgüllüğü hesaplayabiliriz . (Bundan sonra, sadece değerlerin tahmini yapısının örtülü olmasını sağlayarak 'duyarlılık' ve 'özgüllük' yazacağım.)

Kesiktiğimizi seçersek, tüm hastaları anormal olarak sınıflandırırsak , test sonuçları ne olursa olsun (yani, kesikliği 1+ seçersek), 51/51 = 1 hassasiyetini alacağız. / 58 = 0. Kulağa hoş gelmiyor.

Tamam, daha az kesin bir kesim seçelim. Hastaları yalnızca 2 veya daha yüksek test sonuçlarına sahipse anormal olarak sınıflandırırız. Daha sonra 3 anormal hastayı özlüyoruz ve duyarlılığımız 48/51 = 0.94. Ancak, 33/58 = 0,57 olan çok fazla özgünlüğümüz var.

Şimdi çeşitli kesikler seçerek buna devam edebiliriz (3, 4, 5,> 5). (Son durumda, olası en yüksek 5 puanına sahip olsalar bile, hiçbir hastayı anormal olarak sınıflandırmayacağız .)

ROC eğrisi

Bunu tüm olası kesikler için yaparsak ve 1 eksi spesifikliğe karşı hassasiyeti işaretlersek, ROC eğrisini alırız. Aşağıdaki R kodunu kullanabiliriz:

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

Çıktı:

        testres
truestat  1  2  3  4  5
       0 33  6  6 11  2
       1  3  2  2 11 33

Çeşitli istatistikleri hesaplayabiliriz:

( 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

Ve bunu kullanarak, (tahmini) ROC eğrisini çizebiliriz:

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)

AUC eğrisi

AUC'yi manuel olarak hesaplama

Yamuk bölgesi formülü kullanılarak ROC eğrisi altındaki alanı kolayca hesaplayabiliriz:

height = (sens[-1]+sens[-length(sens)])/2
width = -diff(omspec) # = diff(rev(omspec))
sum(height*width)

Sonuç 0.8931711'dir.

Bir uyum ölçüsü

AUC ayrıca bir uyumluluk ölçüsü olarak da görülebilir. Birinin normal, diğerinin anormal olduğu tüm olası hasta çiftlerini alırsak, en yüksek (en 'anormal görünümlü') test sonucuna sahip anormal test sonucunun ne sıklıkta olduğunu hesaplayabiliriz (aynı değere sahipse, biz Bunu 'yarım zafer' olarak sayın):

o = outer(abnorm, norm, "-")
mean((o>0) + .5*(o==0))

Cevap yine ROC eğrisinin altındaki alan olan 0.8931711'dir. Bu her zaman böyle olacak.

Uyumun grafiksel bir görüntüsü

Harrell'in cevabında işaret ettiği gibi, bunun da grafik bir yorumu var. Şimdi y- ekseni üzerinde test puanını (risk tahmini) ve x- ekseni üzerindeki gerçek hastalık durumunu belirleyelim (burada bazı titremelerle, örtüşen noktaları göstermek için):

plot(jitter(truestat,.2), jitter(testres,.8), las=1,
     xlab="True disease status", ylab="Test score")

Gerçek hastalık durumuna karşı risk skorunun dağılım grafiği.

Şimdi soldaki her nokta ('normal' bir hasta) ile sağdaki her nokta ('anormal' bir hasta) arasına bir çizgi çizelim. Pozitif eğimli çizgilerin oranı (yani uyumlu çiftlerin oranı ) uygunluk endeksidir (düz çizgiler '% 50 uygunluk' olarak sayılır).

Bu örnekteki gerçek çizgileri görselleştirmek biraz zor, çünkü ilişkilerin sayısı (eşit risk puanı), ancak biraz titizlik ve şeffaflık ile makul bir komplo elde edebiliriz:

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

Tüm olası gözlem çiftleri arasındaki çizgilerle, gerçek hastalık durumuna karşı risk skorunun dağılım grafiği.

Çizgilerin çoğunun yukarı doğru eğimli olduğunu görüyoruz, bu nedenle uyum endeksi yüksek olacak. Ayrıca her bir gözlem çifti türünün endekse katkısını görüyoruz. Bunların çoğu, risk riski 5 olan (1-5 çift) anormal hastalarla eşleştirilmiş 1 risk skoru olan normal hastalardan gelirken, oldukça fazla da 1-4 ve 4-5 çift arasındadır. Eğim tanımına göre gerçek uyum indeksini hesaplamak çok kolaydır:

d = transform(d, slope=(y_norm-y_abnorm)/(x_norm-x_abnorm))
mean((d$slope > 0) + .5*(d$slope==0))

Cevap yine 0.8931711, yani AUC'dir.

Wilcoxon – Mann – Whitney testi

Uyum ölçüsü ile Wilcoxon-Mann-Whitney testi arasında yakın bir bağlantı var. Aslında sonuncusu, uyumluluk olasılığının (yani, en çok 'anormal görünümlü' test sonucuna sahip olacak rastgele normal-anormal bir çiftte anormal bir hasta olduğu ) test eder. Test istatistiği tahmin edilen uyumluluk olasılığının basit bir dönüşümüdür:

> ( 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

Test istatistiği ( W = 2642), uygun çiftlerin sayısını sayar. Olası çift sayısına bölersek, familar bir sayı alırız:

w = wi$statistic
w/(length(abnorm)*length(norm))

Evet, ROC eğrisinin altındaki alan 0,8931711.

AUC'yi hesaplamanın daha kolay yolları (R cinsinden)

Ama hayatı kendimiz için kolaylaştıralım. AUC'yi bizim için otomatik olarak hesaplayan çeşitli paketler var.

Epi paketi

EpiPaket gömülü (AUC dahil) çeşitli istatistikleri ile güzel ROC eğri oluşturur:

library(Epi)
ROC(testres, truestat) # also try adding plot="sp"

Epi paketinden ROC eğrisi

PROC paketi

Ayrıca pROCpaketi seviyorum , çünkü ROC tahminini pürüzsüzleştirebiliyor (ve düzleştirilmiş ROC'ye dayanarak bir AUC tahminini hesaplıyor):

PROC paketinden ROC eğrisi (düzleştirilmemiş ve düzeltilmiş)

(Kırmızı çizgi orijinal ROC ve siyah çizgi düzleştirilmiş ROC'dir. Ayrıca varsayılan 1: 1 en boy oranına dikkat edin. Hem duyarlılık hem de özgüllüğü 0-1 aralığına sahip olduğundan, bunu kullanmak mantıklı olur.)

Düzleştirilen ROC'den tahmin edilen AUC, düzleştirilmemiş ROC'den AUC'ye benzer, ancak biraz daha büyük olan 0.9107'dir (şekle bakarsanız, neden daha büyük olduğunu kolayca görebilirsiniz). (Pürüzsüz bir AUC hesaplamak için gerçekten çok az olası farklı test sonucu değerimiz olsa da).

Rms paketi

Harrell rmspaketi, rcorr.cens()işlevi kullanarak ilgili çeşitli uygunluk istatistiklerini hesaplayabilir . C IndexÇıktıda AUC geçerli:

> library(rms)
> rcorr.cens(testres,truestat)[1]
  C Index 
0.8931711

CaTools paketi

Sonunda, caToolspakete ve colAUC()işlevine sahibiz . Bazen yardımcı ?colAUColabilecek diğer paketlere (çoğunlukla hız ve çok boyutlu verilerle çalışma yeteneği - bakınız ) göre birkaç avantajı vardır . Ama elbette, tekrar tekrar hesapladığımız aynı cevabı veriyor:

library(caTools)
colAUC(testres, truestat, plotROC=TRUE)
             [,1]
0 vs. 1 0.8931711

CaTools paketinden ROC eğrisi

Son sözler

Birçok insan AUC'nin bize bir testin ne kadar iyi olduğunu söylediğini düşünüyor gibi görünüyor. Bazı insanlar AUC'nin testin hastayı doğru şekilde sınıflandırması olasılığını düşünüyor. Öyle değil . Yukarıdaki örnekten ve hesaplamalardan görebileceğiniz gibi, AUC bize bir test ailesi hakkında , her olası kesim için bir test hakkında bir şeyler anlatır .

Ve AUC, pratikte asla kullanılmayacak olan kesimlere dayanarak hesaplanmaktadır. Neden 'saçma' kesme değerlerinin duyarlılığı ve özgüllüğünü önemsemeliyiz? Yine de, AUC'nin (kısmen) dayandığı şey budur. (Tabii ki, AUC 1'e çok yakınsa, mümkün olan her testin büyük bir ayırt edici gücü olacaktır ve hepimiz çok mutlu oluruz.)

AUC'nin 'rastgele normal-anormal' çifti yorumu güzeldir (ve örneğin en erken ölen en yüksek (göreceli) tehlikeye sahip olan kişi olup olmadığını görmek için hayatta kalma modellerine uzatılabilir). Ancak hiç kimse pratikte kullanmaz. Biri nadir durum bilen birine sahiptir birini sağlıklı ve bir hasta kişiyi hasta biri olan kişinin bilmediği ve tedavi etmek bunlardan hangileri karar vermelidir. (Her durumda, karar kolaydır; tahmini riski en yüksek olanı ele alın.)

Bu nedenle, gerçek ROC eğrisini incelemek sadece AUC özet ölçütüne bakmaktan daha faydalı olacağını düşünüyorum. ROC'yi , yanlış pozitiflerin ve yanlış negatiflerin maliyetleriyle (tahminlerini) birlikte kullanırsanız, okuduğunuz şeyin temel oranları ile birlikte, bir yere gidebilirsiniz.

Ayrıca, AUC'nin kalibrasyonu değil sadece ayrımcılığı ölçtüğünü unutmayın . Yani, risk puanına göre iki kişi (biri hasta diğeri sağlıklı) arasında ayrım yapıp yapamayacağınızı ölçer. Bunun için, sadece bakar göreceli risk değerlerine (ya da eğer sen Wilcoxon-Mann-Whitney testi yorumlama bakınız, rütbeleri) hangi değil mutlak olanlar gerektiğini ilgi duyun. Örneğin, her riski bölmek eğer Lojistik modelinizden 2 ile tahmin ederseniz, aynı AUC (ve ROC) elde edersiniz.

Bir risk modelini değerlendirirken, kalibrasyon da çok önemlidir. Bunu incelemek için, yaklaşık 0.7 gibi bir risk skoru olan tüm hastalara bakacak ve bunların yaklaşık% 70'inin gerçekten hasta olup olmadığını göreceksiniz. Bunu her olası risk puanı için yapın (muhtemelen bir çeşit düzleştirme / yerel regresyon kullanarak). Sonuçları çizdiğinizde, grafiksel bir kalibrasyon ölçümü elde edersiniz .

Hem iyi kalibrasyon hem de iyi ayrımcılığa sahip bir modeliniz varsa, iyi bir modeliniz olmaya başlar. :)


8
Teşekkürler, @Karl Ove Hufthammer, bu aldığım en kapsamlı cevap. Özellikle "Son Sözler" bölümünüzü takdir ediyorum. Harika iş! Tekrar teşekkürler!
Matt Reichenbach

Bu ayrıntılı cevap için çok teşekkür ederim. Epi :: ROC () v2.2.6'nın AUC'nin 1.62 (ikna edici bir çalışma değil) olduğuna ikna olduğu bir veri kümesi ile çalışıyorum, ancak ROC'ye göre, 0.56'da yukarıdaki kodun sonuçlandığına çok daha fazla inanıyorum. içinde.
BurninLeo 16:18

32

Bu soruya bir göz atın: ROC eğrisini anlama

İşte bir ROC eğrisi oluşturmanın yolu (bu sorudan):

ROC eğrisi çizme

sıralama sınıflandırıcınız tarafından işlenen bir veri seti verildi

  • azalan skorda rütbe testi örnekleri
  • (0,0)
  • x
    • x1/pos
    • x1/neg

posneg

Aşağıdaki algoritmayı kullanarak AUC ROC’yu manuel olarak hesaplamak için bu fikri kullanabilirsiniz:

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

Bu güzel gif animasyonlu resim bu süreci daha net göstermeli

eğriyi oluşturma


1
Teşekkürler @Alexey Grigorev, bu harika bir görsel ve gelecekte de faydalı olacağını kanıtlayacak! +1
Matt Reichenbach

1
Lütfen "pozitif ve negatif örneklerin kesirleri" hakkında biraz açıklama yapabilir misiniz, iki eksenin en küçük birim değerini mi kastediyorsunuz?
Allan Ruin

1
@Allan Harabesi: posİşte pozitif veri sayısı. Diyelim ki 11 puan 1 olan 20 veri noktasına sahipsin. Grafiği çizerken 11x9'luk bir dikdörtgene sahibiz (yükseklik x genişlik). Alexey Grigorev ölçeklendirdi, ancak bunu istediğiniz gibi bırakın. Şimdi, her adımda grafik üzerinde 1 hareket ettirin.
Catbuilts,

5

Karl'ın görevinde çok fazla mükemmel bilgi var. Ancak son 20 yılda henüz kimsenin düşüncelerini iyi yönde değiştirmeyen bir ROC eğrisi örneği görmedim. Alçakgönüllü görüşüme göre bir ROC eğrisinin tek değeri, alanının çok faydalı bir uyumluluk olasılığına eşit olacağıdır. ROC eğrisi, okuyucuyu kötü istatistiksel uygulama olan kesimleri kullanmaya teşvik eder.

cY=0,1xY=1yY=0Y=1

n

R Hmiscpaketi rcorr.censişlevi için, daha çok bilgi, özellikle standart bir hata görmek için tüm sonucu yazdırın.


Teşekkürler, @Frank Harell, bakış açınızı takdir ediyorum. Kesimden hoşlanmadığım için c-istatistiğini bir uyumluluk olasılığı olarak kullanıyorum. Tekrar teşekkürler!
Matt Reichenbach

4

İşte ROC eğrisinin altındaki alanı elde etmek için basitçe yamuk kuralı kullanarak AUC'yi hesaplamanın doğal yoluna bir alternatif.

AUC, rastgele örneklenmiş bir pozitif gözlemin, rastgele örneklenmiş bir negatif gözlemden daha büyük bir öngörülen olasılık (pozitif olma) ihtimaline eşittir. Bunu, AUC'yi herhangi bir programlama dilinde, pozitif ve negatif gözlemlerin tüm ikili kombinasyonlarından geçirerek oldukça kolay bir şekilde hesaplamak için kullanabilirsiniz. Örnek büyüklüğü çok büyükse, rasgele örnek gözlemleri de yapabilirsiniz. Kalem ve kağıt kullanarak AUC'yi hesaplamak istiyorsanız, çok küçük bir numune / çok zamanınız yoksa, bu en iyi yaklaşım olmayabilir. Örneğin, 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

pROCPaketi kullanarak doğrulayabiliriz :

library(pROC)
auc(y, probs)
Area under the curve: 0.6287

Rasgele örneklemenin kullanılması:

mean(sample(probs[y == 1L], 100000L, TRUE) > sample(probs[y == 0L], 100000L, TRUE))
[1] 0.62896

1
  1. Gözlemler için gerçek değerin var.
  2. Posterior olasılığını hesaplayın ve sonra gözlemleri bu olasılıkla sıralayın.
  3. PN
    Sum of true ranks0.5PN(PN+1)PN(NPN)

1
@ user73455 ... 1) Evet, gözlemler için gerçek değere sahibim. 2) Posterior olasılık, her gözlem için öngörülen olasılıklarla eş anlamlı mıdır? 3) Anladı; Ancak, "Gerçek rütbelerin toplamı" nedir ve bu değeri nasıl hesaplar? Belki bir örnek, bu cevabı daha ayrıntılı bir şekilde açıklamanıza yardımcı olabilir mi? Teşekkür ederim!
Matt Reichenbach
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.