Machine Learning (5) - 정확도의 한계
평가(Evaluation)
정확도(accuracy)만으로는 평가가 힘든 데이터들도 있다!
분류에 사용되는 성능 평가 지표(Evaluation Matric)에 대해 알아보자
정확도(Accuracy)
\[정확도(Accuracy) = \frac{예측 결과가 동일한 데이터 건수}{전체 예측 데이터 건수}\]타이타닉 데이터셋
from sklearn.base import BaseEstimator
# 커스텀 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
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
이전에 작성한 일괄처리 함수 재사용
# 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)
['female' 'male']
['A' 'B' 'C' 'D' 'E' 'F' 'G' 'N' 'T']
['C' 'N' 'Q' 'S']
myclf = MyDummyClassifier()
myclf.fit(X_train, y_train)
pred = myclf.predict(X_test)
print("커스텀 Classifier 정확도 :", accuracy_score(y_test, pred))
커스텀 Classifier 정확도 : 0.8324022346368715
- 특히 이진분류에서 label의 불균형이 심할 경우 정확도 만으로는 잘못된 평가가 나올수 있다!
MNIST 데이터셋
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
# 커스텀 Classifier 작성
class MyFakeClassifier(BaseEstimator):
def fit(self, X, y):
pass
def predict(self, X):
return np.zeros((len(X), 1), dtype=bool)
# MNIST 데이터 로딩
digits = load_digits()
# 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)
# 불균형한 레이블 데이터 분포도 확인
print('레이블 테스트 세트 크기 :', y_test.shape)
print(pd.Series(y_test).value_counts())
레이블 테스트 세트 크기 : (450,)
0 405
1 45
dtype: int64
# Fake Classifier로 학습/예측/정확도 평가
fakeclf = MyFakeClassifier()
fakeclf.fit(X_train, y_train)
fakepred = fakeclf.predict(X_test)
print(f"가짜 Classifier의 정확도 : {accuracy_score(y_test, fakepred)}")
가짜 Classifier의 정확도 : 0.9
모든 예측을 0으로 해도 정확도가 90%가 나와버림!
오차 행렬(Confusion matrix)
from sklearn.metrics import confusion_matrix
confusion_matrix(y_test, fakepred)
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 개발자 양성 과정 - 심선조 강사님의 강의를 정리한 내용입니다.
댓글남기기