Saya akan merekomendasikan makalah Hanley & McNeil 1982 ' Makna dan penggunaan area di bawah kurva karakteristik operasi penerima (ROC) '.
Contoh
Mereka memiliki tabel status penyakit dan hasil tes berikut (sesuai dengan, misalnya, perkiraan risiko dari model logistik). Angka pertama di sebelah kanan adalah jumlah pasien dengan status penyakit sebenarnya 'normal' dan nomor kedua adalah jumlah pasien dengan status penyakit sebenarnya 'tidak normal':
(1) Pasti normal: 33/3
(2) Mungkin normal: 6/2
(3) dipertanyakan: 6/2
(4) Mungkin tidak normal: 11/11
(5) Jelas tidak normal: 2/33
Jadi ada total 58 pasien 'normal' dan '51' yang abnormal. Kita melihat bahwa ketika prediktornya 1, 'Pasti normal', pasien biasanya normal (berlaku untuk 33 dari 36 pasien), dan ketika 5, 'Pasti abnormal' pasien biasanya abnormal (benar untuk 33 pasien). 35 pasien), sehingga prediktor masuk akal. Tetapi bagaimana kita menilai pasien dengan skor 2, 3, atau 4? Apa yang kami tetapkan untuk menilai pasien sebagai tidak normal atau normal untuk menentukan sensitivitas dan spesifisitas tes yang dihasilkan.
Sensitivitas dan spesifisitas
Kita dapat menghitung estimasi sensitivitas dan spesifisitas untuk cutoff yang berbeda. (Saya hanya akan menulis 'sensitivitas' dan 'spesifisitas' mulai sekarang, membiarkan sifat estimasi nilai menjadi tersirat.)
Jika kami memilih cutoff kami sehingga kami mengklasifikasikan semua pasien sebagai tidak normal, tidak peduli apa hasil tes mereka (yaitu, kami memilih cutoff 1+), kami akan mendapatkan sensitivitas 51/51 = 1. Spesifisitasnya adalah 0 / 58 = 0. Tidak terdengar bagus.
OK, jadi mari kita pilih cutoff yang tidak terlalu ketat. Kami hanya mengklasifikasikan pasien sebagai abnormal jika mereka memiliki hasil tes 2 atau lebih tinggi. Kami kemudian kehilangan 3 pasien abnormal, dan memiliki sensitivitas 48/51 = 0,94. Tetapi kami memiliki spesifisitas yang jauh meningkat, dari 33/58 = 0,57.
Kita sekarang dapat melanjutkan ini, memilih berbagai cutoff (3, 4, 5,> 5). (Dalam kasus terakhir, kita tidak akan mengklasifikasikan setiap pasien sebagai abnormal, bahkan jika mereka memiliki kemungkinan nilai tes tertinggi 5.)
Kurva ROC
Jika kita melakukan ini untuk semua kemungkinan cutoff, dan plot sensitivitas terhadap 1 dikurangi spesifisitas, kita mendapatkan kurva ROC. Kita dapat menggunakan kode R berikut:
# 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)) )
Outputnya adalah:
testres
truestat 1 2 3 4 5
0 33 6 6 11 2
1 3 2 2 11 33
Kami dapat menghitung berbagai statistik:
( 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
Dan menggunakan ini, kita dapat memplot kurva ROC (diperkirakan):
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)
Secara manual menghitung AUC
Kami dapat dengan mudah menghitung area di bawah kurva ROC, menggunakan rumus untuk area trapesium:
height = (sens[-1]+sens[-length(sens)])/2
width = -diff(omspec) # = diff(rev(omspec))
sum(height*width)
Hasilnya adalah 0,8931711.
Ukuran konkordansi
AUC juga dapat dilihat sebagai ukuran konkordansi. Jika kita mengambil semua pasangan pasien yang mungkin di mana satu normal dan yang lain abnormal, kita dapat menghitung seberapa sering itu abnormal yang memiliki hasil tes tertinggi (paling 'kelainan') (jika mereka memiliki nilai yang sama, kami hitung ini sebagai 'setengah kemenangan'):
o = outer(abnorm, norm, "-")
mean((o>0) + .5*(o==0))
Jawabannya adalah lagi 0,8931711, area di bawah kurva ROC. Ini akan selalu menjadi masalah.
Tampilan grafis konkordansi
Seperti yang ditunjukkan oleh Harrell dalam jawabannya, ini juga memiliki interpretasi grafis. Mari kita plot skor tes (estimasi risiko) pada y- sumbu dan status penyakit sebenarnya pada x- sumbu (di sini dengan beberapa jittering, untuk menunjukkan poin yang tumpang tindih):
plot(jitter(truestat,.2), jitter(testres,.8), las=1,
xlab="True disease status", ylab="Test score")
Mari kita menggambar garis antara setiap titik di sebelah kiri (pasien 'normal') dan setiap titik di sebelah kanan (pasien 'abnormal'). Proporsi garis dengan kemiringan positif (yaitu proporsi pasangan konkordan ) adalah indeks konkordansi (garis datar dihitung sebagai 'konkordansi 50%').
Agak sulit untuk memvisualisasikan garis sebenarnya untuk contoh ini, karena jumlah ikatan (skor risiko yang sama), tetapi dengan sedikit jittering dan transparansi kita bisa mendapatkan plot yang masuk akal:
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))
Kita melihat bahwa sebagian besar garis miring ke atas, sehingga indeks kesesuaian akan tinggi. Kami juga melihat kontribusi terhadap indeks dari setiap jenis pasangan pengamatan. Sebagian besar berasal dari pasien normal dengan skor risiko 1 berpasangan dengan pasien abnormal dengan skor risiko 5 (1-5 pasang), tetapi cukup banyak juga berasal dari 1-4 pasang dan 4-5 pasang. Dan sangat mudah untuk menghitung indeks konkordansi aktual berdasarkan definisi kemiringan:
d = transform(d, slope=(y_norm-y_abnorm)/(x_norm-x_abnorm))
mean((d$slope > 0) + .5*(d$slope==0))
Jawabannya lagi 0,8931711, yaitu, AUC.
Tes Wilcoxon – Mann-Whitney
Ada hubungan erat antara ukuran konkordansi dan uji Wilcoxon-Mann-Whitney. Sebenarnya, tes kedua jika probabilitas konkordansi (yaitu, bahwa itu pasien yang abnormal dalam random pasangan yang normal-normal yang akan memiliki paling 'normal-cari' hasil tes) adalah persis 0,5. Dan statistik pengujiannya hanyalah transformasi sederhana dari perkiraan probabilitas konkordansi:
> ( 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
Statistik uji ( W = 2642
) menghitung jumlah pasangan yang sesuai. Jika kita membaginya dengan jumlah pasangan yang memungkinkan, kita mendapatkan nomor familar:
w = wi$statistic
w/(length(abnorm)*length(norm))
Ya, ini 0,8931711, area di bawah kurva ROC.
Cara-cara yang lebih mudah untuk menghitung AUC (dalam R)
Tapi mari kita buat hidup lebih mudah untuk diri kita sendiri. Ada berbagai paket yang menghitung AUC untuk kita secara otomatis.
Paket Epi
The Epi
paket menciptakan kurva ROC bagus dengan berbagai statistik (termasuk AUC) tertanam:
library(Epi)
ROC(testres, truestat) # also try adding plot="sp"
Paket pROC
Saya juga suka pROC
paketnya, karena bisa memperlancar estimasi ROC (dan menghitung estimasi AUC berdasarkan ROC yang dihaluskan):
(Garis merah adalah ROC asli, dan garis hitam adalah ROC yang diperhalus. Juga perhatikan rasio aspek 1: 1 standar. Masuk akal untuk menggunakan ini, karena baik sensitivitas dan spesifisitas memiliki rentang 0-1.)
Taksiran AUC dari ROC yang dihaluskan adalah 0,9107, mirip dengan, tetapi sedikit lebih besar dari, AUC dari ROC yang tidak digerakkan (jika Anda melihat gambar, Anda dapat dengan mudah melihat mengapa itu lebih besar). (Meskipun kami benar-benar memiliki terlalu sedikit kemungkinan nilai hasil tes yang berbeda untuk menghitung AUC yang lancar).
Paket rms
rms
Paket Harrell dapat menghitung berbagai statistik konkordansi terkait menggunakan rcorr.cens()
fungsi. The C Index
output-nya adalah AUC:
> library(rms)
> rcorr.cens(testres,truestat)[1]
C Index
0.8931711
Paket caTools
Akhirnya, kami memiliki caTools
paket dan colAUC()
fungsinya. Ini memiliki beberapa keunggulan dibandingkan paket lain (terutama kecepatan dan kemampuan untuk bekerja dengan data multi-dimensi - lihat ?colAUC
) yang terkadang dapat membantu. Tetapi tentu saja itu memberikan jawaban yang sama seperti yang telah kita hitung berulang-ulang:
library(caTools)
colAUC(testres, truestat, plotROC=TRUE)
[,1]
0 vs. 1 0.8931711
Kata-kata terakhir
Banyak orang tampaknya berpikir bahwa AUC memberi tahu kita seberapa 'baik' suatu tes. Dan beberapa orang berpikir bahwa AUC adalah probabilitas bahwa tes akan mengklasifikasikan pasien dengan benar. Hal ini tidak . Seperti yang dapat Anda lihat dari contoh dan perhitungan di atas, AUC memberi tahu kami sesuatu tentang keluarga tes, satu tes untuk setiap kemungkinan cutoff.
Dan AUC dihitung berdasarkan cutoff yang tidak akan pernah digunakan dalam praktik. Mengapa kita harus peduli dengan sensitivitas dan spesifisitas dari nilai batas 'tidak masuk akal'? Namun, itulah yang menjadi dasar AUC (sebagian). (Tentu saja, jika AUC sangat dekat dengan 1, hampir setiap tes yang memungkinkan akan memiliki kekuatan diskriminatif yang besar, dan kita semua akan sangat bahagia.)
Interpretasi pasangan 'acak normal-abnormal' dari AUC bagus (dan dapat diperpanjang, misalnya untuk model bertahan hidup, di mana kita melihat apakah itu orang dengan bahaya tertinggi (relatif) yang meninggal paling awal). Tetapi seseorang tidak akan pernah menggunakannya dalam praktik. Ini adalah kasus yang jarang terjadi di mana seseorang tahu seseorang memiliki satu orang sehat dan satu orang sakit, tidak tahu orang mana yang sakit, dan harus memutuskan yang mana dari mereka untuk dirawat. (Bagaimanapun, keputusan itu mudah; perlakukan orang yang dengan risiko tertinggi yang diperkirakan.)
Jadi saya pikir mempelajari kurva ROC yang sebenarnya akan lebih berguna daripada hanya melihat ukuran ringkasan AUC. Dan jika Anda menggunakan ROC bersama dengan (perkiraan) biaya positif palsu dan negatif palsu, bersama dengan tarif dasar dari apa yang Anda pelajari, Anda bisa mendapatkan tempat.
Perhatikan juga bahwa AUC hanya mengukur diskriminasi , bukan kalibrasi. Artinya, ini mengukur apakah Anda dapat membedakan antara dua orang (satu sakit dan satu sehat), berdasarkan skor risiko. Untuk ini, ini hanya melihat nilai risiko relatif (atau peringkat, jika Anda mau, lih. Interpretasi tes Wilcoxon-Mann-Whitney), bukan yang absolut, yang harus Anda minati. Misalnya, jika Anda membagi masing-masing risiko estimasi dari model logistik Anda sebesar 2, Anda akan mendapatkan AUC (dan ROC) yang persis sama.
Saat mengevaluasi model risiko, kalibrasi juga sangat penting. Untuk memeriksa ini, Anda akan melihat semua pasien dengan skor risiko sekitar, misalnya 0,7, dan melihat apakah sekitar 70% dari mereka benar-benar sakit. Lakukan ini untuk setiap kemungkinan skor risiko (mungkin menggunakan semacam perataan / regresi lokal). Plot hasilnya, dan Anda akan mendapatkan kalibrasi ukuran grafis .
Jika memiliki model dengan baik kalibrasi yang baik dan diskriminasi yang baik, maka Anda mulai memiliki model yang baik. :)