머신러닝 & 딥러닝
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 )
- 재현율
- 민감도와 같음
- 소극적 예측 : 확실한 경우 아니면 관심범주라고 예측하지 않음 (쿠팡)
정밀도 ↑, 재현율 ↓ - 공격적 예측 : 조금만 의심이 가도 관심범주로 판단 (병원 - 암)
정밀도 ↓, 재현율 ↑
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 출력
- 데이터 로드
- 결측치를 확인
- 훈련 / 테스트 데이터 분리
- 모델 생성 및 훈련
- 모델 예측
- ROC 곡선 그리기
- 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()
본 내용은 아이티윌 '빅데이터&머신러닝 전문가 양성 과정' 을 수강하며 작성한 내용입니다.