Tôi muốn giới thiệu bài viết năm 1982 của Hanley & McNeil ' Ý nghĩa và việc sử dụng khu vực dưới đường cong đặc tính vận hành máy thu (ROC) '.
Thí dụ
Họ có bảng tình trạng bệnh và kết quả xét nghiệm sau đây (tương ứng với, ví dụ, rủi ro ước tính từ một mô hình logistic). Số đầu tiên bên phải là số bệnh nhân có tình trạng bệnh thật 'bình thường' và số thứ hai là số bệnh nhân có tình trạng bệnh thật 'bất thường':
(1) Chắc chắn là bình thường: 33/3
(2) Có lẽ là bình thường: 6/2
(3) Câu hỏi: 6/2
(4) Có thể là bất thường: 11/11
(5) Chắc chắn là bất thường: 2/33
Vì vậy, có tổng số 58 bệnh nhân 'bình thường' và '51' bất thường. Chúng tôi thấy rằng khi dự đoán là 1, 'Chắc chắn là bình thường', bệnh nhân thường bình thường (đúng với 33 trong số 36 bệnh nhân) và khi đó là 5, 'Chắc chắn là bất thường', bệnh nhân thường bất thường (đúng với 33 35 bệnh nhân), vì vậy người dự đoán có ý nghĩa. Nhưng làm thế nào chúng ta nên đánh giá một bệnh nhân có điểm 2, 3 hoặc 4? Những gì chúng tôi đặt ra cho điểm cắt của chúng tôi để đánh giá một bệnh nhân là bất thường hoặc bình thường để xác định độ nhạy và độ đặc hiệu của xét nghiệm kết quả.
Độ nhạy và độ đặc hiệu
Chúng tôi có thể tính toán độ nhạy và độ đặc hiệu ước tính cho các điểm cắt khác nhau. (Tôi sẽ chỉ viết 'độ nhạy' và 'độ đặc hiệu' từ bây giờ, để cho tính chất ước tính của các giá trị được ẩn.)
Nếu chúng tôi chọn mức cắt của chúng tôi để chúng tôi phân loại tất cả các bệnh nhân là bất thường, bất kể kết quả xét nghiệm của họ nói gì (nghĩa là chúng tôi chọn mức cắt 1+), chúng tôi sẽ có độ nhạy 51/51 = 1. Độ đặc hiệu sẽ là 0 / 58 = 0. Nghe không hay lắm.
OK, vì vậy hãy chọn một điểm cắt ít nghiêm ngặt hơn. Chúng tôi chỉ phân loại bệnh nhân là bất thường nếu họ có kết quả xét nghiệm từ 2 trở lên. Sau đó chúng tôi bỏ lỡ 3 bệnh nhân bất thường và có độ nhạy 48/51 = 0,94. Nhưng chúng tôi có độ đặc hiệu tăng lên nhiều, là 33/58 = 0,57.
Bây giờ chúng ta có thể tiếp tục điều này, chọn các điểm cắt khác nhau (3, 4, 5,> 5). (Trong trường hợp cuối cùng, chúng tôi sẽ không phân loại bất kỳ bệnh nhân nào là bất thường, ngay cả khi họ có điểm kiểm tra cao nhất có thể là 5.)
Đường cong ROC
Nếu chúng ta làm điều này cho tất cả các điểm cắt có thể và biểu đồ độ nhạy so với 1 trừ đi độ đặc hiệu, chúng ta sẽ có đường cong ROC. Chúng ta có thể sử dụng mã R sau:
# 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)) )
Đầu ra là:
testres
truestat 1 2 3 4 5
0 33 6 6 11 2
1 3 2 2 11 33
Chúng tôi có thể tính toán các số liệu thống kê khác nhau:
( 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
Và bằng cách sử dụng này, chúng ta có thể vẽ đường cong ROC (ước tính):
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)
Tính toán thủ công AUC
Chúng ta có thể dễ dàng tính toán diện tích dưới đường cong ROC, sử dụng công thức cho diện tích của hình thang:
height = (sens[-1]+sens[-length(sens)])/2
width = -diff(omspec) # = diff(rev(omspec))
sum(height*width)
Kết quả là 0,8931711.
Một biện pháp phù hợp
AUC cũng có thể được coi là một biện pháp phù hợp. Nếu chúng tôi có tất cả các cặp bệnh nhân có thể có một bệnh nhân bình thường và một bệnh nhân khác thường, chúng tôi có thể tính toán mức độ thường xuyên của một bệnh nhân có kết quả xét nghiệm cao nhất (trông có vẻ bất thường nhất) (nếu chúng có cùng giá trị, chúng tôi tính rằng đây là 'một nửa chiến thắng'):
o = outer(abnorm, norm, "-")
mean((o>0) + .5*(o==0))
Câu trả lời là một lần nữa 0.8931711, khu vực dưới đường cong ROC. Điều này sẽ luôn luôn là trường hợp.
Một cái nhìn đồ họa của sự phù hợp
Như được chỉ ra bởi Mitchell trong câu trả lời của mình, điều này cũng có một cách giải thích đồ họa. Hãy cho điểm kiểm tra đồ thị (ước tính rủi ro) trên y -axis và tình trạng bệnh thực sự trên x -axis (ở đây với một số biến động, để hiển thị các điểm chồng chéo):
plot(jitter(truestat,.2), jitter(testres,.8), las=1,
xlab="True disease status", ylab="Test score")
Bây giờ chúng ta hãy vẽ một đường giữa mỗi điểm bên trái (một bệnh nhân 'bình thường') và mỗi điểm ở bên phải (một bệnh nhân 'bất thường'). Tỷ lệ đường có độ dốc dương tính (ví dụ, tỷ lệ chỉnh hợp cặp) là chỉ số sự phù hợp (đường phẳng được tính là '50% sự phù hợp ').
Thật khó để hình dung các dòng thực tế cho ví dụ này, do số lượng mối quan hệ (điểm rủi ro bằng nhau), nhưng với một số sự lộn xộn và minh bạch, chúng ta có thể có được một âm mưu hợp lý:
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))
Chúng tôi thấy rằng hầu hết các đường dốc lên, vì vậy chỉ số phù hợp sẽ cao. Chúng tôi cũng thấy sự đóng góp cho chỉ số từ mỗi loại cặp quan sát. Hầu hết đến từ những bệnh nhân bình thường có điểm rủi ro là 1 cặp với những bệnh nhân bất thường có điểm rủi ro là 5 (1 cặp5), nhưng khá nhiều cũng đến từ 1 cặp4 và 4 cặp5. Và thật dễ dàng để tính toán chỉ số phù hợp thực tế dựa trên định nghĩa độ dốc:
d = transform(d, slope=(y_norm-y_abnorm)/(x_norm-x_abnorm))
mean((d$slope > 0) + .5*(d$slope==0))
Câu trả lời là một lần nữa 0.8931711, tức là AUC.
Thử nghiệm Wilcoxonon MannTHER Whitney
Có một mối liên hệ chặt chẽ giữa biện pháp phù hợp và thử nghiệm WilcoxonTHER MannTHER Whitney. Trên thực tế, các xét nghiệm sau nếu xác suất phù hợp (nghĩa là bệnh nhân bất thường trong một cặp bất thường bình thường ngẫu nhiên bình thường sẽ có kết quả xét nghiệm 'bất thường' nhất) là chính xác 0,5. Và thống kê kiểm tra của nó chỉ là một biến đổi đơn giản của xác suất phù hợp ước tính:
> ( 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
Thống kê kiểm tra ( W = 2642
) đếm số lượng các cặp tương ứng. Nếu chúng ta chia nó cho số lượng các cặp có thể, chúng ta sẽ nhận được một số gia đình:
w = wi$statistic
w/(length(abnorm)*length(norm))
Vâng, đó là 0,8931711, khu vực dưới đường cong ROC.
Các cách dễ dàng hơn để tính AUC (tính bằng R)
Nhưng hãy làm cho cuộc sống của chúng ta dễ dàng hơn. Có nhiều gói tính toán AUC cho chúng tôi tự động.
Gói Epi
Các Epi
gói tạo ra một đường cong ROC tốt đẹp với các thống kê khác nhau (bao gồm cả AUC) được nhúng:
library(Epi)
ROC(testres, truestat) # also try adding plot="sp"
Gói pROC
Tôi cũng thích pROC
gói này, vì nó có thể làm mịn ước tính ROC (và tính toán ước tính AUC dựa trên ROC được làm mịn):
(Đường màu đỏ là ROC gốc và đường màu đen là ROC được làm mịn. Ngoài ra, hãy lưu ý tỷ lệ khung hình 1: 1 mặc định. Thật hợp lý khi sử dụng điều này, vì cả độ nhạy và độ đặc hiệu đều có phạm vi 01 .1).
AUC ước tính từ ROC được làm mịn là 0,9107, tương tự, nhưng lớn hơn một chút so với AUC từ ROC không phẳng (nếu bạn nhìn vào hình, bạn có thể dễ dàng thấy tại sao nó lớn hơn). (Mặc dù chúng tôi thực sự có quá ít giá trị kết quả kiểm tra khác biệt có thể để tính toán AUC trơn tru).
Gói rms
rms
Gói củaellell có thể tính toán các số liệu thống kê phù hợp liên quan khác nhau bằng cách sử dụng rcorr.cens()
hàm. Đầu C Index
ra của nó là AUC:
> library(rms)
> rcorr.cens(testres,truestat)[1]
C Index
0.8931711
Gói caTools
Cuối cùng, chúng ta có caTools
gói và colAUC()
chức năng của nó . Nó có một vài lợi thế so với các gói khác (chủ yếu là tốc độ và khả năng làm việc với dữ liệu đa chiều - xem ?colAUC
) đôi khi có thể hữu ích. Nhưng tất nhiên nó cho câu trả lời giống như chúng ta đã tính toán nhiều lần:
library(caTools)
colAUC(testres, truestat, plotROC=TRUE)
[,1]
0 vs. 1 0.8931711
Từ cuối cùng
Nhiều người dường như nghĩ rằng AUC cho chúng ta biết bài kiểm tra 'tốt' như thế nào. Và một số người nghĩ rằng AUC là xác suất mà xét nghiệm sẽ phân loại chính xác một bệnh nhân. Nó không phải là . Như bạn có thể thấy từ ví dụ và tính toán ở trên, AUC cho chúng ta biết điều gì đó về một gia đình thử nghiệm, một thử nghiệm cho mỗi lần cắt có thể.
Và AUC được tính toán dựa trên mức cắt mà người ta sẽ không bao giờ sử dụng trong thực tế. Tại sao chúng ta nên quan tâm đến độ nhạy và độ đặc hiệu của các giá trị ngưỡng 'vô nghĩa'? Tuy nhiên, đó là những gì AUC (một phần) dựa trên. (Tất nhiên, nếu AUC rất gần với 1, hầu hết mọi bài kiểm tra có thể sẽ có sức mạnh phân biệt đối xử lớn, và tất cả chúng ta sẽ rất hạnh phúc.)
Cách giải thích cặp 'AUC bình thường ngẫu nhiên' của AUC là tốt (ví dụ, có thể được mở rộng cho các mô hình sống sót, trong đó chúng ta thấy nếu đó là người có nguy cơ (tương đối) cao nhất chết sớm nhất). Nhưng người ta sẽ không bao giờ sử dụng nó trong thực tế. Đó là một trường hợp hiếm hoi khi người ta biết một người khỏe mạnh và một người bệnh, không biết người nào là người bệnh và phải quyết định điều trị cho ai. (Trong mọi trường hợp, quyết định là dễ dàng; đối xử với người có rủi ro ước tính cao nhất.)
Vì vậy, tôi nghĩ rằng nghiên cứu đường cong ROC thực tế sẽ hữu ích hơn là chỉ nhìn vào thước đo tóm tắt của AUC. Và nếu bạn sử dụng ROC cùng với (ước tính) chi phí của dương tính giả và âm tính giả, cùng với tỷ lệ cơ bản của những gì bạn đang học, bạn có thể nhận được ở đâu đó.
Cũng lưu ý rằng AUC chỉ đo lường sự phân biệt đối xử , không hiệu chuẩn. Đó là, nó đo lường xem bạn có thể phân biệt giữa hai người (một người ốm và một người khỏe mạnh) hay không, dựa trên điểm số rủi ro. Đối với điều này, nó chỉ xem xét các giá trị rủi ro tương đối (hoặc xếp hạng, nếu bạn muốn, xem diễn giải thử nghiệm WilcoxonTHER MannTHER Whitney), chứ không phải các giá trị tuyệt đối, mà bạn nên quan tâm. Ví dụ: nếu bạn chia từng rủi ro ước tính từ mô hình logistic của bạn bằng 2, bạn sẽ nhận được chính xác AUC (và ROC).
Khi đánh giá một mô hình rủi ro, hiệu chuẩn cũng rất quan trọng. Để kiểm tra điều này, bạn sẽ xem xét tất cả các bệnh nhân có điểm số rủi ro xung quanh, ví dụ 0,7 và xem liệu khoảng 70% trong số này thực sự bị bệnh. Làm điều này cho mỗi điểm rủi ro có thể (có thể sử dụng một số loại hồi quy làm mịn / hồi quy cục bộ). Vẽ các kết quả và bạn sẽ có được một phép đo hiệu chuẩn đồ họa .
Nếu có một mô hình với cả hiệu chuẩn tốt và phân biệt đối xử tốt, thì bạn bắt đầu có mô hình tốt. :)