본문 바로가기
AI/Experiment

01. 머신러닝 모델 평가 방법

by _S0_H2_ 2020. 5. 10.
728x90
반응형

머신러닝은 여러 개의 모델로 학습을 할 수 있습니다. 각각의 알고리즘이 특성, 차이가 있기 때문에 모델을 평가할 지표가 필요합니다. 

 

지도 학습의 평가

1. 분류 문제

혼동 행렬(confusion matrix), 정확도(accuracy), 정밀도(precision), 재현율(recall), F값(F1-score), 곡선아래면적(AUC)

2. 회귀문제

평균제곱오차(MSE), 결정계수(coefficientg of determination)

 


분류 문제의 평가 방법

'미국 위스콘신 대학'의 '유방암 진단 데이터세트'를 로지스틱 회귀 모델로 머신러닝한 코드로 여러 평가 방법을 알아보겠습니다.

code

# 모듈 및 데이터 로드
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression

data = load_breast_cancer()

# x, y 데이터 생성
X = data.data
# 악성을 1, 양성을 0으로 바꿔주자
y = 1 - data.target

# 특징으로 사용할 데이터를 평균으로 구분하는 10개 열로 줄이자
X = X[:, :10]

# 로지스틱 회귀 모델 생성
model_lor = LogisticRegression(solver = 'lbfgs')
model_lor.fit(X,y)

y_pred = model_lor.predict(x)

 

1. 혼동 행렬( confusion matrix )

혼동 행렬은 학습된 분류 모델이 예측을 수행하면서 얼마나 헷갈리고 있는지도 함께 보여주는 지표입니다. 어떠한 유형의 예측 오류가 발생하는지를 확인할 수 있습니다. 오차 행렬이라고도 하며 TN, FP, FN, TP 네 가지의 결과를 출력합니다.

 

TN(true negative) : 실제 부정 데이터를 부정으로 제대로 예측
FP(false positive) : 실제 부정 데이터를 긍정으로 잘못 예측
FN(false negative) : 실제 긍정 데이터를 부정으로 잘못 예측
TP(true positive) : 실제 긍정 데이터를 긍정으로 제대로 예측

 

sklearn의 모듈을 이용해서 혼동 행렬을 구하면, 다음 그림 순서에 따른 결과를 출력합니다.

code

from sklearn.metrics import confusion_matrix

# 종속 변수와 예측 결과로 혼동 행렬 생성
cm = confusion_matrix(y, y_pred)
print(cm)
[[337  20]
 [ 30 182]]

 

 

2. 정확도( accuracy )

정확도는 예측 결과 전체 중 정확하게 예측한 비율입니다. ( TN, TP ) 

정확도 = 예측 결과가 동일한 데이터 건수 / 전체 예측 데이터 건수

 

가장 직관적인 모델 예측 성능을 나타내는 평가 지표이지만, 데이터의 불균형이 심하다면 모델 성능을 판단하기에 좋은 지표가 아닙니다.  

code

from sklearn.metrics import accuracy_score
print(accuracy_score(y, y_pred))
0.9121265377855887

 

 

하지만 불균형 데이터셋의 모델을 평가하기에 '정확도'는 적합하지 않습니다.

그래서 정밀도, 재현율의 평가지표를 사용합니다.

 

 

3. 정밀도( precision )

정밀도 : positive로 예측한 값들 중에 실제로 positive한 값의 비율

정밀도는 불균형한 데이터셋의 모델을 평가하는데도 사용하며, 다음의 경우에 중요하게 사용됩니다.

  1. 스팸 메일을 스팸으로 예측한 경우 (TP)
  2. 정상 메일을 스팸으로 예측한 경우 (FP)
  3. 스팸 메일을 정상으로 예측한 경우 (FN)
  4. 정상 메일을 정상으로 예측한 경우 (FP)

    1번과 4번은 제대로 예측하였지만, 2번과 3번은 번거로운 상황이 발생합니다. 특히, 2번은 업무에 영향을 줄 수도 있습니다. 따라서, FP를 낮추는데 초점을 두어야합니다.

code

from sklearn.metrics import precision_score
print(precision_score(y,y_pred))
0.900990099009901

 

4. 재현율( recall )

재현율 : 실제 값이 positive인 값들 중에 예측을 positive로 한 값의 비율

재현율은 불균형한 데이터셋의 모델을 평가하는데도 사용하며, 다음의 경우에 가장 중요하게 사용됩니다.

  1. 암환자에게 암을 예측한 경우 (TP)
  2. 암환자가 아닌 사람에게 암을 예측한 경우 (FP)
  3. 암환자에게 암이 아니라고 예측한 경우 (FN)
  4. 암환자가 아닌 사람에게 암이 아니라고 예측한 경우 (TN)

    1번과 4번은 제대로 예측하였지만, 2번과 3번은 힘든 상황이 발생합니다. 특히, 3번은 최악의 경우입니다. 따라서 FN을 낮추는데 초점을 두어야합니다.

code

from sklearn.metrics import recall_score
print(recall_score(y,y_pred))
0.8584905660377359

 

 

하지만 정밀도와 재현율은 상호 보완적인 평가 지표이기 때문에 강제로 하나를 올리면, 다른 하나는 떨어지기 쉽습니다. 이를 정밀도/재현율의 trade-off라고 부릅니다. 임계치에 따라 정밀도와 재현율로 속일 수 있기 때문에 극단적인 경우를 방지하기 위해 이 둘을 조합한 지표를 만들었습니다.

 

 

5. F값

F1 score : 정밀도와 재현율을 결합한 지표입니다. 한 쪽으로 치우치지 않는 수치를 나타낼 때 상대적으로 높은 값을 가집니다. 

code

from sklearn.metrics import f1_score
print(f1_score(y, y_pred))
0.8792270531400966

 

 

6. 예측확률

이진 분류는 0과 1 등 두개 중 하나를 예측하지만, 실제로 레이블 2개로 분류되는지에 관한 확률을 나타내는 모델이 많습니다. 즉, 0으로 분류되는 확률과 1로 분류되는 확률을 계산해볼 수 있습니다.

model_lor.predict_proba(X)
array([[7.73103110e-03, 9.92268969e-01],
       [2.04763561e-02, 9.79523644e-01],
       [2.35266319e-03, 9.97647337e-01],
       ...,
       [2.33864630e-02, 9.76613537e-01],
       [8.09237759e-06, 9.99991908e-01],
       [9.99574655e-01, 4.25344878e-04]])

확률값에 조건을 설정하여 평가해보겠습니다.

import numpy as np

# 0으로 예측할 확률이 0.1보다 크면 y_pred2 에 넣는다.
y_pred2 = (model_lor.predict_proba(X)[:,1]>0.1).astype(np.int)

# 혼동행렬
print(confusion_matrix(y,y_pred2))
# 정확도
print(accuracy_score(y, y_pred2))
# 정밀도
print(precision_score(y,y_pred2))
# 재현율
print(recall_score(y,y_pred2))
# f1 score
print(f1_score(y, y_pred2))
# 혼동행렬
[[267  90]
 [  6 206]]
 
# 정확도
0.8312829525483304
# 정밀도
0.6959459459459459
# 재현율
0.9716981132075472
# f1 score
0.8110236220472441

결과를 살펴보니 정확도, 정밀도, f1 score 값은 떨어졌지만 재현율이 높아졌음을 확인할 수 있었습니다.

 

 

 

지금까지의 지표들이 극단적인 불균형 데이터셋에서는 의미가 없습니다. 예를 들어 긍정 95개, 부정 5개라면 95%라는 정확도를 계산하기 때문입니다. 따라서 불균형 데이터에 대응하는 평가 지표가 필요합니다.

 

 

7. ROC 곡선과 AUC

ROC 곡선은 Receiver Operation Characteristic Curve 입니다. ROC 곡선은 FPR(X축)과 TPR(Y축)의 관계를 그린 곡선입니다.

AUC는 Area Under Curve를 입니다. ROC 곡선 아래의 면적을 의미합니다.

FPR : False Positive Rate
TPR : True Positive Rate (재현율)

TPR은 재현율로 이와 대응하는 지표에 TNR(특이성)이 있습니다. 특이성은 실제값 negative가 정확히 예측돼야 하는 수준을 의미합니다.

TNR을 이용해서 FPR을 구할 수 있습니다.

 

 

TPR, FPR 값으로 ROC 곡선과 AUC를 나타낸 그림입니다.

ROC 선과 AUC 면적에 따라 그래프는 다음과 같이 나타날 수 있습니다.

ROC 곡선이 직선에 가까울 수록 성능이 떨어지는 것이고, 멀어질수록 성능이 뛰어난 것입니다.

즉, AUC가 클 수록 좋은 값입니다.

 

code

from sklearn.metrics import roc_curve
probas = model_lor.predict_proba(X)

fpr, tpr, thresholds = roc_curve(y, probas[:,1])

그림으로 확인해보겠습니다.

%matplotlib inline
import matplotlib.pyplot as plt

plt.style.use('fivethirtyeight')
fig, ax = plt.subplots()
fig.set_size_inches(4.8, 5)
ax.step(fpr, tpr, 'gray')
ax.fill_between(fpr, tpr, 0, color='skyblue', alpha=0.8)
ax.set_xlabel('False Positive Rate')
ax.set_ylabel('True Positive Rate')
ax.set_facecolor('xkcd:white')
plt.show()

곡선 아래 면적을 구해보면,

from sklearn.metrics import roc_auc_score
roc_auc_score(y, probas[:,1])
0.9741160615189471

약 1에 가까우므로 정확도가 높은 분류 모델임을 알 수 있습니다.

 

 

 


 

회귀 문제의 평가 방법

회귀 문제는 수치의 크고 작음에 의미를 부여해 예측합니다. '미국 보스턴의 주택 가격 데이터세트'를 사용해 '방 개수에 따른 임대료'를 예측해보겠습니다. 단순성형회귀모델을 사용하겠습니다.

code

# 데이터 로드
from sklearn.datasets import load_boston
data = load_boston()
X = data.data[: , [5,]]
y = data.target

# 선형 회귀 모델 사용
from sklearn.linear_model import LinearRegression
# 학습
model_lir = LinearRegression()
model_lir.fit(X, y)
# 예측
y_pred = model_lir.predict(X)

그림으로 데이터와 직선을 그려보겠습니다.

%matplotlib inline
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.scatter(X, y, color='pink', marker='s', label='data set')
ax.plot(X, y_pred, color='blue', label='regression curve')
ax.legend()
plt.show()

그렇다면, 기울기와 절편을 구해볼까요?

print(model_lir.coef_)
print(model_lir.intercept_)
[9.10210898]
-34.670620776438554

 

1. 평균제곱오차(MSE)

평균제곱오차는 평가할 데이터와 예측값 사이의 오차 제곱을 모두 계산한 후 평균을 낸 것입니다. 평균제곱오차가 작을수록 예측값이 올바르다는 뜻입니다.

code

from sklearn.metrics import mean_squared_error
print(mean_squared_error(y, y_pred))
43.60055177116956

 

2. 결정계수

결정계수는 평균제곱오차를 사용해 학습한 모델 예측의 적합도를 나타냅니다.

 

다른 성능 지표인 RMSE나 MAE는 데이터의 scale에 따라서 값이 천차만별이기 때문에, 절대 값만 보고 바로 성능을 판단하기가 어려운데, 결정계수의 경우 상대적인 성능이기 때문에 이를 직관적으로 알 수 있습니다.

결정계수가 최댓값인 1.0이면 오차가 없다는 뜻이기도 합니다.

보통 0.0과 1.0 사이의 값으로 나타내지만, 예측값과 실제 데이터 사이의 오차가 너무 크면 음숫값으로 나타내기도 합니다. 즉, 1.0에 가까울수록 해당 모델이 데이터 포인터를 정확하게 나타내는 것입니다.

 

code

from sklearn.metrics import r2_score
print(r2_score(y,y_pred))
0.48352545599133423

 


SVR 모델과 비교를 해볼까요?

# 위의 데이터를 서포트 벡터 회귀로 모델을 학습시키자
from sklearn.svm import SVR

model_svr_linear = SVR(C=0.01, kernel='linear')
model_svr_linear.fit(X, y)
y_svr_pred = model_svr_linear.predict(X)
%matplotlib inline
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.scatter(X, y, color='pink', marker='s', label='data set')
ax.plot(X, y_pred, color='blue', label='regression curve')
ax.plot(X, y_svr_pred, color='red', label='SVR')
ax.legend()
plt.show()

선을 그려보니 SVR의 기울기가 더 작음을 확인하였습니다.

# 평균 제곱오차
print(mean_squared_error(y, y_svr_pred))
# 결정계수
print(r2_score(y, y_svr_pred))
72.14197118147209
0.14543531775956597

 

단순선형회귀 모델과 비교해보니 SVR의 결정계수 값이 좋지 않음을 확인하였습니다. 이번 데이터에서는 SVR이 좋은 알고리즘이 아니었나봅니다. 모델의 parameter를 조정하여 볼 수 있습니다.

 

 

 

 

 

 

 

728x90
반응형