<출처>
- 책 : 혼자 공부하는 머신러닝 + 딥러닝
- 저자 : 박해선
- 예제 : https://github.com/rickiepark/hg-mldl
앙상블¶
- 앙상블 학습을 통한 분류는 여러 개의 분류기를 생성하고 그 예측을 결합함으로써 보다 정확한 최종 예측을 도출하는 기법
- 어려운 문제의 결론을 내기 위해 여러 명의 전문가로 위원회를 구성해 다양한 의견을 수렴하고 결정하듯이 앙상블 학습의 목표는 다양한 분류기의 예측결과를 결합함으로써 단일 분류기보다 신뢰성이 높은 예측 값을 얻음
앙상블 특징¶
- 단일 모델의 약점을 다수의 모델들을 결합하여 보완
- 결정 트리의 단점인 오버 피팅을 수십 수천개의 많은 분류기를 결합해 보완
앙상블 유형¶
- 대표적인 배깅은 랜덤 포레스트 알고리즘, 부스팅은 에이다 부스팅, 그래디언트 부스팅, XGBoost, LightGBM 등이 있음
- 보팅 배깅 부스팅, 스태킹 등
In [50]:
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
wine = pd.read_csv('https://bit.ly/wine_csv_data')
data = wine[['alcohol', 'sugar', 'pH']].to_numpy()
target = wine['class'].to_numpy()
train_input, test_input, train_target, test_target = train_test_split(
data, target, test_size=0.2, random_state=42
)
wine
Out[50]:
alcohol | sugar | pH | class | |
---|---|---|---|---|
0 | 9.4 | 1.9 | 3.51 | 0.0 |
1 | 9.8 | 2.6 | 3.20 | 0.0 |
2 | 9.8 | 2.3 | 3.26 | 0.0 |
3 | 9.8 | 1.9 | 3.16 | 0.0 |
4 | 9.4 | 1.9 | 3.51 | 0.0 |
... | ... | ... | ... | ... |
6492 | 11.2 | 1.6 | 3.27 | 1.0 |
6493 | 9.6 | 8.0 | 3.15 | 1.0 |
6494 | 9.4 | 1.2 | 2.99 | 1.0 |
6495 | 12.8 | 1.1 | 3.34 | 1.0 |
6496 | 11.8 | 0.8 | 3.26 | 1.0 |
6497 rows × 4 columns
In [7]:
# return_train_score=True 검증 점수 뿐 아니라 훈련세트에 대한 점수도 같이 반환
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.9973541965122431 0.8905151032797809
- 결정 트리처럼 랜덤 포레스트도 특성 중요도를 제공
- 각 트리의 특성 중요도를 취합하여 계산
- 일반적으로 랜덤 포레스트에서 제공하는 특성 중요도가 하나의 트리에서 제공하는 것보다 더 신뢰도가 높다
In [8]:
rf.fit(train_input, train_target)
print(rf.feature_importances_)
[0.23167441 0.50039841 0.26792718]
In [9]:
import seaborn as sns
feature_names = ['alcohol', 'sugar', 'pH']
# feature 별 importance 매핑
for name, value in zip(feature_names, rf.feature_importances_):
print('{0} : {1: .3f}'.format(name, value))
# feature importance를 column 별로 시각화하기
sns.barplot(x=rf.feature_importances_, y = feature_names)
alcohol : 0.232
sugar : 0.500
pH : 0.268
Out[9]:
<Axes: >
In [11]:
# out of bag 샘플(검증 세트의 역할)
rf = RandomForestClassifier(oob_score=True, n_jobs=-1, random_state=42)
rf.fit(train_input, train_target)
print(rf.oob_score_)
0.8934000384837406
장단점과 매개변수¶
- 회귀와 분류에 있어서 랜덤 포레스트는 현재 가장 널리 사용되는 머신러닝 알고리즘이다.
- 랜덤 포레스트는 성능이 매우 뛰어나고 매개변수 튜닝을 많이 하지 않아도 잘 작동하며, 데이터의 스케일을 맞출 필요도 없다.
- 기본적으로 랜덤 포레스트는 단일 트리의 단점을 보완하는 장점은 가지고 있다.
- 대량의 데이터셋에서 랜덤 포레스트 모델을 만들 때 다소 시간이 걸릴 수 있지만 CPU코어가 많다면 손쉽게 병렬 처리할 수있다.
- n_jobs 매개변수를 이용하여 사용할 코어 수를 지정할 수 있다. (n_jobs=-1로 지정하면 컴퓨터의 모든 코어를 사용한다.)
엑스트라트리¶
- 부트스트랩 샘플을 사용하지 않음
- 각 결정트리를 만들 때 전체 샘플을 사용
- 노드 분할 시 가장 좋은 분할을 찾는 것이 아니라 무작위 분할
- 무작위 분할하므로 성능은 낮아지지만, 많은 트리를 앙상블
- 과대적합을 막고 검증 세트의 점수를 높이는 효과가 있음
In [14]:
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(scores)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
{'fit_time': array([0.50773811, 0.53384781, 0.51623178, 0.70141864, 0.35668468]), 'score_time': array([0.07810569, 0.10934901, 0.06248474, 0.06248522, 0.03190565]), 'test_score': array([0.88365385, 0.87884615, 0.90375361, 0.88835419, 0.88931665]), 'train_score': array([0.9971133 , 0.99663219, 0.998076 , 0.997595 , 0.9978355 ])}
0.9974503966084433 0.8887848893166506
In [15]:
et.fit(train_input, train_target)
print(et.feature_importances_)
[0.20183568 0.52242907 0.27573525]
그레이디언트 부스팅¶
- 그래디언트 부스팅 회귀 트리는 여러 개의 결정 트리를 묶어 강력한 모델을 만드는 앙상블 기법이다.
- 이름이 회귀지만 회귀/분류 모두 사용할 수 있다.
- 랜덤 포레스트와 달리 그래디언트 부스팅은 이전 트리의 오차를 보완하는 방식으로 순차적으로 트리를 만든다. 기본적으로 그래디언트 부스팅 회귀 트리에는 무작위성이 없다.
- 대신 강력한 사전 가지치기가 사용된다.
- 그래디언트 부스팅 트리는 머신러닝 경연 대회에서 우승을 많이 차지하였고, 업계에서도 널리 사용된다.
- 랜덤 포레스트보다는 매개변수 설정에 조금 더 민감하지만 잘 조정하면 높은 정확도를 제공해준다.
In [19]:
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.8881086892152563 0.8720430147331015
In [20]:
# n_estimators=500 : 트리를 500개 만듦, learning_rate=0.2 : 학습률(기본값:0.1)
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.9464595437171814 0.8780082549788999
In [21]:
gb.fit(train_input, train_target)
print(gb.feature_importances_)
[0.15872278 0.68011572 0.16116151]
히스토그램 기반 부스팅¶
- 정형의 데이터를 다루는 ML 알고리즘 중 인기가 높음
- 훈련데이터를 256개 구간으로 잘라서 빠르게 학습
- 255개 구간으로 나누고 누락된 값은 떼어 높은 1개로 사용
In [31]:
# from sklearn.experimental import enable_hist_gradient_boosting
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']))
# gb보다 성능이 좋음
0.9321723946453317 0.8801241948619236
In [36]:
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)
print(result.importances_mean)
{'importances_mean': array([0.08876275, 0.23438522, 0.08027708]), 'importances_std': array([0.00382333, 0.00401363, 0.00477012]), 'importances': array([[0.08793535, 0.08350972, 0.08908986, 0.08312488, 0.09274581,
0.08755051, 0.08601116, 0.09601693, 0.09082163, 0.09082163],
[0.22782374, 0.23590533, 0.23936887, 0.23436598, 0.23725226,
0.23436598, 0.23359631, 0.23398114, 0.23994612, 0.22724649],
[0.08581874, 0.08601116, 0.08062344, 0.07504329, 0.08427939,
0.07792957, 0.07234943, 0.07465846, 0.08139311, 0.08466423]])}
[0.08876275 0.23438522 0.08027708]
In [35]:
result = permutation_importance(hgb, test_input, test_target, n_repeats=10,
random_state=42, n_jobs=-1)
print(result)
print(result.importances_mean)
{'importances_mean': array([0.05969231, 0.20238462, 0.049 ]), 'importances_std': array([0.004 , 0.007938 , 0.00453846]), 'importances': array([[0.06230769, 0.05769231, 0.05538462, 0.05538462, 0.06076923,
0.06076923, 0.06846154, 0.06230769, 0.05461538, 0.05923077],
[0.20076923, 0.2 , 0.21153846, 0.20076923, 0.20307692,
0.18923077, 0.19615385, 0.19461538, 0.21384615, 0.21384615],
[0.05692308, 0.04692308, 0.05076923, 0.04769231, 0.04692308,
0.05 , 0.04384615, 0.04692308, 0.04307692, 0.05692308]])}
[0.05969231 0.20238462 0.049 ]
In [37]:
hgb.score(test_input, test_target)
Out[37]:
0.8723076923076923
XGBoost¶
In [46]:
# tree_method='hist' : 히스토그램 매개변수
from xgboost import XGBClassifier
xgb = XGBClassifier(tree_method='hist', random_state=42)
scores = cross_validate(xgb, train_input, train_target,
return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
0.9555033709953124 0.8799326275264677
LightGBM¶
- MS에서 만든 LightGBM --> 인기가 점점 높아지고 있는 모델
In [47]:
from lightgbm import LGBMClassifier
lgb = LGBMClassifier(random_state=42)
scores = cross_validate(lgb, train_input, train_target, return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
0.935828414851749 0.8801251203079884
반응형
'데이터분석' 카테고리의 다른 글
[23.07.21] 머신러닝(독버섯 찾기) - 36(2) (0) | 2023.07.21 |
---|---|
[23.07.18] 머신러닝(선형회귀) - 33(3) (0) | 2023.07.18 |
[23.07.18] 머신러닝(k-최근접 이웃 회귀) - 33(2) (0) | 2023.07.18 |
[23.07.18] 머신러닝(iris붓꽃데이터) - 33(1) (0) | 2023.07.18 |
[23.07.17] 머신러닝(Machine Learning) - 32(1) (0) | 2023.07.18 |