08_ML(Machine_Learning)

21_트리 앙상블

chuu_travel 2025. 4. 10. 17:50
728x90
트리 앙상블

 

 

앙상블

  • 여러 머신러닝 모델을 결합하여 더 좋은 모델을 얻는 방법
  • 앙상블의 종류
    • 보팅
    • 배깅
    • 부스팅 등

 

보팅(Voting)

 

  • 여러 개의 분류기가 투표를 통해 최종 예측 결과를 결정
  • 종류
    • 하드 보팅(Hard Voting)
      • 다수의 분류기가 예측한 결과값을 최종 결과로 선정
    • 소프트 보팅(Soft Voting)
      • 모든 분류기가 예측한 결정 확률의 평균이 가장 높은 결과값을 최종 결과로 선정

 

배깅(Bagging)

 

 

# 복원추출
# 각각의 데이터셋을 가지고 학습한 모델들
  • 데이터 샘플링(Bootstrap)을 통해 모델을 학습시키고 결과를 집계하는 방법
    • Bootstrap
      • 데이터가 조금씩은 편향되도록 샘플링하는 기법
      • 분산이 높은 모델의 과대적합 위험을 줄이는 효과가 있음
  • 모두 같은 유형의 알고리즘 기반의 분류기를 사용
  • 데이터 분할 시 중복을 허용
  • 예시: 랜덤포레스트(RandomForest)
    • 과대적합되기 쉬운 의사결정나무의 과대적합을 줄여 성능을 높일 수 있음

 

부스팅(Boosting)

 

# 부스팅 -> 순차적으로 학습해야함

 

  • 여러 개의 분류기가 순차적으로 학습을 수행
  • 이전 분류기의 예측이 틀린 데이터에 대해서 올바르게 예측할 수 있도록 다음 분류기에게 가중치(weight)를 부여하면서 학습과 예측을 진행
  • 계속하여 분류기에게 가중치를 부스팅하며 학습을 진행하기 때문에 부스팅 방식이라고 불림
  • 일반적으로 부스팅 방식이 배깅에 비해 성능이 좋지만 속도가 느리고 과적합이 발생할 가능성이 더 높음
  • 예시: XGBoost, LightGBM

 

랜덤포레스트(가장 기본)

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split, cross_validate
from sklearn.ensemble import RandomForestClassifier, ExtraTreesClassifier, GradientBoostingClassifier
df = pd.read_csv('./data/wine.csv')

 

df.head()

 

x = df.drop("class", axis = 1)
y = df["class"]
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, stratify = y, random_state = 26)

 

# 사이킷런의 랜덤포레스트는 기본적으로 100개의 결정 트리를 사용함
rf = RandomForestClassifier(n_jobs = -1, random_state = 26)

 

# return_train_score: 교차 검증 시 훈련 세트에 대한 점수도 함께 반환(원래는 검증 데이터에 대한 점수만 반환)
scores = cross_validate(rf, x_train, y_train, return_train_score = True, n_jobs = -1)

 

print(np.mean(scores["train_score"]), np.mean(scores["test_score"]), np.mean(scores["fit_time"]))
0.9979795781335353 0.8926293773598875 0.2214503765106201

 

  • 랜덤포레스트는 의사결정나무의 앙상블이기 때문에 의사결정나무에서 제공하는 주요 매개변수는 모두 제공함
    • 특성 중요도 계산도 가능
      • 랜덤포레스트의 특성 중요도는 각 의사결정나무의 특성 중요도를 취합

 

rf.fit(x_train, y_train)

 

rf.feature_importances_
array([0.23820619, 0.50152526, 0.26026855])

 

  • 의사결정나무에 비해 두 번째 특성인 sugar의 중요도가 감소하고 alcohol과 pH의 중요도가 상승함
    • 랜덤포레스트는 하나의 특성에 과도하게 집중되지 않고 더 많은 특성이 훈련에 기여할 기회를 얻음
    • 과대적합이 줄어들고 일반화 성능을 높일 수 있음

 

rf = RandomForestClassifier(oob_score = True, n_jobs = -1, random_state = 26)
rf.fit(x_train, y_train)
# oob: out of back

 

rf.oob_score_
# 0.8926293773598875 검증 데이터와 비슷한 수치
0.8974408312487974

 

  • OOB(out of bag)샘플
    • 부트스트랩 샘플에 포함되지 않아 훈련에 사용되지 않은 샘플
    • oob 샘플을 검증 세트처럼 이용하여 훈련한 결정 트리를 평가할 수 있음

 

엑스트라 트리

  • 랜덤포레스트와 매우 유사함
    • 기본적으로 100개의 의사결정나무를 훈련
    • 의사결정나무가 제공하는 대부분의 매개변수를 지원
  • 랜덤포레스트와의 차이점
    • 부트스트랩 샘플을 사용하지 않음
      • 전체 훈련 세트를 사용함
    • 노드를 분할할 때 가장 좋은 분할을 찾는 것이 아니라 무작위로 분할함
      • 하나의 의사결정나무에서 특성을 무작위로 분할한다면 성능이 낮아짐
      • 하지만 많은 트리를 앙상블하기 때문에 과대적합을 방지하고 검증 세트 점수를 높이는 효과가 나타남

 

et = ExtraTreesClassifier(n_jobs = -1, random_state = 26)
scores = cross_validate(et, x_train, y_train, return_train_score = True, n_jobs = -1)
print(np.mean(scores["train_score"]), np.mean(scores["test_score"]), np.mean(scores["fit_time"]))
0.9980276781816354 0.8951328940549346 0.18139023780822755

 

  • 예제에서는 독립변수가 많지 않아서 랜덤포레스트와 차이가 크지 않음
  • 일반적으로 엑스트라트리가 무작위성이 더 크기 때문에 랜덤포레스트보다 더 많은 트리를 훈련해야함
  • 하지만 랜덤하게 노드를 분할하기 때문에 계산 속도가 빠름

 

# 엑스트라 트리도 특성 중요도를 제공함
et.fit(x_train, y_train)
print(et.feature_importances_)
[0.18806788 0.52480397 0.28712815]

 

 

그레디언트 부스팅(gradient boosting)

  • 깊이가 얕은 결정 트리를 사용하여 이전 트리의 오차를 보완하는 방식으로 앙상블하는 기법
  • 사이킷런의 GradientBoostingClassifier는 기본적으로 깊이가 3인 결정트리를 100개 사용함
    • 깊이가 얕은 결정 트리를 사용하여 과대적합을 방지할 수 있고 높은 일반화 성능을 기대할 수 있음
gb = GradientBoostingClassifier(random_state = 26)
scores = cross_validate(gb, x_train, y_train, return_train_score = True, n_jobs = -1)

 

print(np.mean(scores["train_score"]), np.mean(scores["test_score"]), np.mean(scores["fit_time"]))
0.8843081027348528 0.8687706374472496 0.24927101135253907

 

  • 그레디언트 부스팅은 결정 트리의 개수를 늘려도 과대적합에 강함
gb = GradientBoostingClassifier(random_state = 26, n_estimators = 500, learning_rate = 0.2)
scores = cross_validate(gb, x_train, y_train, return_train_score = True, n_jobs = -1)
# learning_rate = 0.2 :학습률

 

print(np.mean(scores["train_score"]), np.mean(scores["test_score"]), np.mean(scores["fit_time"]))
0.9425147380884692 0.8770420892870364 1.2247856616973878

 

gb.fit(x_train, y_train)

 

gb.feature_importances_
array([0.1535165 , 0.68318837, 0.16329513])
728x90

'08_ML(Machine_Learning)' 카테고리의 다른 글

23_서포트 벡터 머신  (0) 2025.04.11
22_랜덤포레스트_문제(상한 개사료)  (0) 2025.04.11
20_교차검증_그리드서치  (0) 2025.04.10
19_의사 결정 나무  (2) 2025.04.09
18_확률적 경사 하강법  (0) 2025.04.09