본문 바로가기

ML,DL

[ML] 트리의 앙상블

정형 데이터와 비정형 데이터

정형 데이터 : csv, 데이터베이스, 엑셀에 저장하기 쉬운 어떤 구조로 이루어진 데이터

비정형 데이터 : 이와 반대되는 데이터

정형 데이터를 다루는 데 가장 뛰어난 성과를 내는 알고리즘 : 앙상블 학습

 

1. 랜덤 포레스트 Random Forest

결정 트리를 랜덤하게 만들어 결정 트리의 숲을 만듦, 그리고 각 결정 트리의 예측을 사용해 최종 예측을 만든다

각 트리를 훈련하기 위해 우리가 입력한 훈련 데이터에서 랜덤하게 샘플을 추출하여 훈련 데이터를 만든다

이렇게 만들어진 샘플 : 부트스트랩 샘플

각 노드를 분할할 때 전체 특성 중에서 일부 특성을 무작위로 고른 다음 이 중에서 최선의 분할을 찾음

장점

  • 랜덤하게 선택한 샘플과 특성을 사용하기 때문에 훈련 세트에 과대적합 되는 것을 막아줌
  • 검증 세트와 테스트 세트에서 안정적인 성능을 얻을 수 있음

교차 검증

from sklearn.model_selection import train_test_split, cross_validate
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold
cv = StratifiedKFold(n_splits=10, shuffle=True, random_state=42)
rc = RandomForestClassifier()
score = cross_validate(rc, wine_data,wine_target,return_train_score=True, cv=cv)
np.mean(score['train_score']), np.mean(score['test_score'])

cross_validate로 교차 검증 수행

return_train_score=True : 훈련 세트와 검증 세트의 점수 반환

특성 중요도

rc.fit(wine_data, wine_target)
rc.feature_importances_

각 특성 중요도 출력

OOB

oob_rc = RandomForestClassifier(oob_score=True)
oob_rc.fit(wine_data, wine_target)
oob_rc.oob_score_

부트스트랩 샘플에 포함되지 않고 남는 샘플 : OOB 샘플

이 남는 샘플을 사용하여 부트스트랩 샘플로 훈련한 결정 트리를 평가할 수 있다

랜덤 포레스트는 각 결정 트리의 oob 점수를 평균하여 출력

 

2. 엑스트라 트리

랜덤 포레스트와 매우 비슷하게 동작, 기본적으로 100개의 결정 트리 훈련

전체 특성 중에 일부 특성을 랜덤하게 선택하여 노드 분할

랜덤 포레스트와의 차이점

부트스트랩 샘플을 사용하지 않는다! 즉 결정 트리를 만들 때 전체 훈련 세트를 사용한다

대신 노드를 분할할 때 가장 좋은 분할을 찾는 것이 아니라 무작위로 분할함

하나의 결정 트리에서 특성을 무작위로 분할하면 성능이 낮아지겠지만 트리를 앙상블 하기 때문에 과대적합을 막고 검증 세트의 점수를 높이는 효과

from sklearn.ensemble import ExtraTreesClassifier
et = ExtraTreesClassifier(n_jobs=-1, random_state=42)
scores = cross_validate(et, wine_data, wine_target, return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))

랜덤하게 노드를 분할하기 때문에 랜덤 포레스트보다 빠른 계산 속도

특성 중요도

et.fit(wine_data, wine_target)
print(et.feature_importances_)

 

3. 그레이디언트 부스팅

길이가 얕은 결정 트리를 사용하여 이진 트리의 오차를 보완하는 방식으로 앙상블

-> 과대적합에 강하고 일반적으로 높은 일반화 성능 기대 가능

결정 트리의 개수를 늘려도 과대적합에 매우 강하다. 학습률을 증가시키고 트리의 개수를 늘리면 조금 더 성능이 향상될 수 있다.

경사 하강법을 사용하여 트리를 앙상블에 추가

  • 분류 : 로지스틱 손실 함수
  • 회귀 : 평균 제곱 오차 함수

결정 트리를 계속 추가하면서 가장 낮은 곳을 찾아 이동

from sklearn.ensemble import GradientBoostingClassifier
gb = GradientBoostingClassifier(random_state = 42)
scores = cross_validate(gb, wine_data, wine_target, return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))

일반적으로 그레이디언트 부스팅이 랜덤 포레스트보다 조금 더 높은 성능을 얻을 수 있다.

하지만 순서대로 트리를 추가하기 때문에 훈련 속도가 느리다.

GradientBoostingClassifier에는 n_jobs 매개변수 x

4. 히스토그램  기반 그레이디언트 부스팅

먼저 입력 특성을 256개의 구간으로 나눔, 노드를 분할할 때 최적의 분할을 매우 빠르게 찾을 수 있다

기본 매개변수에서 안정적인 성능

매개변수

  • max_iter : 부스팅 반복 횟수 지정
from sklearn.experimental import enable_hist_gradient_boosting
from sklearn.ensemble import HistGradientBoostingClassifier
hgb= HistGradientBoostingClassifier(random_state=42)
scores = cross_validate(hgb,wine_data,wine_target,return_train_score=True,n_jobs=-1)
print(np.mean(scores['train_score']),np.mean(scores['test_score']))

과대적합을 잘 억제하면서 그레이디언트 부스팅보다 조금 더 높은 성능 제공

특성 중요도

permutation_importance() 함수 사용

5. XGBoost

from xgboost import XGBClassifier
xgb = XGBClassifier(tree_method='hist', random_state=42)
scores = cross_validate(xgb,wine_data,wine_target,return_train_score=True)
print(np.mean(scores['train_score']),np.mean(scores['test_score']))

6. LightGBM

from lightgbm import LGBMClassifier
lgb = LGBMClassifier(random_state=42)
scores = cross_validate(lgb,wine_data,wine_target,return_train_score=True,n_jobs=-1)
print(np.mean(scores['train_score']),np.mean(scores['test_score']))