정형 데이터를 다룰때에 가장 뛰어난 성과를 내는것이 앙상블 학습
이다
앙상블 학습의 대표적인 모델로 랜덤 포레스트
가 있다
이때 랜덤포레스트는 훈련 데이터
에서 랜덤한 샘플을 추출하여 훈련 데이터
를 만드는데, 중복된 샘플또한 추출 할 수도 있다
이러한 샘플을 부트스트랩 샘플
이라고 부른다
랜덤 포레스트
는 랜덤한 샘플과 특성을 사용하기에, 과대적합을 방지하고 안정적인 성능을 가진다
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개의 구간으로 구분, 최적의 분할을 매우 빨리 얻어낸다
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...
위 값을 통해, 실제로 당도에 더 집중함을 알 수 있다
이를 통해 실전에서 어떤 특성에 더 관심을 둘지 결정 가능하다
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...
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...