[ML] 모델 평가, ROC

박미영·2023년 5월 24일
0

DataSchool StudyNote - ML

목록 보기
7/19

📌모델 평가 개념

  • 모델을 좋다, 나쁘다, 그저그렇다 등 평가할 방법은 없다.
  • 대부분 다양한 모델, 다양한 파라미터를 두고, 상대적으로 비교한다.



<회기 모델 VS 분류 모델>

  • 회기모델
    내가 가지고 있는 데이터를 어떤 직선(꼭 직선일 필요는 없음)으로 만들어 예측해 사용
    회기모델 예측 결과는 연속된 변수의 값이다.

  • 분류 모델
    ex) 강아지, 고양이 구분, iris 품종 맞추기, 몇 개의 종류에서 값을 찾아내는 것



  • 회귀 모델들은 실제 값과의 에러치를 가지고 계산(회귀모델의 평가는 간단한 편)

  • 분류 모델의 평가 항목은 좀 많다.



📌 이진 분류 모델의 평가

이진 분류: 0(Negative), 1(Positive)을 가지고 T/F 맞춘다.


  • 이진 분류에서 predict vs real

1종 오류 -> FP: 가설이 아닌데 틀린 것



- Accuracy

전체 데이터(TP+TN+FP+FN) 중 맞게 예측한 것(TP+TN)의 비율



- Precision

1(Positive)이라고 예측한 것(TP+FP) 중에서 실제 Positive(TP)의 비율

ex) 스팸 메일, 중요한 메일
내가 스팸 메일이라고 예측한 메일 중 실제 스팸 메일이 아닌 중요한 메일이면 곤란하다.



- RECALL (TPR; TRUE POSITIVE RATIO)

참인 데이터(TP+FN)를 중에서 참이라고 예측한 것(TP)의 비율

놓쳐서는 안되는 일을 확인할 때 봐야하는 지표
(ex 암 검사를 했을 때, 100% 검사가 정확하면 좋겠지만 암이 아닌 사람을 암으로 진단(그나마 나은 경우), 암인 사람을 아니라고 진단 (이것을 놓치면 안된다. 그래서 확인해야하는 지표))


Precision VS RECALL
Precision: 내가 1이라고 예측한 것 중에서 실제 1 비율
RECALL: 실제 1의 비율에서 실제 1의 비율



- FALL-OUT (FPR; FALSE POSITION RATIO)

실제 0(FP+TN)중에서 1이라고 잘 못 예측한 것(FP)의 비율



- 분류 모델 반환

분류모델은 그 결과를 속할 비율(확률)을 반환한다.
• 지금까지는 그 비율에서 threshold를 0.5라고 하고 0, 1로 결과를 반영했다. (if 이진분류)
• iris의 경우 가장 높은 확률값이 있는 클래스를 해당 값이라고 했다.



- 모델 평가 지표 관찰

threshold를 변경해 가면서 모델 평가 지표들을 관찰

y: 실제 y의 값(참 값)
y_pred: 1일 확률을 예측한 값



  • Threshold = 0.3
    0.3보다 크거나 같으면 무조건 1이라고 본다.

y_pred가 전부 0.3보다 크거나 같기 때문에 output for threshold 0.3이 모두 1이다.
실제 y가 1인 값은 모두 맞추고 실제 y가 0들은 1로 예측했기 때문에 다 틀렸다.

recall: 실제 1 중에서 1이라고 맞춘 값 (3/3) 100%
fall-out: 실제 0 중에서 1이라고 하여 틀린 값 (4/4) 다 틀림
precision: 내가 1이라고 예측한 값 중에 실제 1의 비율 (3/7)
accuracy: 참 값이 몇 개인가 (3/7)



  • Threshold = 0.4

실제 y가 1인 값은 변함 없이 모두 맞추고 실제 y가 0인 값은 틀린 개수가 4개에서 3개로 줄어들었다.

recall: 실제 1 중에서 1이라고 맞춘 값 (3/3) - 여전히 100%
fall-out: 실제 0 중에서 1이라고 하여 틀린 값 (3/4) - 0인 값을 1개 맞춰서 감소했다.
precision: 내가 1이라고 예측한 값 중에 실제 1의 비율 (3/6) - 상승됐다.
accuracy: 참 값이 몇 개인가 (4/7) - 한 개 더 맞췄으니 증가했다.



  • Threshold = 0.5

실제 0인데 0이라고 맞춘 값은 2개로 증가했고, 실제 1인데 1이라고 맞춘 값은 3개에서 2개로 감소 했다.

recall: 실제 1 중에서 1이라고 맞춘 값 (2/3) - 감소했다.
fall-out: 실제 0 중에서 1이라고 하여 틀린 값 (2/4) - 0인 값을 2개 맞춰서 감소했다.
precision: 내가 1이라고 예측한 값 중에 실제 1의 비율 (2/4)
accuracy: 참 값이 몇 개인가 (5/7) - 한 개 더 맞췄으니 증가했다.


  • Threshold = 0.6

  • Threshold = 0.8

  • Threshold = 0.9



  • 정리

그러나 Recall과 Precision은 서로 영향을 주기 때문에 한 쪽을 극단적으로 높게 설정해서는 안됨



F1-Score

Recall과 Precision을 결합한 지표
Recall과 Precision이 어느 한 쪽으로 치우치지 않고 둘 다 높은 값을 가질 수록 높은 값을 가짐
F1-Score 수학에서 조화 평균이라고 함


  • F1-Score의 계산

📌ROC, AUC

- ROC 곡선

FPR = Fall-out, 1-Sensitiity
TPR = RECALL, Sensitiity


만약 완벽하게 분류했다면

AUC -> 면적


적당히 잘 했다면


분류 성능이 나쁘다면


방금 전 예제에서의 ROC 곡선



- AUC



- ROC 커브 그려보기

  1. 데이터 읽어보기
import pandas as pd

red_url = 'https://raw.githubusercontent.com/PinkWink/ML_tutorial/master/dataset/winequality-red.csv'
white_url = 'https://raw.githubusercontent.com/PinkWink/ML_tutorial/master/dataset/winequality-white.csv'

red_wine = pd.read_csv(red_url, sep=';')
white_wine = pd.read_csv(white_url, sep=';')

red_wine['color'] = 1.
white_wine['color'] = 0.

wine = pd.concat([red_wine, white_wine])
wine['taste'] = [1. if grade>5 else 0. for grade in wine['quality']]

X = wine.drop(['taste', 'quality'], axis=1)
y = wine['taste']

  1. DecisionTree 적용
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=13)
wine_tree = DecisionTreeClassifier(max_depth=2, random_state=13)
wine_tree.fit(X_train, y_train)

y_pred_tr = wine_tree.predict(X_train)      # train accuracy
y_pred_test = wine_tree.predict(X_test)     # test accuracy

print('Train Acc :', accuracy_score(y_train, y_pred_tr))
print('Test Acc :', accuracy_score(y_test, y_pred_test))


  1. 수치 구하기
from sklearn.metrics import (accuracy_score, precision_score, recall_score,
                             f1_score, roc_auc_score, roc_curve)

print('Accuracy : ', accuracy_score(y_test, y_pred_test))
print('Recall : ', recall_score(y_test, y_pred_test))
print('Precision : ', precision_score(y_test, y_pred_test))
print('Auc Score : ', roc_auc_score(y_test, y_pred_test))
print('F1 Score : ', f1_score(y_test, y_pred_test))


  1. ROC 커브 그리기
pred_proba = wine_tree.predict_proba(X_test)[:, 1] # 1일 확률만 가져오기
fpr, tpr, thresholds = roc_curve(y_test, pred_proba)
print(fpr, tpr, thresholds)

import matplotlib.pyplot as plt
%matplotlib inline

plt.figure(figsize=(8, 6))
plt.plot([0,1], [0,1], 'c', ls='dashed')  # (0,0)부터 (1,1) 사이 직선 그리기 
plt.plot(fpr, tpr)
plt.grid()
plt.show()




"이 글은 제로베이스 데이터 취업 스쿨 강의를 듣고 작성한 내용으로 제로베이스 데이터 취업 스쿨 강의 자료 일부를 발췌한 내용이 포함되어 있습니다."

0개의 댓글