Python에서 로지스틱 회귀(Logistic Regression) 분석을 하는 방법을 알아보자.
※ 본 내용에서 사용하는 model_classification_machine_failure.csv 파일은 별도로 다운로드 받아야 한다.
※ model_classification_machine_failure.csv 다운받기 [클릭]
이론
로지스틱 회귀(Logistic Regression)는 이항 로지스틱 회귀, 순서 로지스틱 회귀, 다항 로지스틱 회귀 등 다양한 종류가 있지만, 여기서는 이항 로지스틱 회귀(Binary Logistic Regression)에 대해서 다룬다. 이항 로지스틱 회귀는 종속변수가 이항 분포를 따르는 경우에 사용하는 회귀분석 기법이다. 이항 분포는 성공과 실패 두 가지 결과만을 가지는 n번의 베르누이 시행(Bernoulli trial) 과 관련된 확률분포로, 이항 로지스틱 회귀는 이러한 이항 분포를 따르는 종속변수를 예측하는 모델을 만드는 것이다. 하지만 여기는 통계모델인 일반화 선형 모형(GLM, Generalized Linear Model)을 사용하여 이항 로지스틱 회귀를 구현하는 방법을 다루지 않고, sklearn 라이브러리를 사용하여 이항 로지스틱 회귀를 구현하는 방법을 다룬다.
이항 로지스틱 회귀 모델을 구현하기 위해서는 sklearn 라이브러리의 LogisticRegression()
클래스를 사용한다. 해당 클래스의 공식 문서에서 안내하는 파라미터는 다음과 같다.
penalty : 유형 - str, 기본값 - “l2”
- 설명: 규제 유형을 지정(L1, L2, Elastic Net, None)
- 입력값 범위: {“l1”, “l2”, “elasticnet”, “none”}
dual : 유형 - bool, 기본값 - False
- 설명: 쌍대(Dual) 또는 원시(Primal) 최적화 문제 해결법 지정
- 입력값 범위: {True, False}
tol : 유형 - float, 기본값 - 1e-4
- 설명: 최적화 알고리즘의 수렴 조건 지정
- 입력값 범위: float
C : 유형 - float, 기본값 - 1.0
- 설명: 규제 강도를 지정(값이 작을수록 강한 규제)
- 입력값 범위: float
fit_intercept : 유형 - bool, 기본값 - True
- 설명: 모델 학습에 상수항을 포함할지 여부를 지정(
False
설정시 상수항 미포함)- 입력값 범위: {True, False}
intercept_scaling : 유형 - float, 기본값 - 1
- 설명: 상수항의 스케일링 비율 지정하며 “solver”가 “liblinear” 이면서 “fit_intercept”가
True
일 때만 사용- 입력값 범위: float
class_weight : 유형 - dict or list of dict or “balanced”, 기본값 - None
- 설명: 범주 가중치 지정(범주 불균형 문제 해결을 위한 가중치 지정)
- 입력값 범위: {dict, list of dict, “balanced”, None}
random_state : 유형 - int or RandomState instance or None, 기본값 - None
- 설명: 난수 seed 설정
- 입력값 범위: {int, RandomState instance, None}
solver : 유형 - str, 기본값 - “lbfgs”
- 설명: 최적화 알고리즘 지정
- 입력값 범위: {“lbfgs”, “liblinear”, “newton-cg”, “newton-cholesky”, “sag”, “saga”}
max_iter : 유형 - int, 기본값 - 100
- 설명: 최적화 알고리즘의 최대 반복 횟수 지정
- 입력값 범위: int
multi_class : 유형 - str, 기본값 - “auto”
- 설명: 다중 분류 문제 해결 방법 지정
- 입력값 범위: {“auto”, “ovr”, “multinomial”}
verbose : 유형 - int, 기본값 - 0
- 설명: 최적화 알고리즘의 출력 메시지 수준 지정
- 입력값 범위: int
warm_start : 유형 - bool, 기본값 - False
- 설명: 이전 모델 학습 결과를 초기화하지 않고 추가 학습을 지정(solver가 “liblinear”인 경우 소용 없음)
- 입력값 범위: {True, False}
n_jobs : 유형 - int, 기본값 - None
- 설명: 모델 학습에 사용할 CPU 코어 개수를 지정(
None
설정시 기본적으로 1개 코어 사용)- 입력값 범위: {None, int}
l1_ratio : 유형 - float, 기본값 - None
- 설명: Elastic-Net 규제의 비율 지정
- 입력값 범위: $0 <= l1_ratio <= 1$
예제 코드
먼저 다음과 같이 라이브러리와 데이터를 준비하고 사용하는 데이터와 관련된 전처리 코드는 [Py) 전처리 - ML 분류모델용 - 01] 게시글을 참고하자.
※ model_classification_machine_failure.csv 다운받기 [클릭]
1 | import pandas as pd |
id | is_failure | type_H | type_L | type_M | temp_air | temp_process | speed | torque | tool_wear | Xgrp | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 55100 | 0 | 0.0 | 1.0 | 0.0 | 0.399154 | 1.352290 | -0.877336 | 0.926149 | 1.084815 | train |
1 | 49876 | 0 | 0.0 | 1.0 | 0.0 | 0.001026 | -0.266219 | -0.482743 | 0.596147 | -0.889909 | train |
“Xgrp” 변수을 기준으로 학습과 평가 데이터세트로 나눈 후 학습에 불필요한 “id”, “Xgrp” 변수를 제거한다.
1 | df_train = df_machine.loc[df_machine["Xgrp"] == "train", ] |
is_failure | type_H | type_L | type_M | temp_air | temp_process | speed | torque | tool_wear | |
---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0.0 | 1.0 | 0.0 | 0.399154 | 1.352290 | -0.877336 | 0.926149 | 1.084815 |
1 | 0 | 0.0 | 1.0 | 0.0 | 0.001026 | -0.266219 | -0.482743 | 0.596147 | -0.889909 |
LogisticRegression()
클래스를 사용하여 모델을 학습한다. 여기서 필요시 각 파라미터를 조정하여 학습을 진행할 수 있다.
1 | model_r = LogisticRegression(random_state = 123) |
보통 분류모델의 예측값을 산출할 때는 predict()
메서드를 사용하지만, 이항 로지스틱 회귀 모델의 경우 predict_proba()
메서드를 사용하여 예측 확률도 산출하여 모델 평가에 활용할 수 있다.
1 | pred_proba = model_r.predict_proba(df_test.drop(columns = "is_failure")) |
“pred_proba” 객체의 경우 첫 번째 열의 숫자가 종속변수 범주가 “0”이될 확률이고 두 번째 열의 숫자가 종속변수 범주가 “1”이될 확률이다. “pred” 객체의 값은 “pred_proba” 객체의 결과를 기반으로 분류(threshold = 0.5 기준)한 예측값과 같다.
1 | pd.crosstab((pred_proba[:, 1] > 0.5) + 0, pred, |
pred | 0 | 1 |
---|---|---|
pred_proba | ||
0 | 2958 | 0 |
1 | 0 | 37 |
이제 모델의 성능을 평가해보자. 여기서는 정확도(Accuracy), F1-score, AUC를 사용하여 모델의 성능을 평가한다. 그리고 AUC를 산출할 때 roc_auc_score()
함수에 분류모델의 예측값이 아닌 예측 확률을 입력해야 한다. 즉, 앞에서 생성한 “pred_proba” 객체를 사용하여 AUC를 산출한다.
1 | accuracy_score(y_true = df_test["is_failure"], y_pred = pred) |