수동으로 곡선 아래 면적 (AUC) 또는 c- 통계량을 계산하는 방법


78

이진 로지스틱 회귀 모델의 수작업으로 곡선 아래 면적 (AUC) 또는 c- 통계량을 계산하는 데 관심이 있습니다.

예를 들어, 유효성 검사 데이터 집합에서 종속 변수에 대한 실제 값, 보존 (1 = 유지; 0 = 유지되지 않음)은 다음과 같은 모형을 사용하여 회귀 분석에 의해 생성 된 각 관측치의 예측 보존 상태를 갖습니다. 훈련 세트를 사용하여 작성됩니다 (0에서 1까지).

저의 초기 생각은 "정확한"모델 분류 수를 식별하고 "정확한"관측 수를 총 관측 수로 나누어 c- 통계량을 계산하는 것입니다. "정확한"기준, 관측치의 실제 보유 상태가 1이고 예측 된 보유 상태가> 0.5이면 "정확한"분류입니다. 또한 관측치의 실제 보유 상태 = 0이고 예측 된 보유 상태가 <0.5 인 경우 "정확한"분류이기도합니다. 예측 값이 0.5 일 때 "tie"가 발생한다고 가정하지만 유효성 검사 데이터 세트에서 해당 현상이 발생하지 않습니다. 반면, "정확하지 않은"분류는 관측치의 실제 보유 상태 = 1이고 예측 된 보유 상태가 <0 인 경우입니다. 5 또는 결과의 실제 보존 상태가 0이고 예측 보존 상태가> 0.5 인 경우. 나는 TP, FP, FN, TN을 알고 있지만이 정보가 주어지면 c 통계를 계산하는 방법을 알지 못합니다.

답변:


115

Hanley 's & McNeil의 1982 년 논문 ' ROC (수신기 동작 특성) 곡선 아래 영역의 의미와 사용 '을 추천합니다.

다음과 같은 질병 상태 및 검사 결과 표가 있습니다 (예 : 물류 모델의 예상 위험에 해당). 오른쪽의 첫 번째 숫자는 실제 질병 상태가 '정상'인 환자의 수이고 두 번째 숫자는 실제 질병 상태가 '비정상' 인 환자의 수입니다 .

(1) 확실히 정상 : 33/3
(2) 아마 정상 : 6/2
(3) 의심스러운 : 6/2
(4) 아마도 비정상 : 11/11
(5) 확실히 비정상 : 2/33

따라서 총 58 명의 '정상적인'환자와 '51'의 비정상적인 환자가 있습니다. 예측 변수가 1, '정확히 정상'인 경우 환자는 일반적으로 정상이며 (36 명의 환자 중 33 명에 대해 참), 5 일 때 '확실히 비정상적인'환자는 일반적으로 비정상입니다 ( 35 명의 환자), 예측자가 의미가 있습니다. 그러나 2, 3 또는 4 점의 환자를 어떻게 판단해야합니까? 결과 검사의 민감도와 특이성을 결정하기 위해 환자를 비정상 또는 정상으로 판단하기 위해 컷오프를 설정했습니다.

감도와 특이성

다른 컷오프에 대한 추정 감도 및 특이도를 계산할 수 있습니다 . (이제부터는 '민감도'와 '특이성'을 작성하여 값의 추정 특성을 암시합니다.)

검사 결과에 상관없이 모든 환자를 비정상으로 분류하기 위해 컷오프를 선택하면 (즉, 컷오프 1+를 선택하더라도) 감도는 51/51 = 1이됩니다. 특이도는 0입니다. / 58 = 0. 소리가 잘 들리지 않습니다.

이제 덜 엄격한 컷오프를 선택하겠습니다. 검사 결과가 2 이상인 환자 만 비정상으로 분류합니다. 그런 다음 3 명의 비정상 환자를 그리워하고 48/51 = 0.94의 감도를 갖습니다. 그러나 우리는 33/58 = 0.57의 훨씬 더 높은 특이성을 가지고 있습니다.

이제 다양한 컷오프 (3, 4, 5,> 5)를 선택하여이 작업을 계속할 수 있습니다. (마지막으로, 우리는 가능한 가장 높은 시험 점수가 5 인 경우에도 환자를 비정상으로 분류 하지 않습니다 .)

ROC 곡선

가능한 모든 컷오프에 대해이 작업을 수행하고 1에서 특이성을 뺀 민감도를 플롯하면 ROC 곡선이 나타납니다. 다음과 같은 R 코드를 사용할 수 있습니다.

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

출력은 다음과 같습니다.

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

다양한 통계를 계산할 수 있습니다.

( 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

이를 사용하여 (추정) ROC 곡선을 그릴 수 있습니다.

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 곡선

AUC 수동 계산

사다리꼴 면적에 대한 공식을 사용하여 ROC 곡선 아래 면적을 매우 쉽게 계산할 수 있습니다.

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

결과는 0.8931711입니다.

일치 측정

AUC는 또한 일치 측정으로 볼 수 있습니다. 우리는 모든 가능한 걸릴 경우 하나가 정상이고 다른 하나는 비정상이다 환자를, 우리는 (가장 높은 (가장 '비정상 보이는')의 테스트 결과가 비정상 하나 빈도를 계산할 수 있습니다 그들은 같은 값이있는 경우, 우리 이것을 '승리의 절반'으로 세십시오).

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

답은 다시 ROC 곡선 아래 인 0.8931711입니다. 항상 그렇습니다.

일치의 그래픽보기

Harrell이 그의 답변에서 지적했듯이 이것은 그래픽으로 해석됩니다. y 축 에 대한 테스트 점수 (위험 추정치) 와 x 축 에 대한 실제 질병 상태 (여기서 약간의 지 터링이 있음)를 표시합니다.

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

실제 질병 상태에 대한 위험 점수의 산포도.

이제 왼쪽의 각 지점 ( '정상'환자)과 오른쪽의 각 지점 ( '비정상'환자) 사이에 선을 그리겠습니다. 양의 기울기를 가진 선의 비율 (즉, 일치 쌍 의 비율 )은 일치 지수 (평평한 선은 '50 % 일치 '로 계산)입니다.

동점 수 (동일한 위험 점수)로 인해이 예제의 실제 선을 시각화하는 것은 약간 어렵지만 약간의 지 터링과 투명성을 통해 합리적인 플롯을 얻을 수 있습니다.

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

가능한 모든 관찰 쌍 사이에 선이있는 실제 질병 상태에 대한 위험 점수의 산포도.

우리는 대부분의 선이 위쪽으로 기울어 짐에 따라 일치 지수가 높아질 것입니다. 또한 각 유형의 관측 쌍에서 지수에 대한 기여도를 볼 수 있습니다. 그것의 대부분은 위험 점수가 1 인 정상 환자와 위험 점수가 5 (1-5 쌍) 인 비정상 환자와 짝을 이루고 있지만, 1-4 쌍과 4-5 쌍에서도 상당히 많습니다. 그리고 경사 정의를 기반으로 실제 일치 지수를 계산하는 것은 매우 쉽습니다.

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

대답은 다시 0.8931711, 즉 AUC입니다.

Wilcoxon–Mann–Whitney 테스트

일치 측정과 Wilcoxon–Mann-Whitney 테스트 간에는 밀접한 관련이 있습니다. 실제로 후자는 일치 확률 (즉, 가장 '비정상적인'테스트 결과 를 갖는 임의의 정상-비정상 쌍 에서 비정상 환자 임을 확인)이 정확히 0.5인지 테스트합니다. 테스트 통계량은 추정 된 일치 성 확률의 간단한 변환 일뿐입니다.

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

검정 통계량 ( W = 2642)은 일치 쌍의 수를 계산합니다. 가능한 쌍의 수로 나누면 가족 수가 생깁니다.

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

예, ROC 곡선 아래 인 0.8931711입니다.

보다 쉬운 AUC 계산 방법 (R)

그러나 우리 자신을 위해 인생을 더 편하게합시다. 우리를 위해 자동으로 AUC를 계산하는 다양한 패키지가 있습니다.

Epi 패키지

Epi패키지는 다양한 통계 (AUC 포함)가 포함 된 멋진 ROC 곡선을 만듭니다.

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

Epi 패키지의 ROC 곡선

pROC 패키지

pROCROC 추정치를 매끄럽게 할 수 있고 (매끄러운 ROC를 기반으로 AUC 추정치를 계산할 수 있기 때문에) 패키지 도 좋아합니다 .

pROC 패키지의 ROC 곡선 (부드럽 지 않고 매끄럽게)

(빨간색 선은 원래 ROC이고 검은 색 선은 매끄럽게 된 ROC입니다. 기본 1 : 1 종횡비에 유의하십시오. 감도와 특이도는 모두 0-1 범위이므로이를 사용하는 것이 좋습니다.)

평활 ROC 의 추정 AUC 는 0.9107이며 평활 ROC의 AUC 와 비슷하지만 약간 더 큽니다 (그림을 보면 왜 더 큰지 쉽게 알 수 있습니다). (실제로 AUC를 계산할 수있는 고유 한 테스트 결과 값이 너무 적습니다).

rms 패키지

하렐의 rms패키지는 사용하여 다양한 관련 용어 색인 통계를 계산할 수 있습니다 rcorr.cens()기능. C Index그 출력은 AUC이다 :

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

caTools 패키지

마지막으로 caTools패키지와 colAUC()기능이 있습니다. 때로는 도움이 될 ?colAUC수 있는 다른 패키지 (주로 속도 및 다차원 데이터 작업 기능 – 참조 )에 비해 몇 가지 장점 이 있습니다 . 그러나 물론 우리가 반복해서 계산 한 것과 같은 대답을 제공합니다.

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

caTools 패키지의 ROC 곡선

마지막 단어

많은 사람들이 AUC가 시험이 얼마나 '좋은'지를 말해 준다고 생각하는 것 같습니다. 그리고 어떤 사람들은 AUC가 검사가 환자를 올바르게 분류 할 확률이라고 생각합니다. 그것은이다 없습니다 . 위의 예와 계산에서 볼 수 있듯이 AUC는 가능한 각 컷오프마다 하나씩 테스트 패밀리 에 대해 알려줍니다 .

AUC는 실제로 사용하지 않는 컷오프를 기준으로 계산됩니다. '무의미한'차단 값의 민감도와 특이성에 관심을 가져야하는 이유는 무엇입니까? 여전히 AUC는 (부분적으로) 기반입니다. (물론 AUC가 1에 매우 가까우면 거의 모든 가능한 테스트에 큰 차별 력이 있으며, 우리는 모두 매우 행복 할 것입니다.)

AUC의 '무작위 정상-비정상'페어 해석은 훌륭합니다 (예를 들어 생존 모델로 확장 될 수 있으며, 여기서 가장 높은 (상대) 위험이있는 사람이 가장 빨리 사망하는지 확인). 그러나 실제로는 사용하지 않을 것입니다. 그것은 하나는 드문 경우입니다 알고 하나가 하나의 건강하고 하나 , 아픈 사람을 병 하나입니다 사람을 알고하지 않으며, 치료하는 그들의 결정해야합니다. (어쨌든 결정은 쉬우므로 추정 위험이 가장 높은 결정을 처리하십시오.)

따라서 실제 ROC 곡선을 연구하는 것이 AUC 요약 측정법을 보는 것보다 더 유용 하다고 생각 합니다. 그리고 ROC 를 오탐 (false positive) 및 오탐 (false negative ) 비용 (추정치) 과 함께 연구 대상의 기본 요율과 함께 사용하면 어딘가에 갈 수 있습니다.

또한 AUC는 교정이 아닌 차별 만 측정 합니다. 즉, 위험 점수에 따라 두 사람 (한 사람과 건강한 사람)을 구별 할 수 있는지 여부를 측정합니다. 이를 위해 관심 있는 절대 값이 아닌 상대 위험 값 (또는 윌 콕슨-맨-휘트니 테스트 해석 참조) 만 조사 합니다 . 예를 들어, 각 위험을 나누는 경우 로지스틱 모델에서 2를 추정하면 정확히 동일한 AUC (및 ROC)를 얻게됩니다.

위험 모델을 평가할 때는 교정 도 매우 중요합니다. 이를 검사하기 위해 위험 점수 (예 : 0.7)가있는 모든 환자를 살펴보고 이들 중 약 70 %가 실제로 아픈지 확인합니다. 가능한 모든 위험 점수에 대해이 작업을 수행하십시오 (일부 스무딩 / 로컬 회귀 분석 사용). 결과를 플롯하면 그래픽 보정 측정 값을 얻게 됩니다.

와 모델이있는 경우 모두 좋은 교정과 좋은 차별, 당신은 좋은 모델을 가지고 시작합니다. :)


8
@Karl Ove Hufthammer에게 감사드립니다. 이것이 내가받은 가장 철저한 답변입니다. 특히 "최종 단어"섹션에 감사드립니다. 잘했습니다! 다시 감사합니다!
Matt Reichenbach

이 자세한 답변에 감사드립니다. 나는 Epi :: ROC () v2.2.6이 AUC가 1.62 (정신주의 연구가 아님)라고 확신하는 데이터 세트를 사용하고 있지만 ROC에 따르면 0.56에서 위 코드 결과가 훨씬 더 믿습니다. in.
BurninLeo

32

이 질문을 살펴보십시오 : ROC 곡선 이해

ROC 곡선을 만드는 방법은 다음과 같습니다.

ROC 곡선 그리기

순위 분류 기가 처리 한 데이터 세트

  • 점수 감소에 대한 순위 테스트 예
  • 에서 시작(0,0)
  • x
    • x1/pos
    • x1/neg

posneg

이 알고리즘을 사용하여 다음 알고리즘을 사용하여 AUC ROC를 수동으로 계산할 수 있습니다.

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

이 멋진 gif 애니메이션 그림은이 과정을 명확하게 설명해야합니다.

커브 만들기


1
@Alexey Grigorev에게 감사합니다. 이것은 훌륭한 시각 자료이며 앞으로 유용 할 것입니다! +1
Matt Reichenbach

1
"긍정적 및 부정적 예의 분수"에 대해 조금 설명해 주시겠습니까? 두 축의 최소 단위 값을 의미합니까?
Allan Ruin

1
@Allan Ruin : pos여기서 긍정적 인 데이터의 수를 의미합니다. 11 개의 점이 1 인 20 개의 데이터 점이 있다고 가정합니다. 따라서 차트를 그릴 때 직사각형은 11x9 (높이 x 너비)입니다. Alexey Grigorev는 확장했지만 원하는대로 그대로 두었습니다. 이제 각 단계에서 차트에서 1을 이동하십시오.
Catbuilts

5

Karl의 게시물에는 훌륭한 정보가 많이 있습니다. 그러나 나는 지난 20 년 동안 누군가의 생각을 좋은 방향으로 바꾸는 ROC 곡선의 예를 아직 보지 못했습니다. 겸손한 견해에서 ROC 곡선의 유일한 가치는 그 영역이 매우 유용한 일치 확률과 같다는 것입니다. ROC 곡선 자체는 독자가 컷오프를 사용하도록 유혹합니다.

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

n

R Hmisc패키지 rcorr.cens기능의 경우 전체 결과를 인쇄하여 자세한 정보, 특히 표준 오류를보십시오.


@Frank Harell에게 감사합니다. 귀하의 관점에 감사드립니다. 나는 컷오프를 좋아하지 않기 때문에 단순히 c- 통계량을 일치 확률로 사용합니다. 다시 감사합니다!
Matt Reichenbach

4

다음은 단순히 사다리꼴 규칙을 사용하여 ROC 곡선 아래 영역을 가져 와서 AUC를 계산하는 자연스러운 방법의 대안입니다.

AUC는 무작위로 샘플링 된 양성 관측치가 무작위로 샘플링 된 음성 관측치보다 예측 확률 (양수)이 클 확률과 같습니다. 이 기능을 사용하면 양성 및 음성 관측 값의 쌍별 조합을 통해 프로그래밍 언어에서 AUC를 매우 쉽게 계산할 수 있습니다. 표본 크기가 너무 큰 경우 관측치를 무작위로 표본 추출 할 수도 있습니다. 펜과 종이를 사용하여 AUC를 계산하려는 경우 샘플이 적거나 시간이 많지 않으면 이것이 최선의 방법이 아닐 수 있습니다. 예를 들어 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

pROC패키지를 사용하여 확인할 수 있습니다 .

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

무작위 샘플링 사용 :

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

1
  1. 관측 값에 대한 진정한 가치가 있습니다.
  2. 사후 확률을 계산 한 다음이 확률로 관측 값의 순위를 매 깁니다.
  3. PN
    Sum of true ranks0.5PN(PN+1)PN(NPN)

1
@ user73455 ... 1) 예, 관측 값이 참입니다. 2) 사후 확률은 각 관측치에 대한 예측 확률과 동의어입니까? 3) 이해; 그러나 "진정한 계급"이란 무엇이며이 값을 어떻게 계산합니까? 어쩌면 예를 통해이 답변을보다 철저하게 설명하는 데 도움이됩니까? 감사합니다!
Matt Reichenbach
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.