본문 바로가기
Kaggle마스터가 되기 위한 몸부림/가짜연구소 - Kaggle 마스터가 되기 위한 몸부림!

[Model Evaluation] 분류 모델 평가 방법에 대해 알아보자 (Accuracy, precision, RecallROC, F1Score, AUC-ROC curve, logistic loss)

by Steve-Lee 2021. 2. 25.

출처: freepik

본 포스팅은 Ouassim Adnane의 Kaggle Notebook  'Machine Learning Model Evaluation Metrics'를 기반으로 작성되었습니다. 단순히 이론은 학습하는 것이 아닌 실습을 통해 모델을 평가하는 연습을 충분히 갖는 시간이 되었으면 합니다.

 

안녕하세요 Steve-Lee입니다.

이번 시간에는 '머신러닝 모델 평가 및 해석 방법'에 대한 첫 번째 시간으로 분류 모델(Classification Model)에 대한 평가 방법을 알아보도록 하겠습니다.

분류 모델 평가 실습은 Kaggle Notebook를 통해서 가능합니다. 그럼 시작하겠습니다.

 

본 포스팅에 대한 튜토리얼은 아래의 링크에서 진행하실 수 있습니다
 

[Model Evaluation] 1. Classification Metrics

Explore and run machine learning code with Kaggle Notebooks | Using data from multiple data sources

www.kaggle.com


Before we start it

머신러닝 알고리즘을 통한 모델을 적절히 평가하는 것이 매우 중요합니다.

평가지표(metric) 선택은 머신러닝 알고리즘의 성능을 측정하고 비교하는 방법에 영향을 줍니다.

하나씩 살펴보도록 하겠습니다.


Titanic Dataset 

  • 본 튜토리얼에서는 타이타닉 데이터셋을 사용합니다
  • 데이터셋에 대해 간단히 소개드리겠습니다
    • 영화 '타이타닉'의 주제인 타이타닉호의 침몰 사건 당시의 데이터입니다
    • pclass, sex, Age, sibsp, parch, ticket, fare, cabin, embarked의 특징정보를 활용해 침몰당시 승객의 생존 유무(Survival) 분류하는 문제입니다
    • 데이터에 대한 자세한 내용은 위의 링크를 참고해주시면 감사하겠습니다

 

Import Library

  • 본 튜토리얼에서 사용하는 라이브러리는 다음과 같습니다
import numpy as np
import pandas as pd

import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
    
from sklearn.model_selection import train_test_split

# Pipeline library for Training
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
from sklearn.metrics import mean_absolute_error

 

Data Preprocessing

  • 본 튜토리얼의 목적은 모델 평가입니다
  • 모델 평가를 위해 필요한 최소한의 전처리를 수행합니다
  • train data로부터 target값이 결측치인 값을 제거해줍니다
  • categorical_variable에 대해서는 unique값이 10이하인 feature만 사용합니다
  • numerical_variable에 대해서는 데이터 타입이 'float64' 또는 'int64'인 feature만 사용합니다
# Road the data
X = pd.read_csv("../input/titanic/train.csv")
X_test = pd.read_csv("../input/titanic/test.csv")
print(X.shape, X_test.shape)


# Remove rows with missing target, seperate target from predictors
X.dropna(axis=0, subset=['Survived'], inplace=True)
y = X.Survived
X.drop(['Survived'], axis=1, inplace=True)

# "Cardinality" means the number of unique values in a column
# Select categorical columns with relatively low cardinality (convenient but arbitrary)
categorical_cols = [cname for cname in X.columns if X[cname].nunique() < 10 and X[cname].dtype == 'object']

# Select numerical columns
numerical_cols = [cname for cname in X.columns if X[cname].dtype in ['float64', 'int64']]

# keep selected columns only
my_cols = categorical_cols + numerical_cols
X = X[my_cols].copy()
X_test = X[my_cols].copy()

 

아주 간단하게 시각화를 해보면...

X_ = pd.read_csv("../input/titanic/train.csv")

f, ax = plt.subplots(1, 2, figsize=(12, 4))
X_['Survived'].value_counts().plot.pie(autopct='%1.1f%%', ax=ax[0])
sns.countplot('Survived', data=X_, ax=ax[1])

우리가 갖고 있는 학습 데이터는 사망자가 60% 생존자가 40%를 가지고 있습니다

 

Pipelines

  • 이 때 각 feature에 대한 전처리를 쉽게 도와주는 유용한 library가 있습니다
  • 바로 pipeline입니다
  • pipeline을 만들고 다음의 작업을 수행합니다
    • numerical_transformer/categorical_transformer
    • preprocessor(ColumnTransformer)
    • define model
    • Bundle preprocessing and modeling
    • Preprocessing of training data, fit model
    • Preprocessing of validation data, get predictions
# Preprocessing for numerical data
numerical_transformer = SimpleImputer(strategy='constant')

# Preprocessing for categorical data
categorical_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='most_frequent')),
    ('onehot', OneHotEncoder(handle_unknown='ignore'))
])
# Preprocessing for numerical and categorical data
preprocessor = ColumnTransformer(
        transformers =[
            ('num', numerical_transformer, numerical_cols),
            ('cat', categorical_transformer, categorical_cols)
        ])

 

Modeling & Evaluate Score

지금부터 오늘의 주제인 모델 평가 방법을 샅샅히 파헤쳐보겠습니다

1. Confusion Matrix

Confusion Matrix는 분류모델의 성능을 측정하는 Matrix중 하나입니다. 단순히 Confusion Matrix를 출력하는데 그치지 않고 Confusion Matrix를 어떻게 해석해야하는지, 어떤 의미가 있는지 짚고 넘어가도록 하겠습니다

혼동행렬... 혼동이 더이상 발생해서는 안됩니다

from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score

# train_test_split: 80%, 20%
X_train, X_val, y_train, y_val = train_test_split(X, y, train_size=0.8, test_size=0.2)

# modeling
rf_clf = RandomForestClassifier()

# Bundle preprocessing and modeling code in a pipeline
clf = Pipeline(steps=[
    ('preprocessor', preprocessor),
    ('model', rf_clf)
])

# train
clf.fit(X_train, y_train)
preds = clf.predict(X_val)


# confusion_matrix
cm = confusion_matrix(y_val, preds)
sns.heatmap(cm, annot=True, fmt="d")

혼동이 오시나요? 오늘의 목표는 언제,어디서나 나의 모델을 당당하게 발표하는 것입니다.

 

1) Accuracy

Accuracy in classification problems is the number of correct predictions made by the model over all kinds predictions made

분류 문제(Classification problem)에서 Accuracy는 모든 예측값에 대하여 올바르게 예측된 값을 나타냅니다

Accuracy는 양성을 양성이라고 예측하고 음성을 음성이라고 예측한 확률을 말합니다. 참 쉽습니다

clf.score(X_val, y_val)  # Return the mean accuracy on the given test data and labels

0.8435754189944135

accuracy_score(y_val, preds)

0.8435754189944135

sklearn에서 제공하는 classifier 객체의 score 메서드를 사용하거나

sklearn.metrics의 accuracy_score 메서드를 사용하면 accuracy score를 구할 수 있습니다

 

✔️  그렇다면 Accuracy는 언제 사용하면 좋은걸까요?? (Important!)

Accuracy is good measure when the target variable class in the data are nearly balanced. example Survived(60%-yes, 40% no)

Accuracy score는 target variable이 거의 균등할때 사용하면 좋습니다. 

 

2) Precision

Precision is defined as the number of true positives divided by the number of true positives plus the number of false positives. Precision is about being precise

Precision, 여기서부터 조금 혼동됩니다(왜 이름은 혼동행렬이라 했는지 알 수 있습니다)

Precision이란 한마디로 '예측값이 얼마나 정확한가'라고 생각할 수 있습니다

 

혼동 행렬의 y축은 예측값(predicted)이고 x축은 실제값(Actual)입니다.

Precision은 생존(1)이라고 예측한 값 중에서 실제로 생존인 비율을 나타냅니다.

즉 TP(실제 생존자를 생존자라고 예측한 경우)와 FP(실제로는 사망자이지만 생존자라고 예측한 경우)를 더한 TP+FP 중 TP인 경우를 나타냅니다

아래의 그림과 수식으로 보면 보다 간단하게 이해 가능합니다.

 

Again, 생존자라고 예측한 경우중에 실제로 생존자인 비율이 어떻게 되냐?

3) Recall

When it is actually the positive result, how often does it predict correcly

Recall은 재현율입니다.

즉, 실제 생존자를 얼마나 맞췄느냐라고 생각하시면 됩니다

Precision과 연관지어 생각해본다면

Precision이 생존자라고 예측한값 중에서 실제 생존자를 예측한 정확도라면 Recall은 실제 생존자에 대헤 생존자를 얼마나 정확하게 예측했느냐로 이해하면 좋을것 같습니다

 

4) F1-Score

F1 score is the weighted average of Precision and Recall. Therefore, this score takes both false positives and false negatives into account.
Intuitively it is not as easy to understand as accuracy, but F1 is usually more useful than accuracy, especially if you have an uneven class distribution

여기서 등장하는 또 하나의 metric은 바로 f1-score입니다

결론부터 말씀드리면 f1-score는 Precision과 Recall에 대한  가중 평균(weighted average)입니다

따라서 f1-score는 false positive와 false negative를 고려합니다.

 

f1-score는 언제 사용하면 좋을까요?

f1-score는 데이터가 imbalance할 때 측정 도구로 사용하면 좋습니다

우리가 마주치는 대부분의 데이터는 불균형한 데이터의 분포를 갖기에 f1-scroe를 알아두시면 모델을 평가하는데 많은 도움이 됩니다

 

Again, Imbalce data를 평가하는 방법으로는 f1-score가 있습니다

 

그렇다면 지금까지 학습한 내용을 표로 한번 출력해보겠습니다

(sklearn은 정말 유용한 라이브러리를 많이 제공해주는것 같습니다...!!)

from sklearn.metrics import classification_report

print(classification_report(y_val, preds))

이제 해석해보겠습니다

해석

한 번 해석해보겠습니다

모델의 정확도는 84%입니다. 비교적 균등한 분포를 갖는 데이터이기에 84% 정확도를 해석해도 좋을 것 같습니다

하지만 학습데이터에서 생존자가 38.4% 사망자가61.6%로 조금은 불균형한 데이터라고 본다면 어떤 지표로 모델을 해석하는 것이 좋을까요?

저는 f1-score를 해석하는게 좋다고 생각합니다

f1-score를 보면 macro, weigted가 존재합니다. 두 값의 차이는 무엇일까요?

  • macro avg: 단순평균값
  • weighted avg: 각 클래스에 속하는 표본의 갯수로 가중평균값

다시 한 번 해석해보면 우리의 모델은  단순평균값으로는 82%의 f1-score를 보이며 가중평균으로는 0.84의 f1-score를 나타냅니다.

Accuracy와도 크게 차이가 나지않는것 보면 클래스 불균형으로 인한 문제는 적어보입니다.

 

2. Auc-Roc curve

AUC-ROC curve is a performance measurement for classification problem at various thresholds settings. ROC is a probability curve and AUC represents degree or measure of separability.

 

AUC-ROC curve는 모델이 class를 얼마나 잘 구별해 줄 수 있는지를 말해줍니다

AUC가 클수록 모델은 타이타닉호의 생존자와 사망자를 더 잘 구별해줍니다

 

from sklearn.metrics import roc_curve
import matplotlib.pyplot as plt
%matplotlib inline


fpr, tpr, thresholds = roc_curve(y_val,preds)

plt.plot(fpr, tpr, label='ROC curve')
plt.plot([0, 1], [0, 1], 'k--', label='Random guess')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve')
plt.xlim([-0.02, 1])
plt.ylim([0, 1.02])
plt.legend(loc="lower right")

 

ROC 곡선은 연결을 그래픽 방식으로 표시하는 데 자주 사용됩니다.

 

3. Logistic loss

Log loss, aka logistic loss or cross-entropy loss.

neural net 또는 multinominal logistic regression 등에 사용되는 metric입니다

확률적 분류기의 예측이 주어 졌을 때 실제 label의 음의 로그 우도(negative log-likelihood)로 정의됩니다.

Neural Net, Deep Learning 등에 자주 사용되는 지표입니다


Summary

TL;DR

Too Long, Didn't Read
- Accuracy: is good measure when the target variable class in the data are nearly balanced. example Survived(60%-yes, 40% no)
- f1-Score: is the weighted average of Precision and Recall. Therefore, this score takes both false positives and false negatives into account.if you have an uneven class distribution? than use f1-score
- AUC-ROC curve is a performance measurement for classification problem at various thresholds settings. ROC is a probability curve and AUC represents degree or measure of separability.
- Log loss, aka logistic loss or cross-entropy loss. when evaluate neural network
  • Accuracy는 분류 문제에서 타겟 레이블(또는 클래스)가 균등할 때 사용합니다
  • f1-score는 분류 문제에서 타겟 레이블이 불균형할때 사용합니다
  • AUC-ROC curve를 통해 생존자 사망자를 보다 명확하게 구분할 수 있습니다 (AUC가 클수록 모델은 타이타닉호의 생존자와 사망자를 더 잘 구별해줍니다)
  • Log loss 또는 cross-entropy loss는 neural net등에서 자주 찾아보실 수 있습니다

 

오늘은 분류문제(Classification)를 위한 Machine Learning Model의 평가 방법에 대해 알아보았습니다.

그동안 confusion matrix를 알고 있었다고 생각했었는데 자세한 사용법과 그 의미에 대해서 깊게 이해하지 못했던 것 같은 아쉬움이 있었습니다.

오늘 이 시간을 통해 단순히 Accuracy가 좋은 머신러닝 모델이 아닌 유의미한 머신러닝 모델을 구축하고 해석하는 방법을 다시한번 정리할 수 있었습니다.

 

앞으로는 단순히 모델링을 하는데 그치지 않고 제가 만든 모델이 얼마나 유의미한 모델인지 조금 더 신경써서 해석하고 평가하는 시간을 갖게 될 것같습니다.

머신러닝 Master가 되는 그날까지...!

 

이상 Steve-Lee였습니다. 감사합니다!

댓글