(1) 정확도


머신러닝은 데이터 가공/변환, 모델 학습/예측, 그리고 평가(Evaluation)의 프로세스로 구성

머신러닝 모델은 여러 가지 방법으로 예측 성능을 평가할 수 있음

성능 평가 지표(Evaluation Metric)는 일반적으로 모델이 분류냐 회귀냐에 따라 여러 종류로 나뉨

회귀의 경우 대부분 실제 값과 예측값의 오차 평균값에 기반

  • 예를 들어 오차에 절댓값을 씌운 뒤 평균 오차를 구하거나 오차의 제곱 값에 루트를 씌운 뒤 평균 오차를 구하는 방법 등

  • 기본적으로 예측 오차를 가지고 정규화 수준을 재가공 하는 방법이 휘귀의 성능 평가 지표 유형

분류의 평가 방법도 일반적으로는 실제 결과 데이터와 예측 결과 데이터가 얼마나 정확하고 오류가 적게 발생하는 가에 기반하지만, 단순히 이러한 정확도만 가지고 판단했다가는 잘못된 평가 결과에 빠질 수 있음

본 장에서는 분류에 사용되는 성능 평가 지표에 대해서 집중적으로 설명함

  • 특히 0과 1로 결정값이 한정되는 이진 분류의 성능 평가 지표에 대해서 집중적으로 설명!

분류의 성능 평가 지표
  • 정확도 (Accuracy)

  • 오차행렬 (Confusion Matrix)

  • 정밀도 (Precision)

  • 재현율 (Recall)

  • F1 스코어

  • ROC곡선과 AUC

  • 분류는 결정 클래스 값 종류의 유형에 따라 긍정/부정과 같은 2개의 결괏값만을 가지는 이진 분류여러 개의 결정 클래스 값을 가지는 멀티 분류로 나뉠 수 있음

    • 결정 클래스는 "가능한 정답의 집합"이고 label은 "각 데이터의 실제 정답"

  • 위에서 언급한 분류의 성능 지표는 이진/멀티 분류 모두에 적용되는 지표이지만, 특히 이진 분류에서 더욱 중요하게 강조하는 지표!


왜 위 지표가 모두 이진 분류에서 중요할까?

정확도 (Accuracy)

실제 데이터에서 예측 데이터가 얼마나 같은지를 판단하는 지표

즉, 예측 결과가 동일한 데이터 건수를 전체 예측 데이터 건수로 나눈 값

  • 정확도는 직관적으로 모델 예측 성능을 나타내는 평가 지표

  • 하지만 이진 분류의 경우 데이터의 구성에 따라 ML 모델의 성능을 왜곡할 수 있기 때문에 정확도 수치 하나만 가지고 성능을 평가하지 않음

 

그렇다면 정확도 지표가 어떻게 ML 모델의 성능을 왜곡할까?

  • 앞의 타이타닉 예제 수행 결과를 보면 한 가지 의구심이 생길 수 있음

  • ML 알고리즘을 적용한 후 예측 정확도의 결과가 보통 80%대였지만, 탑승객이 남자인 경우보다 여자인 경우에 생존 확률이 높았기 때문에 별다른 알고리즘의 적용 없이 무조건 성별이 여자인 경우 생존으로, 남자인 경우 사망으로 예측 결과를 예측해도 이와 비슷한 수치가 나올 수 있음

    • 단지 성별 조건 하나만을 가지고 결정하는 별거 아닌 알고리즘도 높은 정확도를 나타내는 상황 발생!

 

다음 예제에서는 사이킷런의 BaseEstimator 클래스를 상속받아 아무런 학습을 하지 않고, 성별에 따라 생존자를 예측하는 단순한 Classifier 생성

Python
import numpy as np from sklearn.base import BaseEstimator class MyDummyClassifier(BaseEstimator): # fit( ) 메소드는 아무것도 학습하지 않음. def fit(self, X , y=None): pass # predict( ) 메소드는 단순히 Sex feature가 1 이면 0 , 그렇지 않으면 1 로 예측함. def predict(self, X): pred = np.zeros((X.shape[0], 1)) for i in range (X.shape[0]) : if X['Sex'].iloc[i] == 1: pred[i] = 0 else : pred[i] = 1 return pred

 

MyDummyClassifier를 이용해 앞 장의 타이타닉 생존자 예측 수행

Python
import pandas as pd from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score # 원본 데이터를 재로딩, 데이터 가공, 학습 데이터/테스트 데이터 분할. titanic_df = pd.read_csv('train.csv') y_titanic_df = titanic_df['Survived'] X_titanic_df= titanic_df.drop('Survived', axis=1) X_titanic_df = transform_features(X_titanic_df) X_train, X_test, y_train, y_test=train_test_split(X_titanic_df, y_titanic_df, test_size=0.2, random_state=0) # 위에서 생성한 Dummy Classifier를 이용해 학습/예측/평가 수행. myclf = MyDummyClassifier() myclf.fit(X_train, y_train) mypredictions = myclf.predict(X_test) print('Dummy Classifier의 정확도는: {0:.4f}'.format(accuracy_score(y_test, mypredictions))) >>> Dummy Classifier의 정확도는: 0.7877
  • 이렇게 단순한 알고리즘으로 예측을 하더라도 데이터의 구성에 따라 정확도 결과는 약 78.77%로 꽤 높은 수치가 나올 수 있기에 정확도를 평가 지표로 사용할 때는 매우 신중해야 함!

  • 특히 정확도불균형한(imbalanced) label 값 분포에서 ML 모델의 성능을 판단할 경우, 적합한 평가 지표가 아님

    • 예를 들어 100개의 데이터가 있고 이 중에 90개의 데이터 label이 0, 단 10개의 데이터 label이 1이라고 한다면 무조건 0으로 예측 결과를 반환하는 ML 모델의 경우라도 정확도가 90%나 됨

 

MNIST 데이터 세트를 변환해 불균형한 데이터 세트로 만든 뒤에 정확도 지표 적용시 문제점 확인

  • MNIST 데이터 세트트 0부터 9까지의 숫자 이미지의 픽셀 정보를 가지고 있으며, 이를 기반으로 숫자 Digit를 예측하는 데 사용

  • 사이킷런은 load_digits() API를 통해 MNIST 데이터 세트 제공

  • 원래 MNIST 데이터 세트는 label 값이 0부터 9까지 있는 멀티 label 분류를 위한 것이지만, 이것을 label=7인 것만 True, 나머지는 모두 False로 변환해 이진 분류 문제로 변경

 

아무것도 하지 않고 무조건 특정한 결과로 예측 결과를 반환해도 데이터 분포도가 균일하지 않은 경우 높은 수치가 나타날 수 있는 것정확도 평가 지표의 맹점!

 

  • 불균형한 데이터 세트와 Dummy Classifier 생성

Python
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 class MyFakeClassifier(BaseEstimator): def fit(self,X,y): pass # 입력값으로 들어오는 X 데이터 셋의 크기만큼 모두 0값으로 만들어서 반환 def predict(self,X): return np.zeros( (len(X), 1) , dtype=bool) # 사이킷런의 내장 데이터 셋인 load_digits( )를 이용하여 MNIST 데이터 로딩 digits = load_digits() print(digits.data) print("### digits.data.shape:", digits.data.shape) print(digits.target) print("### digits.target.shape:", digits.target.shape)