2 분 소요


평가(Evaluation)

정확도(accuracy)만으로는 평가가 힘든 데이터들도 있다!
분류에 사용되는 성능 평가 지표(Evaluation Matric)에 대해 알아보자

정확도(Accuracy)

\[정확도(Accuracy) = \frac{예측 결과가 동일한 데이터 건수}{전체 예측 데이터 건수}\]

타이타닉 데이터셋

In [1]:
from sklearn.base import BaseEstimator
In [2]:
# 커스텀 Classifier 작성
class MyDummyClassifier(BaseEstimator):
    # 아무것도 학습하지 않음
    def fit(self, X, y=None):
        pass
    # 단순히 sex에 따라 1은 0, 아니면 1로 출력
    def predict(self, X):
        pred = np.zeros((X.shape[0], 1)) # 입력되는 X의 행(데이터 수)에 대한 결과값 1개
        for i in range(X.shape[0]):
            if X['Sex'].iloc[i] == 1:
                pred[i] = 0
            else:
                pred[i] = 1
        return pred
In [3]:
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

이전에 작성한 일괄처리 함수 재사용

In [4]:
# Null 처리 함수
def fillna(df):
    df['Age'].fillna(df['Age'].mean(), inplace=True)
    df['Cabin'].fillna('N', inplace=True)
    df['Embarked'].fillna('N', inplace=True)
    df['Fare'].fillna('0', inplace=True)
    return df

# 불필요한 feature 제거
def drop_features(df):
    df.drop(['PassengerId', 'Name', 'Ticket'], axis=1, inplace=True)
    return df

# 레이블 인코딩
def format_features(df):
    from sklearn.preprocessing import LabelEncoder
    df['Cabin'] = df['Cabin'].str[:1]
    features = ['Sex', 'Cabin', 'Embarked']
    for feature in features:
        le = LabelEncoder()
        df[feature] = le.fit_transform(df[feature])
        print(le.classes_)
    return df

# 데이터 전처리 함수 전체 호출
def transform_features(df):
    df = fillna(df)
    df = drop_features(df)
    df = format_features(df)
    return df

# 데이터 불러오기
df = pd.read_csv('titanic.csv')
y = df['Survived']
X = df.drop(columns=['Survived'])

# 데이터 전체 전처리 진행
X = transform_features(X)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=11)
Out [4]:
['female' 'male']
['A' 'B' 'C' 'D' 'E' 'F' 'G' 'N' 'T']
['C' 'N' 'Q' 'S']

In [5]:
myclf = MyDummyClassifier()
myclf.fit(X_train, y_train)
pred = myclf.predict(X_test)
In [6]:
print("커스텀 Classifier 정확도 :", accuracy_score(y_test, pred))
Out [6]:
커스텀 Classifier 정확도 : 0.8324022346368715

  • 특히 이진분류에서 label의 불균형이 심할 경우 정확도 만으로는 잘못된 평가가 나올수 있다!

MNIST 데이터셋

In [7]:
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.base import BaseEstimator
from sklearn.metrics import accuracy_score
import numpy as np
import pandas as pd
In [8]:
# 커스텀 Classifier 작성
class MyFakeClassifier(BaseEstimator):
    def fit(self, X, y):
        pass
    
    def predict(self, X):
        return np.zeros((len(X), 1), dtype=bool)
In [9]:
# MNIST 데이터 로딩
digits = load_digits()
In [10]:
# digits 번호가 7이면 True이고 이를 astype(int)로 1로 변환, 7이 아니면 False이고 0이로 변환
y = (digits.target == 7).astype(int)
X_train, X_test, y_train, y_test = train_test_split(digits.data, y, random_state=11)
In [11]:
# 불균형한 레이블 데이터 분포도 확인
print('레이블 테스트 세트 크기 :', y_test.shape)
print(pd.Series(y_test).value_counts())
Out [11]:
레이블 테스트 세트 크기 : (450,)
0    405
1     45
dtype: int64

In [12]:
# Fake Classifier로 학습/예측/정확도 평가
fakeclf = MyFakeClassifier()
fakeclf.fit(X_train, y_train)
fakepred = fakeclf.predict(X_test)
print(f"가짜 Classifier의 정확도 : {accuracy_score(y_test, fakepred)}")
Out [12]:
가짜 Classifier의 정확도 : 0.9

모든 예측을 0으로 해도 정확도가 90%가 나와버림!

오차 행렬(Confusion matrix)

img

In [13]:
from sklearn.metrics import confusion_matrix
In [14]:
confusion_matrix(y_test, fakepred)
Out [14]:
array([[405,   0],
       [ 45,   0]], dtype=int64)
  • 정확도 = (맞춘건수)/(전체건수) = 타이타닉(103+46)/(103+46+15+15) = MNIST(405+0)/(405+0+45+0) = \(\frac{(TN+TP)}{(TN+TP+FN+FP)}\)

불균형한 레이블 클래스를 가지는 이진 분류 모델에서는 Positive보다 Negative의 데이터 건수가 월등히 많도록 값을 부여하는 경우가 많다.
예를 들어 사기 행위를 1로 정상 행위를 0으로 할 경우, 암 검진 예측모델에서 양성일 경우 1로 음성일 경우 0할 경우가 있다.
이때 정확도 지표는 비대칭한 데이터 세트에서 Positive에 대한 예측 정확도를 판단하지 못한 채 Negative에 대한 예측 정확도만으로도 분류의 정확도가 매우 높게 나타나는 수치적인 판단오류를 일으키게 된다.

정밀도와 재현율

정밀도와 재현율은 Positive 데이터 세트의 예측 성능에 좀 더 초점을 맞춘 평가 지표이다.

  • 정밀도(1이라 예측한 값 기준으로) = (1이라 예측한 값 중 맞춘 값)/(1이라 예측한 값) = \(\frac{TP}{(FP+TP)}\)
    모델이 1이라 예측한 것 중에 맞춘것(양성 예측도)

  • 재현율(실제값 1을 기준으로) = (실제 1인 값 중에 맞춘 값)/(실제 1인 값) = \(\frac{TP}{(FN+TP)}\)
    실제 1인것 중 맞춘것(민감도;Sensitivity, TPR;True Positive Rate)

정밀도와 재현율은 서로 연관되어 하나가 높으면 하나는 떨어져서 보통 밸런스를 맞춰야 한다

  • 재현율이 상대적으로 더 중요한 지표인 경우 : 실제 Positive인 데이터를 Negative로 잘못 판단할 경우 업무상 큰 영향이 발생하는 경우
    예) 암판단 모델 : 암환자가 아닌 사람을 암환자로 판단하는 것보다 실제 암환자를 아니라고 판단할 경우 문제가 더 심각하다.

  • 정밀도가 상대적으로 더 중요한 지표인 경우 : 실제 Negative인 데이터를 Positive로 잘못 판단할 경우 업무상 큰 영향이 발생하는 경우
    예) 스팸메일 모델 : 스팸메일인데 아니라 판단하는 것보다 스팸이 아닌 중요한 메일을 스팸이라 판단할 경우 문제가 더 심각하다.

Reference

  • 이 포스트는 SeSAC 인공지능 자연어처리, 컴퓨터비전 기술을 활용한 응용 SW 개발자 양성 과정 - 심선조 강사님의 강의를 정리한 내용입니다.

댓글남기기