머신러닝 & 딥러닝

8. 머신러닝 평가

김초송 2023. 4. 3. 16:32

머신러닝 모델 평가 = 정확도 + 다른 성능 척도

성능척도 : 카파 통계량, 민감도, 특이도, 정밀도, 재현율, Roc 곡선,  F1 score

 

카파 통계량

  • 두 관찰자간의 측정 범주값에 대한 일치도를 측정하는 방법
    예측값과 실제값의 일치도
  • kappa = Pr(a) - Pr(e) / 1 - Pr(e)
  • Pr(a) : 데이터에서 관찰된 2명의 평가자들의 일치 확률
  • Pr(e) : 2명의 평가자들이 데이터로부터 계산된 확률적 일치 확률 ( 우연히 일치할 확률 )
  • 0 이면 완전불일치, 1 이면 완전 일치
kappa 일치정도
0.0 ~ 0.2 거의 일치하지 않음
0.2 ~ 0.4 어느정도 일치
0.4 ~ 0.6 보통 일치
0.6 ~ 0.8 좋은 일치
0.8 ~ 1.0 매우 좋은 일치
평가자 B 평가자 A  
합격 불합격 합계
합격 40 10 50
불합격 20 30 50
합계 60 40 100
  • 평가자 a : 합격을 60명, 불합격 40명 = 합격을 0.6의 확률로 불합격을 0.4의 확률
  • 평가자 b : 합격을 50명, 불합격 50명 = 합격을 0.5확률 불합격을 0.5의 확률
  • 평가자 a 와 평가자 b 모두 합격을 줄 확률 = 0.6 * 0.5 =0.3
  • 평가자 a, b 모두 확률적으로 불합격을 줄 확률= 0.4 * 0.5 = 0.2
  • Pr(e) : 데이터로부터 계산된 확률적으로 일치하는 확률 = 이 둘을 더해서 0.3 + 0.2 =0.5
a <- as.table(matrix( c(40, 10, 20, 30), byrow=T, nrow=2)) 

install.packages("vcd")
library(vcd)
Kappa(a)
           value    ASE     z  Pr(>|z|)
Unweighted   0.4 0.0898 4.454 8.415e-06
Weighted     0.4 0.0898 4.454 8.415e-06
  • 0.4 면 보통일치이고  p-value 가 0.05보다 작으므로 통계적으로 유의한 결과

 

성능 척도

실제 예측
True (관심범주) False (관심범주 X)
True TP (True Positive) FN (False Negative)
False FP (False Positive) TN (True Negative)
  • 정확도
    • 실제 데이터와 예측 데이터를 비교하여 같은지 판단하는 척도
    • 모델 성능의 가장 일반적인 척도
    • ( TP + TN ) / ( TP + TN + FP + FN )
  • 민감도
    • 실제 관심범주를 관심범주로 올바르게 예측
    • 높으면 공격적 예측을 하는 모델
    • TP / ( TP + FN )
  • 특이도
    • 실제 관심범주가 아닌 것을 관심범주가 아닌 것으로 올바르게 예측
    • TN / ( TN + FP )
  • 정밀도
    • 관심범주로 예측한 것 중에 실제로 관심범주인 것
    • TP / ( TP + FP )
  • 재현율
    • 민감도와 같음
  1. 소극적 예측 : 확실한 경우 아니면 관심범주라고 예측하지 않음 (쿠팡)
    정밀도 ↑, 재현율 ↓
  2. 공격적 예측 : 조금만 의심이 가도 관심범주로 판단 (병원 - 암)
    정밀도 ↓, 재현율 ↑

 

F1 score

  • 정밀도와 재현율을 결합한 조화 평균 지표
  • 예측값이 틀린 것들이 얼마나 많은지 나타냄
  • 값이 클수록 모형이 정확하다고 판단
    0에 가까울수록 FN 과 FP 가 많다는 뜻 (틀린 것이 많음)
  • 2 * 정밀도 * 재현율 / ( 재현율 + 정밀도 ) = 2 * TP /  ( 2 * TP + FP + FN )

 

Python 으로 성능 척도 출력

# 성능척도
from sklearn.metrics import confusion_matrix
tn, fp, fn, tp = confusion_matrix(y_test, predict).ravel()
accuracy = (tn + tp) / (tn + fp + fn + tp)
sensitivity = tp / (tp + fn)
specificity = tn / (tn + fp)
precision = tp / (tp + fp)

print(f"""accuracy : {accuracy}
sensitivity : {sensitivity}
specificity : {specificity}
precision : {precision}""")


# 카파통계량
from sklearn.metrics import cohen_kappa_score
print('kappa : {}'.format(cohen_kappa_score(y_test, predict)))

# f1 score
f1_score = (2 * tp) / (2*tp + fn + fp)
f1_score

 

ROC 곡선 (Receiver Operating Characteristic Curve)

  • 1 - FPR (False Positive Rate, 특이도) 가 변할 때 TPR (True Positive Rate,  민감도) 가 어떻게 변화하는지 나타내는 곡선
  • x축 = FPR, y축 = TPR
  • FPR : 관심범주가 아닌 것을 관심범주로 잘못 판정한 비율
    TRP : 관심범주를 관심범주로 잘 판정한 비율
  • FPR 을 낮추면서 TPR 을 높일 수 있는 cut off 지점을 찾는 것이 목표
  • AUC ( Area Under Curve)
    • ROC 커브 하단 면적. 넓을 수록 좋은 모델
    • 랜덤일 때는 0.5
    • 직선에서 멀어지고 y축에 붙을 수록 성능이 좋은 모델
  • 이진 분류 모델의 성능을 확인하기 위한 그래프

 

R 로 ROC curve 출력

  1. 데이터 로드
  2. 결측치를 확인
  3. 훈련 / 테스트 데이터 분리
  4. 모델 생성 및 훈련
  5. 모델 예측
  6. ROC 곡선 그리기 
  7. AUC 계산하기
credit <- read.csv("C:/Data/credit.csv", stringsAsFactors = TRUE)
head(credit)

# default : 종속변수
# no: 채무 이행, yes: 채무 불이행 
# -> yes 를 줄이기 위한 머신러닝
table(credit$default)

hist(credit$amount) # amount: 대출 금액
summary(credit$amount)

colSums(is.na(credit))

library(caret)
set.seed(1)

split <- createDataPartition(credit$default, p=0.9, list=F)

train <- credit[split, ]
test <- credit[-split, ]

# 데이터가 균등하게 나눠졌는지 확인
prop.table(table(train$default)) # no:yes = 0.7:0.3
prop.table(table(test$default)) # no:yes = 0.7:0.3

# Decision Tree Model
install.packages("C50")
library(C50)

model <- C5.0(train[, -17], train[, 17])
summary(model) # 어떤 사람이 돈을 갚고 어떤 사람이 안 갚는지 패턴

predict <- predict(model, test[, -17])
table(predict)

accuracy <- sum(predict == test[, 17]) / length(test$default) * 100
accuracy

# 몇 퍼센트 확률로 부채 상환할지 안할지
predict_prob <- predict(model, test[, -17], type="prob")
predict_prob

# ROC 곡선을 그리기 위한 백데이터
back_data <- data.frame(actual_type=test[, 17], # 실제값
                        predict_type=predict, # 예측값
                        prob_yes=round(predict_prob[, 2], 5), # yes 일 확률
                        prob_no=round(predict_prob[, 1], 5)) # no 일 확률
back_data

install.packages("ROCR")
library(ROCR)

pred <- prediction(predictions=back_data$prob_yes, 
                   labels = back_data$actual_type)
pred

perf <- performance(pred, measure="tpr", x.measure="fpr")
perf

plot(perf, main="ROC Curve", col="blue", lwd=2)
abline(a=0, b=1, lwd=2, lty=2) # 대각선

# AUC 계산
value <- performance(pred, measure = "auc")
str(value)

unlist(value@y.values) # 1에 가까울 수록 좋은 모델
  • prediction( predictions=관심범주의 확률, labels=실제정답)
    : ROC 곡선을 그리기 위한 100개의 데이터 포인트 생성
  •  perf : x 축인 fpr (1 - 특이도) 와 y 축인 tpr (민감도) 에 해당되는 실제 데이터 포인트 26개 생성

 

Python 으로 AUC 출력

import pandas as pd

credit = pd.read_csv("C:/Data/credit.csv")
credit.head()

credit.isnull().sum()

x = credit.iloc[:, :-1]
y = credit.default

x_dummy = pd.get_dummies(x)
x_dummy.shape

from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(x_dummy, y, test_size=0.1, random_state=1)

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
scaler.fit(x_train)
x_train2 = scaler.transform(x_train)
x_test2 = scaler.transform(x_test)

from sklearn.tree import DecisionTreeClassifier

model = DecisionTreeClassifier(criterion='entropy', max_depth=5)

model.fit(x_train2, y_train)
predict = model.predict(x_test2)
predict

from sklearn.metrics import accuracy_score

accuracy_score(predict, y_test)

pred = model.predict_proba(x_test2)[:, 1]
pred

y_test2 = []
for v in y_test.values:
    if v == 'yes':
        y_test2.append(1)
    else:
        y_test2.append(0)

from sklearn import metrics

fpr, tpr, threshold = metrics.roc_curve(y_test2, pred)
roc_auc = metrics.auc(fpr, tpr)
roc_auc

import matplotlib.pyplot as plt

# 곡선
plt.title("ROC Curve")
plt.plot(fpr, tpr, 'blue', label='AUC %0.2f' % roc_auc)
plt.legend(loc='lower right')

# 대각선
plt.plot([0, 1], [0, 1], 'r--')
plt.show()
  • pred : 관심범주 (yes) 일 확률, 아닐 (no) 확률
  • y_test2 : yes, no 를 숫자형으로 변환
from sklearn.ensemble import RandomForestClassifier

model2 = RandomForestClassifier(n_estimators=100, random_state=4)

model2.fit(x_train2, y_train)
predict2 = model2.predict(x_test2)
predict2

accuracy_score(predict2, y_test)

pred2 = model2.predict_proba(x_test2)[:, 1]
pred2

y_test

y_test2 = []
for v in y_test.values:
    if v == 'yes':
        y_test2.append(1)
    else :
        y_test2.append(0)
        
y_test2

fpr, tpr, threshold = metrics.roc_curve(y_test2, pred2)
roc_auc = metrics.auc(fpr, tpr)
roc_auc

plt.title("ROC Curve")
plt.plot(fpr, tpr, 'blue', label='AUC=%0.2f' % roc_auc)
plt.legend(loc='lower right')

plt.plot([0, 1], [0, 1], 'r--')
plt.show()
본 내용은 아이티윌 '빅데이터&머신러닝 전문가 양성 과정' 을 수강하며 작성한 내용입니다.