Data Analysis & ML

[Machine Learning][머신러닝] XGBoost의 개념과 예제 코드

YSY^ 2024. 5. 16. 18:10

XGBoost(Extra Gradient Boost)

XGBoost란

  • Gradient Boost 알고리즘을 기반으로 개선해서 나온 모델.
  • 캐글 경진대회에서 상위에 입상한 데이터 과학자들이 사용한 것을 알려저 유명해짐.
  • Gradient Boost의 단점인 느린수행시간을 해결하고 과적합을 제어할 수 있는 규제를 제공하여 성능을 높임.
  • 두가지 개발 방법

XGBoost의 장점

  • 높은 성능 (실제로 Kaggle에서 XGboost가 상위권을 다수 차지)
  • 효율성, 유연성 ,휴대성이 뛰어남
  • 여러 파라미터를 조절해 가며 최적의 Model을 만들 수 있음
  • 과적합 방지
  • 신경망에 비해 시각화가 쉽고, 직관적임
  • 자원이 많으면 더 빠르게 학습시킬 수 있음
  • Cross Validation 지원

XGBoost의 알고리즘

Basic Greedly Algorithm - Split Finding Algorithm

  • 기존 Gradient Boost 의 알고리즘은 트리모델에서 최적의 분할 지점을 찾는 알고리즘. 즉 가능한 모든 분할 지점(모든 경우의 수)을 greedly하게 탐색
  • 하지만 데이터가 너무 크면 메모리에 들어가지 않으며, 병렬처리가 되지 않음
  • 이 알고리즘을 병렬 학습을 할 수 있도록 구현한 것이 XGBoost
  • XGBoost는 병렬 학습을 위해 분산 컴퓨팅 시스템, GPU, 다양한 트리 빌딩 방법을 지원

Approximate Algorithm

  1. 전체 데이터의 영역(bucket)을 몇개로 분할
    • 각각의 변수들에 대해서 학습 데이터를 정렬 후, 정렬 분포에서 percent를 보고 영역 분할
  2. 각각의 bucket에 대해 gradient를 찾고, Best split bucket를 찾음.
    • 아래 예시에서 만약 기존 방식이라면 40개의 샘플을 오름차순으로 정렬 후, 인접한 두 값들의 중앙값을 뽑아 각 샘플들을 비교하면, 최대 39번이나 최소가 되는 분할점을 계산해야함.
    • 하지만 그룹(bucket)을 10개로 나눈다면 각 그룹에서 3번씩 계산하고, 이 계산이 총 10개 그룹에서 이뤄짐으로 30번만 계산하면 됨 (기존보다 계산 횟수 감소)
    • 또한 각 그룹의 계산을 다른 쓰레드로 처리할 수 있다. 즉 각각의 bucket에 대해 병렬처리를 할 수 있음

XGBoost에서 제공하는 Tree split 방식은 두가지가 있음

1. Global variant

  • 한 번에 모든 Split point 후보군을 제시, 즉 split한 상황에서 처음에 만들어 놓은 bucket기준을 그대로 적용
  • 아래 Left child node에는 bucket 개수가 5개, Right에는 6개임 (짤린 부분 포함)
  • Tree의 Depth가 깊어질 수록 탐색해야하는 bucket 개수가 줄어듬, bucket내부의 size는 짤린 bucket을 제외하고는 parent node부터 leaf node까지 동일하게 유지

2. Local variant

  • 매 iteration마다 Split point 후보군을 제시, 즉 split한 상황에서 다시 bucket의 영역을 구분
  • Tree의 Depth가 깊어질 수록 각 node들의 bucket의 개수는 같음
  • 다만 bucket내부의 size는 parent node부터 leaf node로 갈 수록 감소
  • split finding 최적화를 통해 split canditate의 수를 줄이고 병렬화도 가능해짐

Global 과 local의 성능 비교

  • 보통 1/eps의 bucket이 생성
    • 0.3의 경우 3~4개의 bucket이, 0.05일때는 20개정도의 bucket가 생성
    • global이나 local 둘다 상황에 따라 성능이 다르며, 주의 사항은 global eps을 너무 크게 잡으면 기존보다 성능이 떨어짐

Sparsity-aware Split Finding

  • XGBoost 알고리즘은 결측치가 있는 데이터 셋도 학습이 가능하며 이를 할 수 있게 하는 것이 Sparsity-aware Split Finding
  • 결측치가 있는 데이터들을 분류할 Default 방향을 결정하는 알고리즘
  • 모든 결측치를 한 번은 오른쪽 전부 배치하고 다른 한번은 왼쪽에 배치하여 Split Point를 찿음
  • 위 그림에서는 모든 결측치를 왼쪽에 배치하였을 때 더 좋은 Split point를 찾을 수 있으므로, 해당 branch에서 결측치가 있는 데이터를 분류할 Default 방향을 왼쪽으로 설정

Sparsity aware algoritm이 기존 알고리즘보다 성능이 훨씬 좋다.

Tree을 병렬처리하기 위한 시스템 최적화

1. Sorting Data Setting

  • 데이터가 커질때 Tree 학습할때 가장 오래 걸리는 부분은 각 변수를 정렬(sorting)하는 것
  • Xgboost는 데이터를 column기반으로 저장 (compressed column foramt)
  • 각각의 column들은 각각의 feautre에 따라 미리 sorting 되어있음.
    • 각 column마다 index는 달라질 수 있음
  • Input 데이터는 처음 한번만 만들어놓기 때문에 Tree를 학습시키면서 sorting을 계속 해줄 필요가 없음

2. Cache-aware access

  • Cache를 최적화 하는 알고리즘 포함

 

 

XGBoost의 예제 코드 (Scikit-learn)

  • XGBoost를 Scikit-learn프레임워크와 연동할 수 있도록 개발됨.
  • Scikit-learn의 Estimator들과 동일한 패턴으로 코드를 작성할 수 있다.
  • GridSearchCV나 Pipeline 등 Scikit-learn이 제공하는 다양한 유틸리티들을 사용할 수 있다.
  • XGBClassifier: 분류
  • XGBRegressor : 회귀

주요 매개변수

  • learning_rate : 학습률, 보통 0.01 ~ 0.2 사이의 값 사용
  • n_estimators : week tree 개수
  • max_depth: 트리의 depth 지정. (보통 3~10개)
  • min_child_weight : 값이 높아지면 under-fitting 됨, CV를 통해 튜닝되어야 한다.
  • booster='gbtree' : 트리,회귀(gblinear) 트리가 기본값, 좋은 성능을 내기 때문에 수정할 필요없음
  • silent=True : 모델이 적합되는 과정을 이해하기위해선 False으로한다
  • colsample_bytree=0.8 : 트리를 생성할때 훈련 데이터에서 변수를 샘플링해주는 비율. 보통0.6~0.9
  • colsample_bylevel=0.9 : 트리의 레벨별로 훈련 데이터의 변수를 샘플링해주는 비율. 보통0.6~0.9
  • gamma =0 : 노드가 split 되기 위한 loss function의 값이 감소하는 최소값을 정의한다. gamma 값이 높아질 수록 알고리즘은 보수적으로 변하고, loss function의 정의 에 따라 적정값이 달라지기때문에 반드시 튜닝해야한다.
  • objective : 'reg:linear', 'binary:logistic', 'multi:softmax', 'mulit:softprob' 가 존재
    • reg:linear : 회귀분석
    • binary:logistic : 이진분류의 경우 로지스틱 분석
    • multi:softmax : 다중분류이며 분류된 class를 return하는 경우
    • mulit:softprob : 다중분류이며 각 class에 속할 확률을 return하는 경우

XGBoost로 위스콘시 데이터 분류

  •  XGBClassifier 사용. 회귀분석일 경우 XGBRegressor 사용

위스콘시 데이터 로드 및 데이터셋 나누기

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split

cancer = load_breast_cancer()
X = cancer.data
y = cancer.target
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=1)

XGBClassifier 로 모델링

from xgboost import XGBClassifier, XGBRegressor

xgb_clf = XGBClassifier(n_estimators=200,
                        learning_rate=0.2,
                        max_depth=1)
xgb_clf.fit(X_train, y_train)
#==> XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1,
#              colsample_bynode=1, colsample_bytree=1, gamma=0, gpu_id=-1,
#              importance_type='gain', interaction_constraints='',
#              learning_rate=0.2, max_delta_step=0, max_depth=1,
#              min_child_weight=1, missing=nan, monotone_constraints='()',
#              n_estimators=200, n_jobs=0, num_parallel_tree=1,
#              objective='binary:logistic', random_state=0, reg_alpha=0,
#              reg_lambda=1, scale_pos_weight=1, subsample=1,
#              tree_method='exact', validate_parameters=1, verbosity=None)

pred_train = xgb_clf.predict(X_train)
pred_test = xgb_clf.predict(X_test)

성능지표 확인

from sklearn.metrics import accuracy_score, f1_score, recall_score, precision_score

def print_metrics(y, pred_y, title=None):
    if title:
        print(title)
    print("정확도:", accuracy_score(y, pred_y))
    print('재현율(recall):', recall_score(y, pred_y))
    print('정밀도(precision):', precision_score(y, pred_y))
    print('f1 score:', f1_score(y, pred_y))

 

참고자료

https://www.youtube.com/watch?v=VHky3d_qZ_E&ab_channel=%EA%B3%A0%EB%A0%A4%EB%8C%80%ED%95%99%EA%B5%90%EC%82%B0%EC%97%85%EA%B2%BD%EC%98%81%EA%B3%B5%ED%95%99%EB%B6%80DSBA%EC%97%B0%EA%B5%AC%EC%8B%A4

728x90
반응형