My Data Story

[모델 알고리즘][앙상블 학습] 그레이디언트 부스팅 본문

Machine Learning/2. 지도 학습 알고리즘

[모델 알고리즘][앙상블 학습] 그레이디언트 부스팅

Hwasss 2021. 8. 13. 15:11
728x90

◈  '앙상블 학습' 목차  

1. 배깅, 페이스팅

2. 랜덤포레스트

3. 에이다부스트

4. 그레이디언트 부스팅

     그레이디언트 부스팅에 대해 이해하고 확률적 그레이디언트 부스팅 패키지 lightGBM 에 대해 알아보자

5. XGBoost

6. 스태킹


1. 그레이디언트 부스팅

인기 많은 또 하나의 부스팅 알고리즘은 그레이디언트 부스팅이다.

그레이디언트 부스팅은 앙상블에 이전까지의 오차를 보정하도록 예측기를 순차적으로 추가한다. 

에이다부스터처럼 반복마다 샘플의 가중치를 수정하는 대신 이전 예측이 만든 잔여 오차에 새로운 예측기를 학습시킨다.

 

from sklearn.tree import DecisionTreeRegressor

tree_reg1 = DecisionTreeRegressor(max_depth=2)
tree_reg1.fit(X,y)

y2 = y - tree_reg1.predict(X)
tree_reg2 = DecsionTreeRegressor(max_depth=2)
tree_reg2.fit(X,y2)

y3 = y2 - tree_reg2.predict(X)
tree_reg3 = DecisionTreeRegressor(max_depth=2)
tree_reg3.fit(X,y3)

#새로운 샘플에 대한 예측을 만들려면 모든 트리의 예측을 더하면 된다. 
y_pred = sum(tree_reg.predict(X_new) in (tree_reg1, tree_reg2, tree_reg3)

 

 

그레이디언트 부스팅은 분류 문제와 회귀 문제에 모두 적용할 수 있고, 연속적으로 잔여 오차를 학습시키는 원리도 비슷하다.

다만 분류 문제 시, 예측기들이 잔여 오차를 학습할 수 있도록 y값을 클래스 레이블 대신 sigmoide 함수를 활용한 클래스 추정 확률을 활용한다. 결국 분류 문제에 그레이디언트 부스팅을 적용할 경우, 예측기들은 클래스 레이블을 예측하는 분류기가 아닌 클래스 추정 확률을 예측하는 회귀 모델이다. 

 

 

2. 그레이디언트 부스팅 모델 구현

사이킷런에서 회귀 문제는 GradientBoostingRegressor를 통해, 

회귀 문제는GradientBoostingClassifier를 통해 그레이디언트 부스팅 모델을 구현할 수 있다.

 

GradientBoostingRegressor 의 기본 손실 함수는 최소 제곱법(ls) 이고, 

GradientBoostingClassifier 의 기본 손실 함수는 로지스틱 손실 함수(deviance) 이다. 

매개 변수 loss 를 통해, 다른 손실 함수로 설정할 수 있다.  

ex. exponential, huber, lad,(최소 절댓값 오차), quantile(사분위수 손실 함수)

 

결정 트리를 기반 예측기로 사용하는 간단한 회귀 문제를 풀어보자.

(결정 트리 기반의 그레이디언트 부스팅 모델은 Gradient Tree Boosting  또는 Gradient Boosted Decision Tree이라고 한다.)

 

사이킷런에서 GradientBoostingRegressor를 사용하면 GBRT 앙상블을 간단하게 훈련시킬 수 있다.

 

from sklearn.ensembles import GradientBoostingRegressor

gbrt = GradientBoostingRegressor(max_depth=2, n_estimators=3, learning_rate=1.0)
gbrt.fit(X,y)

 

GradientBoostingRegressor의 매개 변수 중 learning_rate 는 각 트리의 기여 정도를 조절한다.

낮게 설정하면 앙상블을 훈련 세트에 학습시키기 위해 많은 트리가 필요하지만 예측 성능은 좋다. 

이는 축소라고 불리는 규제 방법이다. 

 

 

왼쪽은 훈련 세트를 학습하기에 트리가 충분하지 않은 반면, 오른쪽은 트리가 너무 많아 훈련 세트에 과대 적합되었다. 

 

 

3. 최적 트리수 

그레이디언트 부스팅 모델을 구성하는 최적의 트리수는 어떻게 찾을까?

 

■  방법1

많은 수의 트리를 훈련시키고 각 훈련 단계에서 검증 오차를 측정하여, 검증 오차가 최소인 예측기까지 앙상블 구성한다.

 

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

X_train, X_val, y_train, y_val = train_test_split(X, y)

gbrt = GradientBoostingRegressor(max_depth=2, n_estimators=120)
gbrt.fit(X_train, y_train)

#staged_predict() 함수를 사용해, 각 훈련 단계에서 만들어진 예측기를 순회하는 반복자를 반환한다. 
#각 훈련 단계에서 예측기 마다 검증 오차 계산한다.
errors = [mean_squared_errors(y_val, y_pred) 
          for y_pred in gbrt.staged_predict(X_val)]
          
#검증 오차가 가장 낮은 예측기까지 포함하는 앙상블을 구성한다.
best_n_estimators = np.argmin(errors) + 1

#최적의 트리수로 다시 훈련시킨다.
gbrt_best = GradientBoostingRegressor(max_depth=2, n_estimators=best_n_estimators)
grrt_best.fit(X_train, y_train)

 

 

■ 방법2 

실제로 훈련을 중지하는 방법으로 조기 종료를 구현할 수 있다. 

 

사이킷런에서 GradientBoostingRegressor 의 매개 변수 warm_start = True 로 설정하면, fit() 메서드가 호출될 때 기존 트리를 유지한 상태에서 예측기 훈련을 추가할 수 있다. 

 

gbrt = GradientBoostingRegressor(max_depth=2, warm_start=True)

min_val_error = float('inf')
error_going_up = 0

for n_estimators in range(120) : 
    gbrt.n_estimators = n_estimators
    gbrt.fit(X_train, y_train)
    
    y_pred = gbrt.predict(X_val)
    val_error = mean_squared_error(y_val, y_pred)
    
    if val_error < min_val_error : 
       min_val_error = val_error
       error_going_up = 0
    else :
       error_going_up += 1
       
       #min_val_error 가 5번 이상 갱신되지 않으면 조기 종료 실행
       if error_going_up == 5 : 
           break

 

 

4. 확률적 그레이디언트 부스팅

확률적 그레이디언트 부스팅은 랜덤 포레스트처럼 데이터와 특성을 서브 샘플링하는 식으로 그레이디언트 부스팅에 랜덤한 요소를 추가한 모델이다.

 

GradientBoostingRegressor 나 GradientBoostingClassifier 는 매개 변수 subsamples 를 통해, 각 트리가 훈련할 때 사용할 훈

련 샘플의 비율을 지정할 수 있다. 매개 변수 subsamples 값이 1이면 그레이디언트 부스팅 모델이 되고, subsamples 값이 1보다 작으면 확률적 그레이디언트 부스팅 모델이 된다.

 

예를 들어, subsampels=0.25로 설정하면 각 트리는 무작위로 선택된 25%의 훈련 샘플로 훈련하게 된다. 

이는 편향이 높아지는 대신 분산이 낮아지며 훈련 속도가 매우 빨라진다. 

 

이런 기법을 확률적 그레이디언트 부스팅이라고 한다. 

 

5. ligthGBM

lightGBM은 기존 트리 기반 알고리즘 '균형 트리 분할' 과 다르게, '리프 중심 트리 분할' 방식이다. 

즉 lightGBM은 트리의 균형을 맞추지 않고, 최대 손실값을 가지는 리프 노드를 계속 분할하면서 트리의 깊이가 깊어지고 비대칭적인 트리를 생성한다. 이로써  속도가 빨라지는 효과가 있다. 

 

사이킷런에서 LGBMRegressor 의 매개 변수 bagging_fraction, feature_fraction 등을 통해 샘플과 특성의 랜덤 선택 비율을 설정할 수 있다.

 

from lightgbm import LGBMRegressor

lgb_reg = LGBMRegressor(random_state=42) 
lgb_reg.fit(X_train, y_train)
y_pred = lgb_red(X_val)