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
- 전체 데이터의 영역(bucket)을 몇개로 분할
- 각각의 변수들에 대해서 학습 데이터를 정렬 후, 정렬 분포에서 percent를 보고 영역 분할
- 각각의 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 방향을 왼쪽으로 설정
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))
참고자료
728x90
반응형
'Data Analysis & ML' 카테고리의 다른 글
[Machine Learning][머신러닝] 릿지/라쏘/엘라스틱넷 (정규화 회귀분석) (1) | 2024.05.15 |
---|