도찐개찐
[머신러닝] 07. ROC 그래프 본문
ROC
- Receiver Operation Characteristic
- 수신자 판단 곡선
- 세계 2차 대전 통신 장비 성능 평가를 위해 고안된 수치
- 레이더 데이터를 분석하여 적 항공기와 신호 소음을 구별하는 데 사용
- 수신기의 감도가 증가함에 따라 거짓 긍정의 수(즉, 특이성)이 감소함
- 의학분야에 많이 사용되지만, 머신러닝의 이진 분류 모델 예측 성능 평가에도 사용
- ROC곡선의 y축은 '민감도TPR'를, x축은 '1-재현율FPR'로 그림
- FPR : FP/(TN+FP) : 아군항공기 소리를 적항공기 소리라고 오판한 비율 - 낮아야 함
- TPR : TP/(TP+FN) : 적항공기 소리를 적항공기 소리라고 잘판단한 비율 - 높아야 함
- FPR이 변할때 TPR이 어떻게 변하는지 알아봄
- 모델이 양성/긍정으로 예측했을때 얼마나 잘 맞추고 있는지를 설명한 것
ROC 그래프 그리기
- 타이타닉 데이터셋으로 로지스틱회귀 분석한 후
- 특이도, 재현율을 구한후 ROC 그래프 작성
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn.metrics import recall_score
from sklearn.metrics import precision_score
from sklearn.preprocessing import LabelEncoder
def getAge(x):
result = 'a'
if 80 < x <= 90:
result = 'b'
elif 70 < x <= 80:
result = 'c'
elif 60 < x <= 70:
result = 'd'
elif 50 < x <= 60:
result = 'e'
elif 40 < x <= 50:
result = 'f'
elif 30 < x <= 40:
result = 'g'
elif 20 < x <= 30:
result = 'h'
elif 10 < x <= 20:
result = 'i'
elif 5 < x <= 10:
result = 'j'
elif x <= 5:
result = 'k'
return result
def getFare(x):
result = 'a'
if 400 < x <= 500:
result = 'b'
elif 300 < x <= 400:
result = 'c'
elif 200 < x <= 300:
result = 'd'
elif 100 < x <= 200:
result = 'e'
elif x <= 100:
result = 'f'
return result
random_state = 2211171140
titanic = pd.read_csv('../data/titanic2.csv')
titanic['Age'] = titanic.age.apply(lambda x: getAge(x))
titanic['Fare'] = titanic.fare.apply(lambda x: getFare(x))
encoder = LabelEncoder()
encoder.fit(titanic.Age)
titanic['Age'] = encoder.transform(titanic.Age)
encoder = LabelEncoder()
encoder.fit(titanic.Fare)
titanic['Fare'] = encoder.transform(titanic.Fare)
titanic
field = ['pclass', 'sibsp', 'parch', 'Title', 'gender', 'Embarked', 'age', 'fare']
data = titanic.loc[:, field]
target = titanic.survived
X_train, X_test, y_train, y_test = train_test_split(data, target, train_size = 0.7,
stratify=target, random_state=random_state)
lrclf = LogisticRegression(random_state=random_state, max_iter=500)
lrclf.fit(X_train, y_train)
pred = lrclf.predict(X_test)
accuracy_score(y_test, pred)
0.8061224489795918
분류 알고리즘 종류
- 판별함수 모형
- 주어진 데이터를 범주category에 따라 서로 다른 영역으로 나누는 경계면decision boundary을 찾아낸 후, 이 경계면을 기준으로 데이터가 어디에 있는지를 계산하는 함수를 이용
- 확률적 판별/생성 모형
- 주어진 데이터에 대해 각 범주category/레이블이 정답일 조건부확률을 계산하는 방법에 따라 조건부 확률함수를 추정하거나 베이즈 정리를 사용해서 분류하는 모형
- 따라서, 분류기의 예측 불확실성을 추정하려면 scikit-learn에서 제공하는 2가지 함수를 사용
decision function
,predict_proba
### 타이타닉 생존 예측확률 알아보기1
X_test[:5]
pclass | sibsp | parch | Title | gender | Embarked | age | fare | |
---|---|---|---|---|---|---|---|---|
951 | 3 | 0 | 0 | 13 | 1 | 0 | 22.0 | 7.2250 |
364 | 2 | 1 | 0 | 16 | 1 | 2 | 54.0 | 26.0000 |
1125 | 3 | 0 | 0 | 13 | 1 | 2 | 19.0 | 7.8958 |
1170 | 3 | 8 | 2 | 10 | 0 | 2 | 28.0 | 69.5500 |
393 | 2 | 0 | 1 | 10 | 0 | 2 | 18.0 | 23.0000 |
# 판별함수 모형으로 생존 여부 확인 : 이산형 수치 출력
lrclf.predict(X_test[:5])
array([0, 0, 0, 0, 1])
# 확률적 판별/생성 모형으로 생존여부 확인
lrclf.predict_proba(X_test[:5])
array([[0.81780204, 0.18219796],
[0.90538997, 0.09461003],
[0.87151718, 0.12848282],
[0.81173904, 0.18826096],
[0.17735944, 0.82264056]])
타이타닉 승객 생존 여부 확률값 추출
- 타이나닉 승객 생존 여부에서 생존(1)이 주된 관심사이므로
- 생존에 대한 확률값만 따로 추출
pred_proba = lrclf.predict_proba(X_test)
pred_proba[:5, 1]
array([0.18219796, 0.09461003, 0.12848282, 0.18826096, 0.82264056])
# 실제값, 확률값, 예측값을
# 하나의 데이터 프레임에 작성
table = pd.DataFrame()
table['실제값'] = y_test
table['생존 확률값'] = pred_proba[:, 1]
table['예측값'] = lrclf.predict(X_test)
table.head()
실제값 | 생존 확률값 | 예측값 | |
---|---|---|---|
951 | 1 | 0.182198 | 0 |
364 | 0 | 0.094610 | 0 |
1125 | 0 | 0.128483 | 0 |
1170 | 0 | 0.188261 | 0 |
393 | 1 | 0.822641 | 1 |
각 예측값 별 특이도fprs, 민감도(재현률)tprs, 임계값을 구함
- tprs : 실제값이 양성(승객 생존)이고 예측값이 양성(승객 생존)으로 예측되는 정도
- fprs : 실제값이 음성(승객 사망)인데 예측값이 양성(승객 생존)으로 예측되는 정도
- thresholds : 임계값
from sklearn.metrics import roc_curve
fprs, tprs, thresholds = roc_curve(y_test, pred_proba[:, 1])
print('양성 tprs 결과', tprs[:20])
print('음성 fprs 결과', fprs[:20])
print('임계 값', thresholds[:20])
# 임계값에 따라 tprs, fprs가 달라져 보임
양성 tprs 결과 [0. 0.00671141 0.20134228 0.20134228 0.36912752 0.36912752
0.39597315 0.39597315 0.42281879 0.43624161 0.45637584 0.45637584
0.4966443 0.4966443 0.51677852 0.52348993 0.52348993 0.53020134
0.53691275 0.55033557]
음성 fprs 결과 [0. 0. 0. 0.00411523 0.00411523 0.00823045
0.00823045 0.01234568 0.01234568 0.01234568 0.01234568 0.02057613
0.02057613 0.02469136 0.02469136 0.02469136 0.02880658 0.02880658
0.03292181 0.03292181]
임계 값 [1.94471902 0.94471902 0.88688535 0.87539431 0.78355664 0.77898588
0.76331131 0.76050806 0.73562007 0.73506918 0.72066805 0.70270998
0.68020194 0.67717055 0.67551737 0.67360769 0.67311293 0.67163371
0.66679513 0.66114106]
# 특이도 fprs, 민감도/ 재현율 tprs 시각화
roc = pd.DataFrame()
roc['fprs'] = fprs
roc['tprs'] = tprs
roc['thresholds'] = thresholds
roc.head()
fprs | tprs | thresholds | |
---|---|---|---|
0 | 0.000000 | 0.000000 | 1.944719 |
1 | 0.000000 | 0.006711 | 0.944719 |
2 | 0.000000 | 0.201342 | 0.886885 |
3 | 0.004115 | 0.201342 | 0.875394 |
4 | 0.004115 | 0.369128 | 0.783557 |
import seaborn as sns
sns.displot(roc.iloc[:, [0, 1]], kind='kde')
# 하단 그래프의 fprs, tprs의 겹침 영역이 넓을 수록 분류가 잘 되지 않는 그래프로 판단 해야함.
# 즉, 하단 그래프는 분류가 잘 되지 않는 그래프로 임계치 조정등으로 수정 필요
<seaborn.axisgrid.FacetGrid at 0x7fc965947220>
최적 임계값 알아보기
- argmax : 가장 큰 값을 지닌 요소의 index값 출력
optidx = np.argmax(tprs - fprs)
thresholds[optidx]
0.6331740880282526
ROC 그래프 그리기
- 분류를 잘 하는 모델일수록 커브는 1에 가깝게 표시
- fpr, tpr 그래프의 겹친 부분이 크다 - 변별력 낮음 - 곡선이 0에 가깝게 붙어서 출력
- fpr, tpr 그래프가 겹친 부분이 작다 - 변별력 높음 - 곡선이 1에 가깝게 붙어서 출력
plt.plot(fprs, tprs)
plt.plot([0,1], [0,1], 'k--')
plt.xlabel('FPRS')
plt.ylabel('TPRS')
plt.plot()
AUC
- Area Under Curve
- ROC 곡선 밑의 면적을 구한 값
- 1에 가까울 수록 좋은 수치를 의미함
- 0.9 ~ 1 : excellent
- 0.8 ~ 0.9 : good
- 0.7 ~ 0.8 : normal
from sklearn.metrics import roc_auc_score
roc_auc_score(y_test, pred)
0.7852072803601514
728x90
'PYTHON > 데이터분석' 카테고리의 다른 글
[머신러닝] 09. 의사결정 나무 (0) | 2023.01.03 |
---|---|
[머신러닝] 08. 로지스틱 회귀 (0) | 2023.01.03 |
[머신러닝] 06. 오차행렬 (0) | 2023.01.03 |
[머신러닝] 05. 데이터 전처리 (0) | 2023.01.03 |
[머신러닝] 04. 머신러닝 타이타닉 생존자 예측 (0) | 2023.01.03 |
Comments