본문 바로가기
머신러닝

머신러닝 ROC curve(커브), AUC 개념 제대로 이해하기

by 데싸루나 2023. 2. 22.

머신러닝 Classification 모델에 있어서 ROC 커브와 AUC는 몰라서는 안되는 정말 중요한 개념입니다. 이를 이해하는 데 있어 필수적으로 같이 알아야하는 Threshold, Sensitivity, Specificity 그리고 Youden Index 개념까지 함께 알아보겠습니다.

Understanding ROC curve and AUC
Understanding ROC curve and AUC

ROC 커브란?

ROC 커브는 "Receiver Operating Characteristic" 커브로 binary classification 모델의 퍼포먼스를 나타내는 그래프입니다. 그래프의 X축은 False Positive Rate(FPR) Y축은 True Positive Rate(TPR)을 나타냅니다. 모델의 Threshold가 변함에 따라 TPR과 FPR 변화 추이를 그린 그래프입니다. (Threshold가 무엇인지는 아래 설명 참고하세요) 따라서 TPR은 높고 FPR은 낮으면 완벽하게 Classification을 수행한다는 뜻으로 왼쪽 상단 쪽으로 휘어져있는 ROC 커브를 그릴수록 해당 모델의 퍼포먼스는 높다고 평가할 수 있습니다. (TPR과 FPR의 개념을 모르신다면 이 포스팅 참고하세요)

ROC curve and AUC
ROC curve and AUC

 

 

여기서 잠깐! Classification 모델의 Threshold란? 

Supervised Learning의 Classification 모델이 예측을 수행할 때 1(positive), 0(negative)와 같이 class를 예측하기 전에 먼저 1(positive)일 가능성(probability)에 대해서 예측을 수행합니다. 그런다음 Threshold를 정해서 그보다 가능성이 적으면 0(negative)으로 크면 1(positive)로 예측을 하게 되는 것이죠. 사이킷런(Scikit-learn)같은 패키지를 사용할 때 이 Threshold를 따로 정해주지 않으면 default값으로 0.5를 기준으로 class를 나누게 됩니다. 하지만 Classification 모델의 Threshold에 따라 TPR, FPR이 크게 달라지므로 ROC커브를 그려보고 왼쪽 상단 가까이에 TPR과 FPR이 위치하도록 만들어주는 Threshold를 찾아서 해당 값으로 모델을 세팅해야 합니다. 

 

이전에 Logistic Regression 모델을 설명드리면서 적절한 Threshold 찾는 방법과 중요성에 대해 설명드렸는데 해당 포스팅도 함께 참고해주세요. 

 

AUC란?

AUC는 "Area Under the ROC Curve"를 뜻하는 것으로, ROC 커브 아래 부분의 면적의 너비를 말합니다. AUC가 클수록 ROC 커브가 더욱 왼쪽 상단쪽으로 치우쳐져 있다는 것을 의미하므로, 해당 모델은 더 나은 퍼포먼스를 가진다고 볼 수 있습니다.

 

완벽한 모델의 경우 AUC는 1을 가질 것이고, 랜덤하게 추측하는 모델의 경우 반정도밖에 못 맞출 것이므로 0.5의 AUC를 가진다고 볼 수 있습니다. 

 

AUC와 ROC 커브는 어떤 경우에 활용하는지? 

앞에서 살펴본 Classification 모델의 Threshold를 구하기 위해서도 사용되고, 여러가지 모델들을 비교할 때 각 모델의 ROC 커브를 함께 그려봄으로써 가장 AUC가 넓은 모델이 무엇인지 한눈에 볼 때도 사용됩니다. 

Classification 모델 최적의 Threshold 찾는 경우

ROC curve and Threshold
ROC curve and Threshold

 

ROC 커브를 위와 같이 그려본 후 왼쪽 상단에 위치하게 하는 Threshold를 Optimal Threshold로 정하면 되겠지만 사실 그래프로 봤을 때 어떤 지점이 가장 Optimal한지 알기 힘든 경우도 있습니다. 따라서 ROC커브를 그려서 Threshold가 변함에 따라 이 모델의 퍼포먼스가 어떻게 변하는지 전반적으로 이해를 하고 각 Threshold 마다 Youden's index (Sensitivity + Spicificity - 1 또는 tpr - fpr)를 계산하여 해당 값을 Max로 만들어주는 Threshold를 Optimal Threshold로 정하는 방법이 적합합니다. 

 

 

여러가지 모델들을 비교할 경우

ROC curve and multiple classification models
ROC curve and multiple classification models

ROC커브가 위와 같이 그려져서 어떤 모델이 더 나은지 명확하게 구분이 가능한 경우도 있겠지만 아래와 같이 서로 겹치게 그려져서 눈으로는 식별이 어려운 경우가 있을 수 있습니다. 이런 경우는 ROC 커브의 아래 면적에 해당하는 AUC를 각각 계산하여 비교해야 합니다.

 

Roc curve and AUC
Roc curve and AUC

 

 

알아두면 좋은 개념 Sensitivity, Specificity

Sensitivity, Specificity는 머신러닝을 공부할 때 자주 등장하는 용어입니다. 

Sensitivity: TPR(True Positive Rate)을 가리키는 용어로, Positive로 예측된 것들 중 진짜 Positive인 것의 비율을 나타냅니다. ( TPR = TP / (TP+FN) )

Specificity : TNR(True Negative Rate)을 가리키는 용어로, Negative로 예측된 것들 중 진짜 Negative인 것의 비율을 나타냅니다. (TNF = TN / (TN + FP)) 반면에 FPR 은 FP / ( TN + FP) 이므로, 결국 Specificity = 1-FPR이라는 공식이 성립됩니다. 

 

ROC curve, AUC를 이용한 사이킷런(Scikit-learn) 코드 예제

1. ROC 커브를 그려보고 Youden's Index로 Optimal Threshold를 찾는 예제

from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_curve, roc_auc_score
import matplotlib.pyplot as plt
import numpy as np

# Generate a binary classification dataset
X, y = make_classification(n_samples=1000, n_classes=2, random_state=42)

# Split dataset into training and testing sets
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# Fit a logistic regression model
logreg = LogisticRegression()
logreg.fit(X_train, y_train)

# Predict probabilities of target values for test set
y_prob = logreg.predict_proba(X_test)

# Calculate the fpr and tpr for all thresholds of the classification
fpr, tpr, thresholds = roc_curve(y_test, y_prob[:, 1])

# Plot the ROC curve
plt.plot(fpr, tpr, label='ROC curve (AUC = %0.2f)' % roc_auc_score(y_test, y_prob[:, 1]))
plt.plot([0, 1], [0, 1], 'k--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic (ROC) Curve')
plt.legend(loc="lower right")

# Find the optimal decision threshold using Youden's index
optimal_idx = np.argmax(tpr - fpr)
optimal_threshold = thresholds[optimal_idx]
plt.plot(fpr[optimal_idx], tpr[optimal_idx], 'ro', markersize=8)

# Calculate Youden's index
youden_idx = tpr[optimal_idx] - fpr[optimal_idx]

# Print optimal threshold and Youden's index
print('Optimal threshold:', optimal_threshold)
print("Youden's index:", youden_idx)

plt.show()

ROC curve
ROC curve

 

 

2. 여러가지 모델의 ROC커브를 그리고 AUC를 계산하여 가장 퍼포먼스가 좋은 모델 찾는 코드 예시

from sklearn.datasets import make_classification
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.metrics import roc_curve, roc_auc_score
import matplotlib.pyplot as plt

# Generate a binary classification dataset
X, y = make_classification(n_samples=1000, n_classes=2, random_state=42)

# Split dataset into training and testing sets
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# Fit different classification models
dtc = DecisionTreeClassifier()
dtc.fit(X_train, y_train)

logreg = LogisticRegression()
logreg.fit(X_train, y_train)

svm = SVC(probability=True)
svm.fit(X_train, y_train)

# Predict probabilities of target values for test set
y_prob_dtc = dtc.predict_proba(X_test)
y_prob_logreg = logreg.predict_proba(X_test)
y_prob_svm = svm.predict_proba(X_test)

# Calculate the fpr and tpr for all thresholds of each classification model
fpr_dtc, tpr_dtc, _ = roc_curve(y_test, y_prob_dtc[:, 1])
fpr_logreg, tpr_logreg, _ = roc_curve(y_test, y_prob_logreg[:, 1])
fpr_svm, tpr_svm, _ = roc_curve(y_test, y_prob_svm[:, 1])

# Plot the ROC curves for all models on the same plot
plt.plot(fpr_dtc, tpr_dtc, color='red', label='Decision Tree')
plt.plot(fpr_logreg, tpr_logreg, color='blue', label='Logistic Regression')
plt.plot(fpr_svm, tpr_svm, color='green', label='SVM')
plt.plot([0, 1], [0, 1], 'k--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic (ROC) Curve')
plt.legend(loc="lower right")

# Calculate the AUC for each model and print them
auc_dtc = roc_auc_score(y_test, y_prob_dtc[:, 1])
auc_logreg = roc_auc_score(y_test, y_prob_logreg[:, 1])
auc_svm = roc_auc_score(y_test, y_prob_svm[:, 1])

print('AUC for Decision Tree:', auc_dtc)
print('AUC for Logistic Regression:', auc_logreg)
print('AUC for SVM:', auc_svm)

# Determine the model with the maximum AUC
max_auc = max(auc_dtc, auc_logreg, auc_svm)
if max_auc == auc_dtc:
    print('The Decision Tree model has the highest AUC')
elif max_auc == auc_logreg:
    print('The Logistic Regression model has the highest AUC')
else:
    print('The SVM model has the highest AUC')

plt.show()

ROC Curve and AUC Scikit learn code result
ROC Curve and AUC Scikit learn code result

 

이번 포스팅에서는 ROC Curve(커브)와 AUC의 개념과 Classification 모델의 Threshold란 무엇인지 그리고 Optimal Threshold를 찾는 방법에 대해 알아보았습니다. 또한 Sensitivity, Specificity의 개념과 Youden's Index 계산하는 방법도 함께 알아보았습니다. 위에서 보여드린 사이킷런(Scikit-learn) 코드 예시를 통해 Classification 모델의 Threshold를 찾는 과정, 그리고 여러 가지 Classification 모델을 비교할 때 ROC커브와 AUC를 이용하는 방법에 대해 정확하게 이해하는데 도움이 되셨으면 좋겠습니다. 

댓글