본문 바로가기
국비 교육/머신러닝, 딥러닝

[머신러닝] 분류분석 : [다지분류]로지스틱 회귀분석

by 육츠 2023. 11. 21.
Contents 접기

임계값 Threshold : 결정함수

각 샘플의 결정함수를 사용하여 점수를 계산하고 이 점수가 임계값 보다 크면 샘플을 양성으로 판단하고
그렇지 않으면 음성으로 판단한다.

임계값의 위치에 따라 정밀도와 재현율이 달라지는 것을 알 수 있다.

다중클래스 혼동행렬

1:n  의 모양으로 혼동행렬을 만든다. 예시에서는 사과인 것과 - 사과가 아닌 것

Micro F1
마이크로 평균 F1 score 라고 하며 모델의 전체 TP, 전체 FP, 전체 FN을 고려하여 계산된다.
하나의 클래스 간에 TP끼리, FP끼리, FN 끼리 더한다.

Macro F1
각 클래스에 대해 메트릭을 계산한 다음 측정값의 가중되지 않은 평균을 말한다. (각 클래스 별의 메트릭을 산술평균(f1-score를 산술평균한 것 ))

Weighted F1
매크로F1 과 달리 측정값의 가중평균을 사용한다.(각 클래스의 가중치는 총 샘플의 수가 된다.)

 

[실습] 붓꽃 판별

패키지 로딩

import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix, precision_score, f1_score, classification_report, roc_auc_score

 

데이터 로드 및 확인

x,y = load_iris(return_X_y = True)

print(x.shape, y.shape)
unique, counts = np.unique(y, return_counts= True) 
# print(unique,counts) # 판다스 value_counts() 와 유사
print(dict(zip(unique,counts))) # 딕셔너리 형태로 변환
# 데이터의 비율이 1:1:1 로 동일하다
(150, 4) (150,)
{0: 50, 1: 50, 2: 50}

한 종속변수 당 몇 개의 케이스가 있는지 보기 위해서는 zip 형식을 취한다.
print(unique,counts) # 판다스 value_counts() 와 유사하다.  -> [0, 1, 2] [50, 50, 50]

학습, 평가데이터 분리

x_train, x_test,y_train, y_test = train_test_split(x, y, test_size= 0.3, 
                                                   random_state= 10, stratify= y)

 

모델생성

model = LogisticRegression(solver = 'lbfgs', multi_class= 'multinomial')
# model = LogisticRegression(solver = 'liblinear', multi_class= 'ovr') 

# 다지 분류에는 liblinear 는 사용할 수 없다.
# softmax 함수를 사용하겠다
model.fit(x_train,y_train)

 

모델 예측

y_hat = model.predict(x_test)
print(y_hat[:5])
# 가장 높은 값을 품종분류
[0 2 0 2 1]

predict_proba()에서 높은 확률을 가진 것을 어떻게 분류시켰는지 보여주는 것이다.

 

np.set_printoptions(precision=3, suppress= True)
prob = model.predict_proba(x_test) # 다지분류 0, 1, 2 에대한 확률값
# 높은 확률이 결과값
print(prob[:5])
[[0.968 0.032 0.   ]
 [0.    0.082 0.918]
 [0.978 0.022 0.   ]
 [0.    0.009 0.991]
 [0.013 0.811 0.176]]

 

모델 평가

print(confusion_matrix(y_test,y_hat))
print(f'정확도: {accuracy_score(y_test,y_hat):.3f}')
prob = model.predict_proba(x_test)
print(f'auc: {roc_auc_score(y_test,prob,multi_class="ovr"):.3f}')
[[15  0  0]
 [ 0 15  0]
 [ 0  0 15]]
정확도: 1.000
auc: 1.000

 

print(classification_report(y_test,y_hat))
  precision    recall  f1-score   support

           0       1.00      1.00      1.00        15
           1       1.00      1.00      1.00        15
           2       1.00      1.00      1.00        15

    accuracy                           1.00        45
   macro avg       1.00      1.00      1.00        45
weighted avg       1.00      1.00      1.00        45

 

seaborn 으로도 확인 가능하다.

mport seaborn as sns
import matplotlib.pyplot as plt
cm = confusion_matrix(y_test,y_hat)
sns.heatmap(cm, annot=True, fmt = '.3f', linewidths= 0.5)
plt.xlabel('Predict')
plt.ylabel('Actual')
plt.show()

 

하이퍼 파라메터 튜닝

모형에 들어가는 파라메터를 리스트로 전달해주면 모형을 번갈아가며 테스트 -> 최적의 파라메터를 도출해줌

from sklearn.model_selection import GridSearchCV

model = LogisticRegression() # 디폴트값으로 생성
params = {'C': [10, 5, 3, 1, 0.1, 0.01], 
          'penalty': ['l1','l2'], # 규제방식
          'solver': ['newton-cg','ldfgs','sag','saga','liblinear'],
         'multi_class': ['ovr','multinomal']}

gs = GridSearchCV(model, params, cv = 5, scoring= 'accuracy', n_jobs= -1) # n_jobs= -1 : 가능한 모든 코어
gs.fit(x,y)
print('최적 파라미터: ', gs.best_params_)
print(f'최적 정확도: {gs.best_score_:.3f}') # 교차검증을 수행했을때
최적 파라미터:  {'C': 10, 'multi_class': 'ovr', 'penalty': 'l1', 'solver': 'liblinear'}
최적 정확도: 0.980

오류메세지가 같이 검출되는데 , 가능하지 않는 파라미터들의 오류메세지를 띄워준 것이다.

 

최적 파라메터를 이용한 모델평가 및 예측

>> 정확도

best_model = gs.best_estimator_
y_hat = best_model.predict(x_test)
print(f'정확도: {accuracy_score(y_test,y_hat):.3f}')
정확도: 1.000

 

>> 정밀도

# 다중클래스 분류의 경우 average 속성에 집계방식을 지정(macro, micro, weight)
print(f'정밀도: {precision_score(y_test,y_hat, average= "micro"):.3f}')
정밀도: 1.000

 

>> AUC

# 다중클래스 auc 측정 함수에는 multi_class 속성의 값으로 ovr, ovo 값을 가짐
auc = roc_auc_score(y_test, best_model.predict_proba(x_test), multi_class= 'ovr')
print(f'AUC: {auc:.3f}')
AUC: 1.000