12. 트리 앙상블

akanana·2023년 1월 16일
0

개인공부

목록 보기
24/30
post-thumbnail

정형 데이터를 다룰때에 가장 뛰어난 성과를 내는것이 앙상블 학습이다

랜덤 포레스트

앙상블 학습의 대표적인 모델로 랜덤 포레스트가 있다
이때 랜덤포레스트는 훈련 데이터에서 랜덤한 샘플을 추출하여 훈련 데이터를 만드는데, 중복된 샘플또한 추출 할 수도 있다
이러한 샘플을 부트스트랩 샘플이라고 부른다
랜덤 포레스트는 랜덤한 샘플과 특성을 사용하기에, 과대적합을 방지하고 안정적인 성능을 가진다

import numpy as np
import pandas as pd
wine = pd.read_csv('https://bit.ly/wine_csv_data')

data = wine[['alcohol','sugar','pH']].to_numpy()
target = wine['class'].to_numpy()

from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = \
    train_test_split(data,target,test_size=0.2,random_state=42)

우선 정보를 가져온다음, RandomForestClassifier를 통해 모델을 생성하였다

from sklearn.model_selection import cross_validate
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_jobs=-1, random_state=42)
scores = cross_validate(rf, train_input, train_target, \
	return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']),np.mean(scores['test_score']))
# 0.997... 0.890...

과대적합이 됐지만 어느정도 동작하는 모델은 완성되었다
이제 특성 중요도를 출력해보자

rf.fit(train_input, train_target)
print(rf.feature_importances_) # [0.23167441 0.50039841 0.26792718]

RandomForestClassifier 에는 자체적으로 모델을 평가하여 점수를 얻을 수 있는 기능이 있다
이를 OBB SAMPLE 라고 한다

rf = RandomForestClassifier(oob_score=True,n_jobs=-1, random_state=42)
rf.fit(train_input, train_target)
print(rf.oob_score_) # 0.893...

엑스트라 트리

위 랜덤트리와 매우 비슷하지만, 약간의 차이가 있다

  • 부트스트랩 샘플을 사용하지 않음
  • 성능이 상대적으로 낮지만 과대적합을 방지 할 수 있다
from sklearn.model_selection import cross_validate
from sklearn.ensemble import ExtraTreesClassifier
et = ExtraTreesClassifier(n_jobs=-1, random_state=42)
scores = cross_validate(et, train_input, train_target, \
	return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']),np.mean(scores['test_score']))
# 0.997... 0.888...

먼저 위처럼 모델을 만들어 점수를 출력하였다

et.fit(train_input, train_target)
print(et.feature_importances_) # [0.20183568 0.52242907 0.27573525]

그레이디언트 부스팅

얕은 결정트리로 오차를 보정하는 모델
경사하강법을 통해 트리를 앙상블에 추가한다

from sklearn.model_selection import cross_validate
from sklearn.ensemble import GradientBoostingClassifier
gb = GradientBoostingClassifier(random_state=42)
scores = cross_validate(gb, train_input, train_target, \
	return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']),np.mean(scores['test_score']))
# 0.888... 0.872...

과대적합에 매우 강한 모습을 보여준다
트리개수를 늘려 점수를 높혀보자

gb = GradientBoostingClassifier(n_estimators=500, \
	learning_rate=0.2,random_state=42)
scores = cross_validate(gb, train_input, train_target, \
	return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']),np.mean(scores['test_score']))
# 0.946... 0.878...
gb.fit(train_input, train_target)

n_estimators를 500개로 늘렸지만 여전히 과대적합을 잘 억제하고있다
마지막으로 특성 중요도를 확인하자

print(gb.feature_importances_)
# [0.15872278 0.68011572 0.16116151]

히스토램 기반 그래이디언트 부스팅

히스토램 기반 그래이디언트 부스팅은 특성을 256개의 구간으로 구분, 최적의 분할을 매우 빨리 얻어낸다

HistGradientBoostingClassifier

from sklearn.model_selection import cross_validate
from sklearn.ensemble import HistGradientBoostingClassifier
hgb = HistGradientBoostingClassifier(random_state=42)
scores = cross_validate(hgb, train_input, train_target, \
	return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']),np.mean(scores['test_score']))
# 0.932... 0.880...

과대적합에도 유리하며, 성능또한 매우 우수하다
이번엔 n_repeats값을 변경하여 섞을 횟수를 지정해보자

from sklearn.inspection import permutation_importance
hgb.fit(train_input, train_target)
result = permutation_importance(hgb, train_input, train_target, \
	n_repeats=10, random_state=42, n_jobs=-1)
print(result.importances_mean) # [0.059... 0.202... 0.049]

result = permutation_importance(hgb, test_input, test_target, \
	n_repeats=10, random_state=42, n_jobs=-1)
print(result.importances_mean) # [0.088... 0.234... 0.080...]

print(hgb.score(test_input, test_target)) # 0.872...

위 값을 통해, 실제로 당도에 더 집중함을 알 수 있다
이를 통해 실전에서 어떤 특성에 더 관심을 둘지 결정 가능하다

XGBClassifier

from xgboost import XGBClassifier
xgb = XGBClassifier(tree_method='hist', random_state=42)
scores = cross_validate(xgb, train_input, train_target, \
	return_train_score=True)
print(np.mean(scores['train_score']),np.mean(scores['test_score']))
# 0.955... 0.879...

LGBMClassifier

from lightgbm import LGBMClassifier
lgb = LGBMClassifier(random_state=42)
scores = cross_validate(lgb, train_input, train_target, \
	return_train_score=True, n_jobs=-11)
print(np.mean(scores['train_score']),np.mean(scores['test_score']))
# 0.935... 0.880...

0개의 댓글