Machine Learning Evaluation
- Evaluation Metric (성능 평가 지표) : 모델의 타입(분류 / 회귀)에 따라 나뉨
- 회귀 : 대부분 실제값과 예측값의 오차 평균값에 기반함
- 분류 : 실제 결과 데이터와 예측 결과 데이터의 차이만으로 판단하지는 않음.
- 특히, 이진 분류(0 or 1로 판단)에서는 accuracy score보다는 다른 성능 평가 지표를 함께 사용하는 것이 선호됨.
- 분류의 성능 평가 지표
- 정확도(Accuracy) : 불균형한 label data set에서 사용 X
- 오차행렬(confusion Matrix) : 오차의 정도, 종류를 알 수 있음
- 정밀도(Precision) : (선호됨)
- 재현율(Recall) : (선호됨)
- F1 스코어
- ROC AUC
- 분류는 label class 값 종류에 따라 이진분류(0 or 1) or 멀티 분류로 구분됨
- 위의 6가지는 이진분류에서 중요하게 다루는 방법들임.
Accuracy
- 정확도 : 실제 데이터에서 예측 데이터가 얼마나 같은지를 판단하는 지표
정확도(Accuray) = 예측 결과가 동일한 데이터 건수 / 전체 예측 데이터 건수- 직관적으로 모델 예측 성능을 나타내는 평가 지표
- 불균형한 label data set에서는 사용하면 안된다.
- 이진 분류의 경우, 데이터 구성에 따라 모델 성능을 왜곡할 수 있기에 정확도는 여러개를 사용하는 것이 좋음.
- titanic에 대해 sklearn으로 보는 '정확도 지표가 모델 성능을 왜곡하는 예제
- 불균형한 label 값 분포에서 ML 모델의 성능을 판단할 경우, 적합하지 않음.
In [30]:
# 단순히 Sex feature가 1(남자)이면 0(사망), 그렇지 않으면(여자면) 1(생존)로 예측하는 단순한 Classifier
import pandas as pd
from sklearn.base import BaseEstimator
class MyDummyClassifier(BaseEstimator):
# fit() method는 아무것도 학습하지 않음.
def fit(self, X, y=None):
pass
# predict() method는 단순히 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
In [31]:
# 데이터 전처리 함수
from sklearn.preprocessing import LabelEncoder
# 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
# 머신러닝 알고리즘에 불필요한 속성 제거
def drop_features(df):
df.drop(['PassengerId','Name','Ticket'],axis=1,inplace=True)
return df
# 레이블 인코딩 수행.
def format_features(df):
df['Cabin'] = df['Cabin'].str[:1]
features = ['Cabin','Sex','Embarked']
for feature in features:
le = LabelEncoder()
le = le.fit(df[feature])
df[feature] = le.transform(df[feature])
return df
# 앞에서 설정한 Data Preprocessing 함수 호출
def transform_features(df):
df = fillna(df)
df = drop_features(df)
df = format_features(df)
return df
In [32]:
# 생성된 MyDummyClassifier를 이용해 titanic 생존자 예측을 수행.
# transform_features는 2장에서 진행한 데이터 처리함수
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import numpy as np
# 원본 데이터를 재로딩, 데이터 가공, 학습 데이터/테스트 데이터 분할.
titanic = pd.read_csv('data/titanic_train.csv')
titanic_y = titanic['Survived']
titanic_X = titanic.drop('Survived', axis=1)
X_titanic = transform_features(titanic_X)
X_train, X_test, y_train, y_test = train_test_split(titanic_X, titanic_y, 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)))
MNIST DATASET로 해보는 accuracy_score 실습
: MNIST dataset를 변환해 불균형한 dataset에 대한 정확도의 오류를 확인해보는 코드
MNIST dataset
- 0-9까지의 숫자 이미지의 픽셀 정보를 가지고 있음
- 숫자 Digit을 예측하는데 사용함
- load_digits() API를 통해 MNIST dataset를 제공함
- 원래 MNIST에서는 값이 0-9까지 multi label임.
- 이진분류 문제로의 변형을 위해 7에 대해 True, 나머지는 False로 바꾸고 시작.
- 모든 데이터를 False, 즉 0ㅡ로 예측하는 Classifier를 이용해 정확도를 측정 -> 0.9예상
- 데이터 불균형 정도가 심할수록 이 Classifier의 성능이 높은 수치를 기록하게 됨
In [33]:
# 불균형한 dataset의 DummyClassifier를 생성함
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)
In [34]:
digits.target == 7
Out[34]:
In [35]:
# 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 [36]:
# 불균형한 레이블 데이터 분포도 확인.
print('레이블 테스트 세트 크기 :', y_test.shape)
print('테스트 세트 레이블 0 과 1의 분포도')
print(pd.Series(y_test).value_counts())
# Dummy Classifier로 학습/예측/정확도 평가
fakeclf = MyFakeClassifier()
fakeclf.fit(X_train , y_train)
fakepred = fakeclf.predict(X_test)
print('모든 예측을 0으로 하여도 정확도는:{:.3f}'.format(accuracy_score(y_test , fakepred)))
'AI Study > Machine Learning' 카테고리의 다른 글
분류 (1) - Decision Tree (0) | 2021.12.05 |
---|---|
머신러닝 성능 평가 지표 (2) - 정밀도,재현율,F1 score, ROC curve (0) | 2021.11.28 |
데이터 전처리 기본 (2) - feature scailing (0) | 2021.11.21 |
데이터 전처리 기본 (1) - data encoding (0) | 2021.11.21 |
sklearn의 model selction module (데이터셋 분리 및 교차검증) (0) | 2021.09.06 |