Search

부스팅 - LightGBM

마이크로소프트에서 개발한 고성능 그래디언트 부스팅 프레임워크다.
기존의 그래디언트 부스팅 방법론을 개선해 대규모 데이터셋에서도 빠른 학습과 예측을 제공하도록 설계되었다.
XGBoost에서 GridSearchCV를 통해서 하이퍼 파라미터를 튜닝하려고 하면 사실상 대용량의 데이터의 경우 많은 CPU코어를 가진 시스템에서 높은 병렬도로 학습을 진행해야 한다.
반면, LightGBM의 가장 큰 장점은 XGBoost보다 학습에 걸리는 시간이 훨씬 적다는 점이다. 또한 메모리 사용량도 상대적으로 적다.
다행이도 LightGBM과 XGBoost의 예측 성능은 별다른 차이가 없다.
한 가지 단점은 적은 데이터 세트에 LightGBM을 적용할 경우 과적합이 발생하기 쉽다는 점이다. 여기서 적은 데이터라고 함은 대략 10000건 이하의 데이터 세트 라고 생각하면 된다.
LightGBM은 일반 GBM 계열의 트리 분할 방법과 다르게 리프 중심 트리 분할 방식을 사용한다.
일반 GBM계열의 트리 분할 방법균형 트리 분할(Level Wise) 방식이다. 사실상 이 구조가 더 과적합에 강하다고 알려져 있다.
LightGBM의 리프 중심 트리 분할 방식은 최대 손실 값을 가지는 리프 노드를 지속적으로 분할하면서 트리의 깊이가 깊어지고 비대칭적인 규칙 트리가 생성된다. 하지만, 학습을 반복할수록 결국은 균형 트리 분할 방식보다 예측 오류 손실을 최소화 할 수 있다는 것이 구현 사상이다.
LGBM 특징 및 인기요인
데이터가 적을 때(10000개 이하) 과적합 발생 가능성이 높다.
고속처리 및 효율성이 높다
메모리 효율성을 통한 최적화
결측치 자동 처리
범주형 변수 자동 처리
자료형을 category로 바꿔주면 알아서 처리한다.
트리 기반 모델 → 스케일링 불필요
높은 정확도
xgboost 모델 비교
xgboost는 병렬 처리와 과적합 방지 기능에서 강력한 성능을 발휘한다.
둘다 그래디언트 부스팅 기반한 라이브러리
둘다 대규모 데이터셋에서 좋은 성능, 병렬 처리 → 속도가 빠름
xgboost 는 균형 잡힌 트리로 과적합 방지 lightgbm 은 비대칭 트리를 빠르게 성장
xgboost는 병렬 처리를 통해 트리 구축하며 학습 속도를 향상시키는데, 이 과정에서 모든 특성을 스캔해야하기 때문에 매우 큰 데이터셋의 경우, 계산 비용과 시간이 많이 소요될 수 있다.
lightgbm은 히스토그램 기반 분할 방식을 이용해서 위의 계산 비용을 대폭 줄임. 데이터의 모든 연속형 변수를 미리 정의된 구간으로 변환하고, 이 정보를 바탕으로 트리의 분할을 결정한다. → 시간과 메모리 비용을 모두 줄임
xgboost는 범주형 인코딩 처리가 필요하다. 한편, lightgbm은 category로 자료형만 바꿔주면 인코딩이 필요없다.
파이썬에서 하는 LightGBM의 패키지명은 ‘lightgbm’이다. 물론, 처음에 LightGBM도 초기에는 파이썬 래퍼용 LightGBM만 개발됐었다. 이후 사이킷런과의 호환성을 지원하기 위해 사이킷런 래퍼 LightGBM이 추가로 개발 된 것이다. lightgbm 패키지 내에 이 두개의 래퍼 모듈을 모두 가지고 있다.
level wise 방식
leaf wise 방식

LightGBM 활용 사례 및 확인 문제

지도 학습 모델로, 정형 데이터를 분석할 때 사용된다.
예시 1. 악성코드 탐지
사이버 보안 분야에 사용된다.
정적 분석을 통해 파일의 데이터를 분석하고, 이를 통해 악성 여부분류한다.
예시 2. 물류 입고 프로세스 최적화
물류 최적화 분야에 사용된다.
물류 데이터를 분석해 차량의 적절한 수를 예측함으로써, 필요한 물류 자원의 효율적 사용을 가능하게 한다. 예시 3. 감귤 착과량 예측 AI 경진대회 및 청경채 성장 예측 AI 경진대회
농업 기술 분야에서도 활용된다.
단독 모델로 사용했을 때 3위, 2위를 차지했으며 다른 앙상블 모델과 비슷한 성능을 보여주었다.
사이킷런 래퍼 LightGBM 클래스는 분류를 위한 LGBMClassifier 클래스와 회귀를 위한 LGBMRegressor 클래스가 있다.
이제, 사이킷런 LightGBM클래스만 사용하겠다.
먼저, 아나콘다를 이용해서 LightGBM을 쉽게 설치할 수 있는데,
conda install -c conda-forge lightgbm이 failed 라고 나오면 conda install -c conda-forge/label/cf201901 lightgbm로 바꿔서 해보자.

실전 데이터 적용

train = pd.read_csv('신용_train.csv') print(train.isnull().sum()) # 컬럼별 결측치 개수 확인 train.head(2)
Python
복사
index 0 gender 0 car 0 reality 0 child_num 0 income_total 0 income_type 0 edu_type 0 family_type 0 house_type 0 days_birth 0 days_employed 0 flag_mobil 0 work_phone 0 phone 0 email 0 job_type 8171 family_size 0 begin_month 0 credit 0 dtype: int64
Plain Text
복사
# 학습 전 범주형 데이터 자료형 category 로 변환 target = train['credit'] independent = train.drop(['index', 'credit'], axis = 1) object_cols = [col for col in independent.columns if independent[col].dtype == "object"] independent[object_cols] = independent[object_cols].astype('category')
Python
복사
# 학습, 검증 데이터 분리 from sklearn.model_selection import train_test_split X_train, X_valid, y_train, y_valid = train_test_split(independent, target, test_size=0.2, random_state=42) from lightgbm import LGBMClassifier # LightGBM 모델 정의 및 학습 base_lgbm = LGBMClassifier(random_state = 42) base_lgbm.fit(X_train, y_train) # 검증점수 확인 print("LGBM 모델 정확도:", base_lgbm.score(X_valid, y_valid))
Python
복사
LGBM 모델 정확도: 0.6993575207860923
# 세부 설정 - 하이퍼파라미터 # n_estimators = 300 (분류기 개수) # max_depth = 6 # num_leaves # early_stopping : 조기 종료 # log_evaluation : 학습 과정에서 지정된 주기마다 평가지표를 출력, eval_metrics 매개변수를 설정해 평가지표 조정 가능 from lightgbm.callback import early_stopping, log_evaluation tuning_lgbm = LGBMClassifier(n_estimators=300, max_depth=6, random_state=42) # 조기 종료와 학습 로그 출력 콜백 정의 early_stop = early_stopping(stopping_rounds=5) log_eval = log_evaluation(period=20) # 모델 학습 tuning_lgbm( X_train, y_train, eval_set = [(X_valid, y_valid)], eval_metrics='multi_logloss', callbacks=[early_stop,log_eval] ) # 정확도 출력 print('하이퍼파라미터가 튜닝된 LGBM 모델 정확도: ', tuning_lgbm.score(X_valid, y_valid))
Python
복사
하이퍼파라미터가 튜닝된 LGBM 모델 정확도: 0.7018140589569161

학습에 따른 검증 데이터의 로그 손실 추이

평가지표의 변화가 멈추거나, 특정 지점에서 성능이 개선되지 않는다면 과적합이 발생했거나 학습이 더 이상 효과적이지 않음을 의미할 가능성이 높다. 이런 경우, 모델 학습 과정을 모니터링하면서 적절한 하이퍼파라미터가 얼마인지 여부를 결정해야 한다.
로그 손실 추이 시각화
로그 손실은 분류 모델의 평가지표이며 모델이 잘 예측할수록 낮은 값을 갖는다.
앞서 모델을 학습할 때 eval_metric을 ‘multi_logloss’ 로 설정했기 때문에 로그 손실 값을 시각화해서 성능을 평가할 수 있다.
LightGBM 의 plot_metric 메소드
모델의 evals_result_ 속성
import lightgbm as lgb import matplotlib.pyplot as plt # 모델 학습 중 사용된 metric과 동일한 'multi_logloss'를 사용 loss_plot = lgb.plot_metric(tuning_lgbm.evals_result_, metric='multi_logloss') plt.show()
Python
복사
반복 횟수가 증가함에 따라 multi_logloss의 값이 줄어든다.
모델의 피처 중요도 시각화
피처 중요도가 항상 높은 예측 성능을 보장하지는 않는다.
때로는 피처 중요도가 높은 피처가 오히려 과적합을 일으키는 원인이 될 수 있다.
따라서 피처 중요도를 해석할 때는 전체 모델 성능과 함께 고려해야 한다.
LightGBM 모델의 plot_ importance 함수
모델 학습 중 각 피처의 중요도를 바 차트로 시각화하는 데 사용된다. 이 함수는 tuning_lgbm.booster_ 에서 제공하는 정보를 기반으로 작동한다. booster_ 속성은 LightGBM 모델의 부스터 객체를 포함하고 있으며 이는 모델이 생성한 결정 트리들의 집합이다. 각 피처들의 중요도는 이 결정 트리들 내에서 해당 피처가 얼마나 자주 사용되었는지를 통해 계산된다.
모델의 booster_ 속성, max_num_features 옵션
importance_plot = lgb.plot_importance(tuning_lgbm.booster_, max_num_features=10) plt.show()
Python
복사

LightGBM 예측값 확인

pred = tuning_lgbm.predict(X_valid) logloss_pred = tuning_lgbm.predict_proba(X_valid) print(pred) print('-'*40) print(logloss_pred)
Python
복사
[2 2 2 ... 2 2 2] ---------------------------------------- [[0.03495136 0.26626222 0.69878642] [0.03300809 0.27927178 0.68772013] [0.04629304 0.14970047 0.80400649] ... [0.08706734 0.12037167 0.79256099] [0.16755148 0.25153999 0.58090853] [0.05666229 0.13668796 0.80664975]]
Plain Text
복사

LightGBM 하이퍼 파라미터

LightGBM 하이퍼 파라미터는 리프 중심 트리 분할이라고 했기 때문에 이에 걸맞는 하이퍼 파라미터 설정이 필요하다.
< 일반 파라미터 >
booster
‘gbdt’ / ‘dart’ / ‘rf’ : 부스팅이 아닌 랜덤포레스트 모형(배깅)을 만드는 방법/ ‘goss’ : SGD를 더 빠르고 더 잘 수렴시키기 위해 서브샘플링을 이용하는 방법
그냥 ‘gbdt’(default)를 사용하거나 ‘dart’는 과적합을 제어하기 좋으니 시도해보기 좋다.
verbosity [default=1] : 0(생략), 1(경고), 2(알려줌), 3(debug)
< 부스터 파라미터 >
learning_rate [default=0.1] : 0~1 사이의 값을 지니는 학습률. 사이킷런의 learning rate와 같은 파라미터다.
max_depth [default=-1] : 트리 기반 알고리즘의 max_depth와 같다. 0보다 작은 값을 지정하면 깊이에 제한이 없는것. LightGBM은 Leaf Wise 기반이므로 깊이가 상대적으로 더 깊다.
num_iterations [default=100] : 반복 수행하려는 트리의 개수. 크게 지정할수록 예측 성능이 높아지기는하나 과적합의 위험이 있다. n_estimators와 같은 파라미터다. 따라서 사이킷런 호환 클래스에서는 n_estimators로 이름이 변경된다는 점 참고하자.
min_data_in_leaf [default=20] : 결정 트리의 min_samples_leaf 와 같은 파라미터다. 하지만 사이킷런 래퍼 LightGBMClassifier에서는 min_child_samples 파라미터로 이름이 바뀐다. 과적합을 제어하기 위한 파라미터다.
num_leaves [default=31] : 하나의 트리가 가질 수 있는 최대 리프 개수. 작을수록 제어 커짐.
max_depth 별로 여러 개의 num_leaves 조합을 만들어 cross-validation 성능이 가장 좋은 조합을 찾아보는 것도 좋다.
bagging_fraction / subsample [default=1] : 각 이터레이션에 사용되는 행의 비율. 과적합 제어에 유용. [ row sampling ]
booster가 ‘goss’ 일때는 subsample 허용 불가다.
column sampling 과 함께 튜닝하는 것이 좋다.
feature_fraction / colsample_bytree [default=1] : 각 이터레이션에서 사용되는 칼럼의 비율. 보통 0.7 정도의 값을 사용. 마찬가지로 과적합을 제어하기 위해 사용. 세세하게 튜닝할 필요는 없다. [ column sampling ]
lambda_l2 [default=0.0] : L2 regulation 제어를 위한 값. 피처 개수가 많을 경우 적용 검토. 값이 클수록 과적합 감소 효과있음. 사이킷런에서는 reg_lambda로 변경
lambda_l1 [default=0.0] : L1 regulation 제어를 위한 값. 사이킷런에서는 reg_alpha로 변경
[Positive Binary Scaling]
이진 분류 문제를 풀 때 positive label에 가중치를 부여하는 것. 잘 모르겠다면 default로 두는 것이 좋다.
→ xgboost 와 lightgbm 모두 동일 파라미터
scale_pos_weight [ default = 1 ]
반드시 positive label 의 수가 더 적을 경우 사용한다. 경험적으로는 scale_pos_weight를 조절하는 것보다는 디폴트로 두고, 언더샘플링 같이 데이터셋에 대한 샘플링 기법을 사용하는 것이 더 효과적이라고 한다.
Learning Task 파라미터
objective : 최솟값을 가져야할 손실함수 정의

하이퍼 파라미터 튜닝 방안

num_leaves 의 개수를 중심으로 min_child_samples(min_data_in_leaf), max_depth를 함께 조정해가면서 모델의 복잡도를 줄이는 것이 기본 튜닝 방안이다.
1.
num_leaves는 개별 트리가 가질 수 있는 최대 리프의 개수다. 커질수록 예측 정확도는 높아지지만 반대로 모델의 복잡도는 커져서 과적합될 위험이 커진다.
2.
min_data_in_leaf 또는 min_child_samples는 과적합을 제어하기 위한 중요한 파라미터다. 큰 값으로 설정하면 트리가 깊어지는 것을 방지한다.
3.
max_depth는 딱 명시적으로 트리의 깊이를 조정한다. 과적합을 개선하는 데 사용한다.

파이썬 래퍼 LightGBM과 사이킷런 래퍼 XGBoost, LightGBM 하이퍼 파라미터 비교

LightGBM은 사이킷런과 호환하기 위해 분류를 위한 LGBMClassifier과 회귀를 위한 LGBMRegressor 클래스를 래퍼 클래스로 생성했다.
사이킷런의 XGBoost 클래스와 LightGBM클래스는 많은 하이퍼 파라미터가 똑같다.

LightGBM 적용 - 위스콘신 유방암 예측

먼저, 파이썬 패키지인 lightgbm에서 LGBMClassifier를 임포트(사이킷런 래퍼)해 사용하겠다.마찬가지로 fit()에서 조기중단 기능이 가능하다.
# 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 dataset = load_breast_cancer() ftr = dataset.data target = dataset.target # 전체 데이터 중 80%는 학습용 데이터, 20%는 테스트용 데이터 추출 X_train,X_test,y_train,y_test = train_test_split(ftr,target,test_size=0.2,random_state=156) # 앞서 XGBoost와 동일하게 n_estimators는 400으로 설정 lgbm_wrapper = LGBMClassifier(n_estimators=400) # LightGBM도 XGBoost와 동일하게 조기 중단 수행 가능. evals = [(X_test,y_test)] lgbm_wrapper.fit(X_train,y_train, early_stopping_rounds=100, eval_metric="logloss",eval_set=evals, verbose=True) preds = lgbm_wrapper.predict(X_test) pred_proba = lgbm_wrapper.predict_proba(X_test)[:,1]
Python
복사
이제, 학습된 LightGBM모델을 기반으로 예측 성능을 평가해보자. get_clf_eval() 함수를 이용하겠다.
get_clf_eval(y_test,preds,pred_proba) ''' 오차 행렬 [[33 4] [ 1 76]] 정확도:0.9561, 정밀도:0.9500, 재현율:0.9870, f1 스코어:0.9682, AUC : 0.9905 '''
Python
복사
파이썬 패키지인 lightgbm은 XGBoost 파이썬 패키지인 xgboost와 동일하게 피처 중요도를 시각화할 수 있는 API를 제공한다. 이름도 plot_importance()다. 물론, 사이킷런 래퍼 클래스를 입력해도 시각화를 제공한다.
# plot_importance() 를 이용해 피처 중요도 시각화 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)
Python
복사