[Python 머신러닝] 04-7 LightGBM
분류
LightGBM
LightGBM 개요
XGBoost 대비 장점
- 더 빠른 학습과 예측 수행 시간
- 더 작은 메모리 사용량
- 카테고리형 피처의 자동 변환과 최적 분할 (원-핫 인코딩 등을 사용하지 않고도 카테고리형 피처를 최적으로 변환하고 이에 따른 노드 분할 수행)
LightGBM 트리 분할 방식 - 리프 중심
LightGBM은 일반 GBM 계열의 트리 분할 방법과 다르게 리프 중심 트리 분할(Leaf Wise) 방식을 사용한다.
LightGBM 파이썬 구현
- C/C++ Native Module
- 원래는 Windows 기반의 C/C++로 작성
- 현재는 Linux 등 타 기반 OS 지원
- 파이썬 Wrapper
- C/C++ 모듈을 호출하는 파이썬 Wrapper
- 사이킷런 Wrapper
- 사이킷런 프레임과 통함 될 수 있는 파이썬 Wrapper Class 지원
- LGBMClassifier
- LGBMRegressor
- 학습과 예측을 다른 사이킷런 API와 동일하게 fit( )과 predict( )로 수행
- GridSearchCV와 같은 다른 사이킷런 모듈과 같이 사용 가능
- 사이킷런 프레임과 통함 될 수 있는 파이썬 Wrapper Class 지원
LightGBM 설치
아나콘다 프롬프트를 관리자 권한으로 실행한 후 conda install -c conda-forge lightgbm 명령어를 입력한다.
LightGBM 하이퍼 파라미터
| 유형 | 파이썬 래퍼 LightGBM | 사이킷런 래퍼 LightGBM | |
|---|---|---|---|
| num_iterations | n_estimators | 약한 학습기의 개수 (반복 수행 횟수) | |
| learning_rate | learning_rate | 학습률 (learning rate) 0에서 1 사이의 값을 지정하며 부스팅 스텝을 반복적으로 수행할 때 업데이트되는 학습률 값 |
|
| 파라미터명 | max_depth | max_depth | 결정트리의 max_depth와 동일 트리의 최대 깊이 |
| min_data_in_leaf | min_child_samples | 리프 노드가 될 수 있는 최소 데이터 건수 (Sample 수) | |
| bagging_fraction | subsample | 트리가 커져서 과적합되는 것을 제어하기 위해 데이터를 샘플링하는 비율 지정 sub_sample=0.5로 지정하면 전체 데이터의 절반을 트리를 생성하는 데 사용 |
|
| feature_fraction | colsample_bytree | GBM의 max_features와 유사 트리 생성에 필요한 피처(칼럼)를 임의로 샘플링 하는 데 사용 매우 많은 피처가 있는 경우 과적합을 조정하는 데 적용 |
lightGBM 사이킷런 래퍼는 XGBoost 사이킷런 래퍼에 해당 하이퍼 파라미터가 있으면 이를 그대로 사용하고 그렇지 않으면 파이썬 래퍼 LightGBM 하이퍼 파라미터 사용
하이퍼 파라미터 튜닝 방안
| 유형 | 파이썬 래퍼 LightGBM | 사이킷런 래퍼 LightGBM | |
|---|---|---|---|
| lambda_l2 | reg_lambda | L2 규제(Regularization) 적용 값 기본값은 1 값이 클수록 규제 값이 커짐 과적합 제어 |
|
| lambda_l1 | reg_alpha | L1 규제(Regularization) 적용 값 기본값은 0 값이 클수록 규제 값이 커짐 과적합 제어 |
|
| 파라미터명 | early_stopping_round | early_stopping_rounds | 학습 조기 종료를 위한 early stopping interval 값 |
| num_leaves | num_leaves | 최대 리프 노드 개수 | |
| min_sum_hessian_in_leaf | min_child_weight | 결정트리의 min_child_leaf와 유사 과적합 조절용 |
num_leaves의 개수를 중심으로 min_child_samples(min_data_in_leaf), max_depth를 함께 조정하면서 모델의 복잡도를 줄이는 것이 기본 튜닝 방안
파이썬 래퍼 LightGBM과 사이킷런 래퍼 XGBoost, LightGBM 하이퍼 파라미터 비교
| 유형 | 파이썬 래퍼 LightGBM | 사이킷런 래퍼 LightGBM | 사이킷런 래퍼 XGBoost |
|---|---|---|---|
| num_iterations | n_estimators | n_estimators | |
| learning_rate | learning_rate | learning_rate | |
| 파 | max_depth | max_depth | max_depth |
| 라 | min_data_in_leaf | min_child_samples | N/A |
| 미 | bagging_fraction | subsample | subsample |
| 터 | feature_fraction | colsample_bytree | colsample_bytree |
| 명 | lambda_l2 | reg_lambda | reg_lambda |
| lambda_l1 | reg_alpha | reg_alpha | |
| early_stopping_round | early_stopping_rounds | early_stopping_rounds | |
| num_leaves | num_leaves | N/A | |
| min_sum_hessian_in_leaf | min_child_weight | min_child_weight |
LightGBM 적용 – 위스콘신 유방암 예측
<실습>실습>
import lightgbm
print(lightgbm.__version__)
3.3.2
# LightGBM의 파이썬 패키지인 lightgbm에서 LGBMClassifier 임포트
from lightgbm import LGBMClassifier
import pandas as pd
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
import warnings
warnings.filterwarnings('ignore')
dataset = load_breast_cancer()
cancer_df = pd.DataFrame(data=dataset.data, columns=dataset.feature_names)
cancer_df['target']= dataset.target
cancer_df.head()
| mean radius | mean texture | mean perimeter | mean area | mean smoothness | mean compactness | mean concavity | mean concave points | mean symmetry | mean fractal dimension | ... | worst texture | worst perimeter | worst area | worst smoothness | worst compactness | worst concavity | worst concave points | worst symmetry | worst fractal dimension | target | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 17.99 | 10.38 | 122.80 | 1001.0 | 0.11840 | 0.27760 | 0.3001 | 0.14710 | 0.2419 | 0.07871 | ... | 17.33 | 184.60 | 2019.0 | 0.1622 | 0.6656 | 0.7119 | 0.2654 | 0.4601 | 0.11890 | 0 |
| 1 | 20.57 | 17.77 | 132.90 | 1326.0 | 0.08474 | 0.07864 | 0.0869 | 0.07017 | 0.1812 | 0.05667 | ... | 23.41 | 158.80 | 1956.0 | 0.1238 | 0.1866 | 0.2416 | 0.1860 | 0.2750 | 0.08902 | 0 |
| 2 | 19.69 | 21.25 | 130.00 | 1203.0 | 0.10960 | 0.15990 | 0.1974 | 0.12790 | 0.2069 | 0.05999 | ... | 25.53 | 152.50 | 1709.0 | 0.1444 | 0.4245 | 0.4504 | 0.2430 | 0.3613 | 0.08758 | 0 |
| 3 | 11.42 | 20.38 | 77.58 | 386.1 | 0.14250 | 0.28390 | 0.2414 | 0.10520 | 0.2597 | 0.09744 | ... | 26.50 | 98.87 | 567.7 | 0.2098 | 0.8663 | 0.6869 | 0.2575 | 0.6638 | 0.17300 | 0 |
| 4 | 20.29 | 14.34 | 135.10 | 1297.0 | 0.10030 | 0.13280 | 0.1980 | 0.10430 | 0.1809 | 0.05883 | ... | 16.67 | 152.20 | 1575.0 | 0.1374 | 0.2050 | 0.4000 | 0.1625 | 0.2364 | 0.07678 | 0 |
5 rows × 31 columns
X_features = cancer_df.iloc[:, :-1]
y_label = cancer_df.iloc[:, -1]
# 전체 데이터 중 80%는 학습용 데이터, 20%는 테스트용 데이터 추출
X_train, X_test, y_train, y_test=train_test_split(X_features, y_label,
test_size=0.2, random_state=156 )
# 위에서 만든 X_train, y_train을 다시 쪼개서 90%는 학습과 10%는 검증용 데이터로 분리
X_tr, X_val, y_tr, y_val= train_test_split(X_train, y_train,
test_size=0.1, random_state=156 )
# 앞서 XGBoost와 동일하게 n_estimators는 400 설정.
lgbm_wrapper = LGBMClassifier(n_estimators=400, learning_rate=0.05)
# LightGBM도 XGBoost와 동일하게 조기 중단 수행 가능.
evals = [(X_tr, y_tr), (X_val, y_val)]
lgbm_wrapper.fit(X_tr, y_tr, early_stopping_rounds=50, eval_metric="logloss",
eval_set=evals, verbose=True)
preds = lgbm_wrapper.predict(X_test)
pred_proba = lgbm_wrapper.predict_proba(X_test)[:, 1]
[1] training's binary_logloss: 0.625671 valid_1's
.
. (생략)
.
[61] training's binary_logloss: 0.0532381 valid_1's binary_logloss: 0.260236
.
. (생략)
.
[111] training's binary_logloss: 0.00850714 valid_1's binary_logloss: 0.280894
from sklearn.metrics import confusion_matrix, accuracy_score
from sklearn.metrics import precision_score, recall_score
from sklearn.metrics import f1_score, roc_auc_score
def get_clf_eval(y_test, pred=None, pred_proba=None):
confusion = confusion_matrix( y_test, pred)
accuracy = accuracy_score(y_test , pred)
precision = precision_score(y_test , pred)
recall = recall_score(y_test , pred)
f1 = f1_score(y_test,pred)
# ROC-AUC 추가
roc_auc = roc_auc_score(y_test, pred_proba)
print('오차 행렬')
print(confusion)
# ROC-AUC print 추가
print('정확도: {0:.4f}, 정밀도: {1:.4f}, 재현율: {2:.4f},\
F1: {3:.4f}, AUC:{4:.4f}'.format(accuracy, precision, recall, f1, roc_auc))
get_clf_eval(y_test, preds, pred_proba)
오차 행렬
[[34 3]
[ 2 75]]
정확도: 0.9561, 정밀도: 0.9615, 재현율: 0.9740, F1: 0.9677, AUC:0.9877
# plot_importance( )를 이용하여 feature 중요도 시각화
from lightgbm import plot_importance
import matplotlib.pyplot as plt
%matplotlib inline
fig, ax = plt.subplots(figsize=(10, 12))
plot_importance(lgbm_wrapper, ax=ax)
plt.show()