도찐개찐
[머신러닝] 06. 오차행렬 본문
머신러닝의 모델평가
- 일반적으로 머신러닝은
- 데이터 가공/변환(전처리)
- 모델 학습/예측
- 평가의 과정을 거침
- 앞의 타이타닉 예제에서 모델의 평가는 정확도만 사용했음
- 한편, 머신러닝의 예측성능의 평가방법은 다양함
- 회귀 - R^2, MSE평균제곱오차
- 분류 - 혼동(오차)행렬, 크로스엔트로피, 최대우도, ROC, AUC, F1스코어
정확도의 함정
- 앞의 타이타닉 생존자 ML예제의 정확도는 평균 80%였음
- 그런데 정확도 지표만으로 ML 모델의 성능을 파악하기에는 다소 문제가 있음 - 왜곡의 위험
- 즉, 탐색적 분석을 시행했을때 성별을 기준으로 생존비율은 여성일 때가 더 높았음
- 따라서, 굳이 ML 알고리즘을 적용하지 않아도 성별이 여성일 경우 생존, 남성일 경우 사망이라고 예측해도 크게 무리 없음
- 단순히 성별 조건 하나만 적용해도 별거 아닌 알고리즘으로도 높은 정확도가 나타나는 상황 발생
가짜 분류기 생성
- 성별이 남자면 사망
- 성별이 여자면 생존이라고 예측하는 더미분류기 생성
from sklearn.base import BaseEstimator
class MyDummyClassifier(BaseEstimator):
# 아무것도 학습하지 않는 fit 메서드 정의
def fit(self, X, y=None):
pass
# 성별이 1(남성)이면 0(사망), 0이면 1
def predict(self, X):
pred = np.zeros((X.shape[0], 1))
# 입력데이터 크기만큼 0으로 채워진 1차원 행렬 생성
for i in range(X.shape[0]):
if X['gender'].iloc[i] != 1:
pred[i] = 1
# 성별이 여성인 경우 1로 설정
return pred
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import sklearn
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
titanic = pd.read_csv('../data/titanic2.csv')
titanic
data = titanic.iloc[:, 1:12]
target = titanic.survived
X_train, X_test, y_train, y_test = train_test_split(data, target, train_size = 0.7,
stratify=target)
dmyclf = MyDummyClassifier()
dmyclf.fit(X_train, y_train)
pred = dmyclf.predict(X_test)
accuracy_score(y_test, pred)
0.7857142857142857
# 즉, 이렇게 단순한 알고리즘만으로 예측하더라도
# 데이터의 구성에 따라 정확도가 약 76%가 나옴
# 불균형한 레이블의 비율()에서는
# 정확도 지표만으로 모델 성능을 평가하는 것은 올바르지 않음
# 예를 들어, 100개의 종속변수 중 90개의 레이블 0이고, 10개의 레이블이 1인 경우,
# 무조건 0으로 예측결과를 반환하는 머신러닝 알고리즘의 정확도는 90%임!
# 즉, 선생님이 시험 정답지의 답을 1로만 작성한 경우,
# 학생이 1로 찍기만 해도 100점을 맞는 경우와 비슷한 상황임!
# 따라서, 불균형한 레이블 데이터세트의 성능수치로
# 정확도 평가지표를 사용하면 안됨
# 이러한 한계를 극복하기 위해 오차행렬 사용
# 특히, 정확도보다는 정밀도, 재현율을 더 선호
오차행렬
TP : 임신을 했다고 예측 했는데 임신을 한 케이스
TN : 임신을 안했다고 예측 했는데 임신을 안한 케이스
----------------------------------------
FP : 임신을 했다고 예측 했는데 임신을 안한 케이스
FN : 임신을 안했다고 예측했는데 임신을 한 케이스
맞는것 = 양성 : Positive, 1
틀린것 = 음성 : Negative, 0
from sklearn.metrics import confusion_matrix
confusion_matrix(y_test, pred)
array([[203, 40],
[ 44, 105]])
from sklearn.metrics import classification_report
print(classification_report(y_test, pred))
precision recall f1-score support
0 0.82 0.84 0.83 243
1 0.72 0.70 0.71 149
accuracy 0.79 392
macro avg 0.77 0.77 0.77 392
weighted avg 0.78 0.79 0.79 392
정확도accuracy
맞는 것
을 맞다고,틀린 것
을 틀리다고 올바르게 예측한 것- $ accuracy = \frac {TP + TN} {TP + FN + FP + TN} $
- 위 혼동행렬 대각선 부분
accuracy_score(y_test, pred)
# array([[203, 40],
# [ 44, 105]])
0.7857142857142857
(203 + 105) / (203 + 44 + 40 + 105)
0.7857142857142857
정밀도Precision
- 모델의 예측값이 얼마나 올바른지 알아봄
- 양성이라고 예측한 것이 얼마나 맞았는지 알아봄 * 스팸분류 분야에서 주 활용 됨
- $precision = \frac {TP} {TP+FP}$
- 위 오차행렬 1열 부분
from sklearn.metrics import precision_score
precision_score(y_test, pred)
0.7241379310344828
재현율Recall
- 실제로
맞는 것
중 맞다고 예측된 것들의 비율 - 민감도Sensitivity(통계학), 적중률hit rate(마케팅) * 임상분야에서 주 활용 됨
- $recall = \frac {TP} {TP+FN}$
- 위 오차행렬 1행 부분
# array([[203, 40],
# [ 44, 105]])
(203) / (203 + 40)
0.8353909465020576
특이도Specificity
틀린 것
중 틀리다고 예측된 것들의 비율- $\frac {FP} {TN+FP}$
- 위 오차행렬의 2행 부분
(40) / (105 + 40)
0.27586206896551724
간단예제 - 정확도, 정밀도, 재현율(민감도)
- 6마리의 동물형상 중 개p/고양이n를 맞추는 게임을 진행
- 정답 =
[개 개 개 고양이 개 고양이]
- 예측 =
[개 고양이 개 고양이 개 개 ]
def getAnimal(x):
return 'p' if x == '개' else 'n'
### 오차행렬
# predict
# actual [3 1][개,개 | 개,고양이]
# [1 1][고양이,개 | 고양이,고양이]
### 정확도 = 개를 '개'라고, 고양이를 '고양이'라고 예측한 비율
4/6
0.6666666666666666
### 정밀도 = 얼마나 개를 잘 예측 했는가?
### 개라고 예측 : 1, 3, 5, 6
## 실제 개 : 1, 2, 3, 5
3/4
0.75
### 재현율 - 실제 개중에서 얼마나 적중했는가?
### 실제 개 : 1, 2, 3, 5
### 개라고 적중 : 1, 3, 5, 6
3/4
0.75
ytest = ['개', '개', '개', '고양이', '개', '고양이']
pred = ['개', '고양이', '개', '고양이', '개', '개' ]
confusion_matrix(ytest, pred)
array([[3, 1],
[1, 1]])
# print(classification_report(y_test, pred, pos_label='개'))
#정확도
accuracy_score(ytest, pred)
0.6666666666666666
#정밀도
precision_score(ytest, pred, pos_label='개')
0.75
#재현률
from sklearn.metrics import recall_score
recall_score(ytest, pred, pos_label='개')
0.75
1종오류/2종오류 알아보기
- 전자회로기판PCB 생산업체에서 불량률이 6% 이하일때
- 계약업체로 선적해서 납품한다는 품질보증계약 체결함
- 불량률 6% 이하 선적 함(P), 불량률 6% 초과 선적 안함(N)
# 2종 오류(FN)
# 4000개의 회로판에서 표본 50개 추출
# 4개가 불량 -> 0.08 -> 8% -> 선적x
# 그런데, 4개의 불량이 전체 4000개에서 유일하다면?
# 불량률 0.1% -> 선적취소는 잘못된 결정
# 1종 오류(FP)
# 4000개의 회로판에서 표본 50개 추출
# 2개가 불량 -> 0.04 -> 4% -> 선적o
# 그런데, 48개 정상품이 전체 4000개에서 유일
# 불량률 98.8% -> 선적허용은 잘못된 결정
정밀도/재현율 trade-off
- 분류하는 업무의 특성상 정밀도 또는 재현율이 특별히 강조되어야 하는 경우(특히 임상의료)
- 정밀도 : 스팸분류(FP 중시 - 1종 오류)
- 재현률 : 임상실험(FN 중시 - 2종 오류)
- 결정 임계값을 조정하면 정밀도 또는 재현율을 높일 수 있음
- 즉, 이진분류에서 0 또는 1로 판정할 기준값을 의미
- 임계값을 0.5로 정하는 경우 기준값보다 확률이 크면 positive, 작으면 negative로 결정
- 한편, 정밀도와 재현율은 상호보완적인 지표이기때문에,
- 어느 한쪽을 올리면 다른 한쪽은 떨어지는 관계를 뜀
728x90
'PYTHON > 데이터분석' 카테고리의 다른 글
[머신러닝] 08. 로지스틱 회귀 (0) | 2023.01.03 |
---|---|
[머신러닝] 07. ROC 그래프 (0) | 2023.01.03 |
[머신러닝] 05. 데이터 전처리 (0) | 2023.01.03 |
[머신러닝] 04. 머신러닝 타이타닉 생존자 예측 (0) | 2023.01.03 |
[머신러닝] 03. 훈련과 테스트 데이터 (0) | 2023.01.03 |
Comments