본 게시글은 ROC 기반하여 Sensitivity와 Specificity의 합을 최대로 하는 지점을 찾아주는 방법인 Youden's J Index에 대해 소개하고자 한다.
이진분류 문제에서 특정 id를 1로 분류할 cut-off을 결정 할 때,
Sensitivity와 Specificity를 균형있게 고려할 필요가 있으며 이때 Youden Index를 사용할 수 있다.
본 게시글은 R의 'pROC'와 'cutpointr' 패키지를 사용하여, youden index를 계산하는 두 가지 방법을 소개하고자 한다.
0. 준비
분석을 준비하기 위해 필요한 패키지와 예시 데이터를 준비한다.
library(pROC)
library(cutpointr)
data(suicide)
head(suicide)
# age gender dsi suicide
# 1 29 female 1 no
# 2 26 male 0 no
# 3 26 female 0 no
# 4 27 female 0 no
# 5 28 female 0 no
예측된 결과 값을 기반하여 ROC 를 그릴 수 있기 때문에,
예시로 아래의 일반화 선형 모형을 사용하여 예측 값을 계산해 둔다.
n <- nrow(suicide)
tr_n <- round(n*0.8)
idx <- sample(n)
# train - test 분리
tr_idx <- idx[1:tr_n]; test_idx <- setdiff(idx, tr_idx)
tr_dat <- suicide[tr_idx,]; test_dat <- suicide[test_idx, ]
# 모형 적합
fit <- glm(suicide ~ age + gender + dsi, data=tr_dat, family='binomial') # prediction model
# suicide = yes 확률 값 계산
pred_y <- predict(fit, test_dat, "response")
1. ROC와 AUC 계산
roc는 pROC 패키지를 통해, 계산할 수 있다.
my_roc <- pROC::roc(test_dat$suicide, pred_y)
my_roc
# Call:
# roc.default(response = test_dat$suicide, predictor = pred_y)
#
# Data: pred_y in 96 controls (test_dat$suicide no) < 10 cases (test_dat$suicide yes).
# Area under the curve: 0.9479
my_roc$AUC
# Area under the curve: 0.9479
ROC는 다음과 같이 그릴 수 있다.
ROC 는 0~1 사이의 다양한 cut-off를 모두 고려하였을 때의 y축을 Sensitivity, x축을 1-Speicificity 값을 시각화하는 방법으로 모형 성능을 나타낸다.
이때 해당 선 아래의 너비를 AUC라 부르며, ROC를 요약하여 AUC만을 보고하는 경우도 많다.
plot(my_roc)
2. Youden Index
일반적으로 확률 값을 예측했을 때 0.5를 기준으로 0.5보다 크면 1, 작으면 0으로 분류한다.
하지만, 데이터의 균형이 굉장히 깨져있는 경우에, 0.5라는 기준이 제대로 작동하지 않을 수 있다.
이 cut-off의 값의 크기에 따라 Sensitivity와 Specificity 사이의 Trade-off가 일어나기 때문에 적절한 값을 설정하는 것이 어려울 수 있다.
이때, Youden 방법은 Sensitivity + Speicficity + 1이 가장 크게 하는 cut-off 값을 채택한다.
이를 그림으로 나타내면 아래와 같다. 결국 기울기가 1인 직선과 roc와 만나는 점을 채택하는 것을 의미한다. 해당 지점이 Sensitivity와 Specificity의 합을 최대로 하는 지점이다.
먼저 pROC 패키지를 사용해서 구하는 방법이다.
위의 roc 오브젝트에서 youden 방법으로 구한 최고의 sensitivity 값과 specificity값을 알려준다.
coords(my_roc, "best", best.method="youden")
# threshold specificity sensitivity
# 1 0.04378208 0.8958333 1
다음으로 cutpointr 패키지를 사용하는 방법이다. cutpointr의 경우 더욱 친절하게 값을 제공해 준다.
cutpointr(x=pred_y, class=test_dat$suicide, metric = youden)
# Assuming the positive class is yes
# Assuming the positive class has higher x values
# # A tibble: 1 x 16
# direction optimal_cutpoint method youden acc sensitivity specificity AUC pos_class neg_class prevalence outcome predictor data
# 1 >= 0.0509530 maximize_metric 0.895833 0.905660 1 0.895833 0.947917 yes no 0.0943396 class x <tibble [106 x 2]>
# roc_curve boot
# 1 <rc_ctpnt [71 x 10]> NA
Reference
https://cran.r-project.org/web/packages/cutpointr/vignettes/cutpointr.html
An introduction to cutpointr
Finding all cutpoints with acceptable performance By default, most packages only return the “best” cutpoint and disregard other cutpoints with quite similar performance, even if the performance differences are minuscule. cutpointr makes this process mo
cran.r-project.org