[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개의 댓글

관련 채용 정보