● XGBoost

  • 트리 기반의 앙상블 기법
  • 분류에 있어서 다른 알고리즘보다 좋은 예측 성능을 보여줌
  • XGBoost는 GBM 기반이지만, GBM의 단점인 느린 수행 시간과 과적합 규제 부재 등의 문제를 해결
  • 병렬 CPU 환경에서 빠르게 학습 가능

 

  • 필요 라이브러리
from sklearn.datasets import load_iris, load_breast_cancer, load_wine, load_diabetes
from sklearn.model_selection import train_test_split, cross_validate
from sklearn.metrics import accuracy_score, precision_score, recall_score

import xgboost as xgb
from xgboost import XGBClassifier, XGBRegressor
from xgboost import plot_importance, plot_tree

import graphviz
import matplotlib.pyplot as plt

 

1. 파이썬 기반 XGBoost

  - 유방암 데이터로 연습

cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, test_size = 0.2, random_state = 42)

# XGBoost는 XGBoost만의 데이터 형식인 DMatrix 형식을 사용하므로 다음과 같이 train과 test 데이터를 변환
dtrain = xgb.DMatrix(data = X_train, label = y_train)
dtest = xgb.DMatrix(data = X_test, label = y_test)

# 파라미터
params = {
    'max_depth': 3,
    'eta': 0.1,
    'objective': 'binary:logistic',
    'eval_metric': 'logloss',
    'early_stopping': 100
}
num_rounds = 400

# 모델 생성
evals = [(dtrain, 'train'), (dtest, 'eval')]
xgb_model = xgb.train(params = params, dtrain = dtrain, num_boost_round = num_rounds, early_stopping_rounds = 100, evals = evals)

 

  - xgb_model 생성 결과, logloss가 더 이상 감소되지 않을 때까지 모델 최적화

  - 계속 감소한다면 사전에 정해둔 round 횟수(num_rounds = 400)만큼만 진행한 뒤 모델 생성 종료

  - 가장 마지막 모델로 생성

 

  - train 데이터로 생성한 모델에 test 데이터를 넣어 예측값 출력(상위 10개만)

import numpy as np

predicts = xgb_model.predict(dtest)
print(np.round(predicts[:10], 3))

 

  - 정확도, 정밀도, 재현율 출력

# 데이터 생성 결과를 이원화(0 또는 1로)하여 2*2 테이블 상에서 정확도, 정밀도, 재현율을 계산할 수 있도록 변경
preds = [1 if x > 0.5 else 0 for x in predicts]
print(preds[:10])

print("정확도: {}".format(accuracy_score(y_test, preds)))
print("정밀도: {}".format(precision_score(y_test, preds)))
print("재현율: {}".format(recall_score(y_test, preds)))

# 출력 결과
정확도: 0.9736842105263158
정밀도: 0.9722222222222222
재현율: 0.9859154929577465

 

  - 변수들의 중요도를 알아보기 위한 그래프 출력

fig, ax = plt.subplots(figsize = (10, 12))
plot_importance(xgb_model, ax = ax)

 

  - xgb 모델을 트리 형식으로 표현한 그래프 출력

dot_data = xgb.to_graphviz(xgb_model)
dot_data

 

2. XGBClassifier

  - 붓꽃 데이터

iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size = 0.2, random_state = 42)

  - XGBClassifier 모델 생성

xgbc = XGBClassifier(n_estimators = 400, learning_rate = 0.1, max_depth = 3)
xgbc.fit(X_train, y_train)
preds = xgbc.predict(X_test)
preds_proba = xgbc.predict_proba(X_test)[:, 1]

cross_val = cross_validate(
    estimator = xgbc,
    X = iris.data, y = iris.target,
    cv = 5
)
print('avg fit time: {} (+/- {})'.format(cross_val['fit_time'].mean(), cross_val['fit_time'].std()))
print('avg score time: {} (+/- {})'.format(cross_val['score_time'].mean(), cross_val['score_time'].std()))
print('avg test score: {} (+/- {})'.format(cross_val['test_score'].mean(), cross_val['test_score'].std()))

# 출력 결과
avg fit time: 0.38040671348571775 (+/- 0.12548339326469174)
avg score time: 0.0038000106811523437 (+/- 0.001165665213187403)
avg test score: 0.96 (+/- 0.024944382578492935)

  - 모델에서 데이터의 각 변수 중요도 출력

fig, ax = plt.subplots(figsize = (10, 12))
plot_importance(xgbc, ax = ax)

  - xgb 모델을 트리 형식으로 출력

dot_data = xgb.to_graphviz(xgbc)
dot_data

 

 

  - 와인 데이터

wine = load_wine()
X_train, X_test, y_train, y_test = train_test_split(wine.data, wine.target, test_size = 0.2, random_state = 42)

  - XGBClassifier 모델 생성

  - 파라미터의 종류

  • n_estimators : 학습 모델의 수, 많아질수록 성능 향상의 가능성이 있으나, 속도가 느려짐
  • learning_rate : 학습률, 너무 크면 gradient 발산의 가능성이 있으며, 너무 작으면 학습이 느림
  • max_depth : 최대 탐색 깊이, 너무 크면 과적합의 가능성, 너무 작으면 학습 성능 저하
  • min_samples_split : 분할 종료 최소 샘플 수, 큰 수면 과적합을 막지만 학습 성능 저하 가능성
  • min_samples_leaf : leaf node가 되기 위한 최소 샘플 수, min_samples_split과 비슷한 용도
xgbc = XGBClassifier(n_estimators = 400, learning_rate = 0.1, max_depth = 3)
xgbc.fit(X_train, y_train)
preds = xgbc.predict(X_test)
preds_proba = xgbc.predict_proba(X_test)[:, 1]

cross_val = cross_validate(
    estimator = xgbc,
    X = iris.data, y = iris.target,
    cv = 5
)
print('avg fit time: {} (+/- {})'.format(cross_val['fit_time'].mean(), cross_val['fit_time'].std()))
print('avg score time: {} (+/- {})'.format(cross_val['score_time'].mean(), cross_val['score_time'].std()))
print('avg test score: {} (+/- {})'.format(cross_val['test_score'].mean(), cross_val['test_score'].std()))

# 출력 결과
avg fit time: 0.8099905490875244 (+/- 0.2795799385941016)
avg score time: 0.004575538635253906 (+/- 0.0016525575848722433)
avg test score: 0.96 (+/- 0.024944382578492935)

  - 모델에서 데이터의 각 변수 중요도 출력

fig, ax = plt.subplots(figsize = (10, 12))
plot_importance(xgbc, ax = ax)

  - xgb 모델을 트리 형식으로 출력

dot_data = xgb.to_graphviz(xgbc)
dot_data

 

 

3. XGBRegressor

  - XGB는 Classifier에 더 특화되어 있지만 Regressor도 할 수는 있음

  - 당뇨병 데이터

diabetes = load_diabetes()
X_train, X_test, y_train, y_test = train_test_split(diabetes.data, diabetes.target, test_size = 0.2, random_state = 42)

  - XGBRegressor 모델 생성

  - 파라미터의 종류

  • n_estimators : 학습 모델의 수, 많아질수록 성능 향상의 가능성이 있으나, 속도가 느려짐
  • learning_rate : 학습률, 너무 크면 gradient 발산의 가능성이 있으며, 너무 작으면 학습이 느림
  • max_depth : 최대 탐색 깊이, 너무 크면 과적합의 가능성, 너무 작으면 학습 성능 저하
  • min_samples_split : 분할 종료 최소 샘플 수, 큰 수면 과적합을 막지만 학습 성능 저하 가능성
  • min_samples_leaf : leaf node가 되기 위한 최소 샘플 수, min_samples_split과 비슷한 용도
  • objective : 목적함수, reg:linear(linear-regression), binary:logistic(binary-logistic-classification), count:poisson(count data poison regression) 등 다양

  - XGBClassifier보다 test score가 낮게 나

xgbr = XGBRegressor(n_estimators = 400, learning_rate = 0.1, max_depth = 3, objective = 'reg:squarederror')
xgbr.fit(X_train, y_train)
preds = xgbr.predict(X_test)

cross_val = cross_validate(
    estimator = xgbr,
    X = diabetes.data, y = diabetes.target,
    cv = 5
)
print('avg fit time: {} (+/- {})'.format(cross_val['fit_time'].mean(), cross_val['fit_time'].std()))
print('avg score time: {} (+/- {})'.format(cross_val['score_time'].mean(), cross_val['score_time'].std()))
print('avg test score: {} (+/- {})'.format(cross_val['test_score'].mean(), cross_val['test_score'].std()))

# 출력 결과
avg fit time: 0.3746964454650879 (+/- 0.027832593554179098)
avg score time: 0.005658674240112305 (+/- 0.0017620359721342335)
avg test score: 0.30005291115066424 (+/- 0.07589309667544569)

  - 모델에서 데이터의 각 변수 중요도 출력

fig, ax = plt.subplots(figsize = (10, 12))
plot_importance(xgbr, ax = ax)

  - xgb 모델을 트리 형식으로 출력

dot_data = xgb.to_graphviz(xgbr)
dot_data

 

 

● LightGBM

  • XGBoost보다 2년쯤 뒤에 나와 더 개선됨
  • 빠른 학습과 예측 시간
  • 더 적은 메모리 사용
  • 범주형 특징의 자동 변환과 최적 분할

 

  • 필요 라이브러리
from lightgbm import LGBMClassifier, LGBMRegressor
from lightgbm import plot_importance, plot_metric, plot_tree

 

1. LGBMClassifier

  - 붓꽃 데이터

iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size = 0.2, random_state = 42)

  - LGBMClassifier 모델 생성

lgbmc = LGBMClassifier(n_estimators = 400)
evals = [(X_test, y_test)]
lgbmc.fit(X_train, y_train, early_stopping_rounds = 100, eval_metric = 'logloss', eval_set = evals, verbose = True)
preds = lgbmc.predict(X_test)

cross_val = cross_validate(
    estimator = lgbmc,
    X = iris.data, y = iris.target,
    cv = 5
)
print('avg fit time: {} (+/- {})'.format(cross_val['fit_time'].mean(), cross_val['fit_time'].std()))
print('avg score time: {} (+/- {})'.format(cross_val['score_time'].mean(), cross_val['score_time'].std()))
print('avg test score: {} (+/- {})'.format(cross_val['test_score'].mean(), cross_val['test_score'].std()))

# 출력 결과
avg fit time: 0.19687752723693847 (+/- 0.08293570240505971)
avg score time: 0.001802968978881836 (+/- 0.0004004494069017428)
avg test score: 0.9600000000000002 (+/- 0.04898979485566355)

  - lgbm 모델이 실행되며 logloss의 변화를 관찰할 수 있는 그래프 출력

  - 성능이 어떻게 향상되고 있는지 볼 수 있음

plot_metric(lgbmc)

150번째 반복쯤에서 거의 최저값 나옴

  - 변수 중요도

  - LGBM 전용 plot_importance 사용

plot_importance(lgbmc, figsize = (10, 12))

  - 트리 형태로 출력

plot_tree(lgbmc, figsize = (28, 24))

 

  - 와인 데이터

wine = load_wine()
X_train, X_test, y_train, y_test = train_test_split(wine.data, wine.target, test_size = 0.2, random_state = 42)

  - LGBMClassifier 모델 생성

lgbmc = LGBMClassifier(n_estimators = 400)
evals = [(X_test, y_test)]
lgbmc.fit(X_train, y_train, early_stopping_rounds = 100, eval_metric = 'logloss', eval_set = evals, verbose = True)
preds = lgbmc.predict(X_test)

cross_val = cross_validate(
    estimator = lgbmc,
    X = wine.data, y = wine.target,
    cv = 5
)
print('avg fit time: {} (+/- {})'.format(cross_val['fit_time'].mean(), cross_val['fit_time'].std()))
print('avg score time: {} (+/- {})'.format(cross_val['score_time'].mean(), cross_val['score_time'].std()))
print('avg test score: {} (+/- {})'.format(cross_val['test_score'].mean(), cross_val['test_score'].std()))

# 출력 결과
avg fit time: 0.6419896125793457 (+/- 0.21000223475863156)
avg score time: 0.003860330581665039 (+/- 0.002245084936532545)
avg test score: 0.9776190476190475 (+/- 0.01119469694127331)

  - lgbm 모델이 실행되며 logloss의 변화를 관찰할 수 있는 그래프 출력

plot_metric(lgbmc)

  - 변수 중요도

plot_importance(lgbmc, figsize = (10, 12))

  - 트리 형태로 출력

plot_tree(lgbmc, figsize = (28, 24))
 

 

  - 유방암 데이터

cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, test_size = 0.2, random_state = 42)

  - LGBMClassifier 모델 생성

lgbmc = LGBMClassifier(n_estimators = 400)
evals = [(X_test, y_test)]
lgbmc.fit(X_train, y_train, early_stopping_rounds = 100, eval_metric = 'logloss', eval_set = evals, verbose = True)
preds = lgbmc.predict(X_test)

cross_val = cross_validate(
    estimator = lgbmc,
    X = cancer.data, y = cancer.target,
    cv = 5
)
print('avg fit time: {} (+/- {})'.format(cross_val['fit_time'].mean(), cross_val['fit_time'].std()))
print('avg score time: {} (+/- {})'.format(cross_val['score_time'].mean(), cross_val['score_time'].std()))
print('avg test score: {} (+/- {})'.format(cross_val['test_score'].mean(), cross_val['test_score'].std()))

# 출력 결과
avg fit time: 1.5169551372528076 (+/- 0.7215118218596442)
avg score time: 0.0062160491943359375 (+/- 0.002043592719798801)
avg test score: 0.9736531594472908 (+/- 0.015674460437800138)

  - lgbm 모델이 실행되며 logloss의 변화를 관찰할 수 있는 그래프 출력

plot_metric(lgbmc)

  - 변수 중요도

plot_importance(lgbmc, figsize = (10, 12))

  - 트리 형태로 출력

plot_tree(lgbmc, figsize = (28, 24))

 

 

2. LGBMRegressor

  - 당뇨병 데이터

diabetes = load_diabetes()
X_train, X_test, y_train, y_test = train_test_split(diabetes.data, diabetes.target, test_size = 0.2, random_state = 42)

  - LGBMRegressor 모델 생성

lgbmr = LGBMRegressor(n_estimators = 400)
evals = [(X_test, y_test)]
lgbmr.fit(X_train, y_train, early_stopping_rounds = 100, eval_metric = 'logloss', eval_set = evals, verbose = True)
preds = lgbmr.predict(X_test)

cross_val = cross_validate(
    estimator = lgbmr,
    X = diabetes.data, y = diabetes.target,
    cv = 5
)
print('avg fit time: {} (+/- {})'.format(cross_val['fit_time'].mean(), cross_val['fit_time'].std()))
print('avg score time: {} (+/- {})'.format(cross_val['score_time'].mean(), cross_val['score_time'].std()))
print('avg test score: {} (+/- {})'.format(cross_val['test_score'].mean(), cross_val['test_score'].std()))

# 출력 결과
avg fit time: 1.210813045501709 (+/- 0.6173186047501074)
avg score time: 0.010993432998657227 (+/- 0.009632501449539222)
avg test score: 0.30867643947179507 (+/- 0.07010708786960605)

  - lgbm 모델이 실행되며 logloss의 변화를 관찰할 수 있는 그래프 출력

plot_metric(lgbmr)

  - 변수 중요도

plot_importance(lgbmr, figsize = (10, 12))

  - 트리 형태로 출력

plot_tree(lgbmr, figsize = (28, 24))

+ Recent posts