[머신러닝] 5-3. 트리의 앙상블
앙상블 학습이 뭐야?
우와아 참 많이 달려왔다 좀만 더!! 파이팅!!!!
정형 데이터와 비정형 데이터
어떤 구조로 가지런히 정리 되어 있는 것을 정형 데이터라 한다. csv, 데이터 베이스, 엑셀에 저장하기 쉽다
반대는? 비정형 데이터!
우리 주변에 책, 글과 같은 텍스트, 사진, 음악! 이것이 비정형 데이터지
정형 데이터를 다루는 데 가장 뛰어난 성과를 내는 알고리즘이 앙상블 학습이다. 이는 대부분 결정트리 기반이다.
랜덤 포레스트
랜덤 포레스트는 앙상블 학습의 대표 주자이다. 안정적인 성능으로 많이 사용한다.
랜덤 포레스트! 결정 트리를 랜덤하게 만들어서 숲을 만든다. 각 결정 트리의 예측으로 최종 예측을 만드는 것이다
각 트리를 훈련하기 위한 데이터를 랜덤하게 만든다.
입력한 훈련 데이터에서 랜덤하게 샘플을 추출하여 훈련 데이터를 만든다. 한 샘플이 여러 번 뽑힐 수 있다. 이렇게 만들어진 샘플이 부트스트랩 샘플이다. 이 크기는 훈련 세트의 크기와 같다.
부트 스트랩: 데이터 세트에서 중복을 허용하여 데이터를 샘플링 하는 방법!
부트스트랩 샘플: 부트스트랩 방식으로 샘플링하여 분류한 데이터
각 노드를 분할 할 때 전체 특성 중 일부 특성을 랜덤으로 뽑고 그 중 최고를 찾는다. RandomForestClassifier는 기본적으로 전체 특성 개수의 제곱근만큼의 특성을 선택! 특성이 4개면 노드마다 2개를 랜덤 선택! 다만 Regressor은 전체 특성을 사용한다.
훈련하고 각 트리의 클래스별 확률을 평균하여 가장 높은 확률을 가진 클래스를 예측으로 삼는다.
회귀일때는 단순히 각 트리의 예측을 평균한다.
랜덤하게 선택한 샘플과 특성을 사용하니 과대적합될 걱정은 없다. 아주 안정적이다!
이제 실습해보자
1
2
3
4
5
6
7
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
wine=pd.read_csv('https://bit.ly/wine-date')
data=wind[['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)
cross_validate()로 교차 검증! 기본 100개 결정트리! n_jobs를 -1로 해서 모든 CPU코어를 사용해버리자! cross_validate의 n_jobs도 -1로 해서 최대한 병렬로 교차 검증!! return_train_score=True로 하면 검증 점수+훈련 세트 점수 반환이 된다!! 우와아아 과대적합을 파악하는데 정말 좋잖아!
1
2
3
4
5
6
7
from sklearn.model_selection import cross_validate
from sklearn.ensemble import RandomForestClassifier
rf=RandomForestClassifier(n_jobs=-1, random_state=42)
score=cross_validate(rf, train_input, train_target, return_train_socre=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
#0.9973 0.8905
흐음 과대적합이잖아?
랜덤 포레스트 특성 중요도는 각 결정 트리의 특성 중요도를 취합한 것이다.
1
2
3
4
5
#특성 중요도 출력
rf.fit(train_input, train_target)
print(rf.feature_importances_)
#[0.2316 0.5003 0.1679]
결정 트리에서는 [0.1234 0.8686 0.0007]이었다. [알코올 도수, 당도, pH] 였는데 당도 중요도가 감소하고 나머지는 조금 올라갔다. 랜덤하게 선택한 결과다
하나의 특성에 과도하게 집중되지 않고 좀 더 많은 특성이 훈련에 기여할 기회를 얻는다. 과대적합을 줄이고 일반화 성능을 높인 것이다!
모델을 자체적으로 평가하는 점수를 얻을 수도 있다! 랜덤 포레스트는 훈련 세트에서 중복을 허용해서 샘플을 만든다고 했다. 여기서 샘플에 포함되지 않는 것들도 있을 것이다. 이러한 것을 OOB(out of bag)샘플이라고 한다. 이것으로 훈련한 결정트리를 평가할 수 있다. 검증 세트와 비슷하다!
oob_score=True로 하면 각 결정트리의 OOB 점수를 평균하여 출력한다.
1
2
3
4
5
rf=RandomForestClassifier(oob_score=True, n_jobs=-1, random_state=42)
rf.fit(train_input, train_target)
print(rf.oob_score_)
#0.893
엑스트라 트리
엑스트라 트리 랜덤 포레스트와 참 비슷하다. 전체 특성 중에 일부 특성을 랜덤하게 선택하여 노드를 분할하는데 사용한다
그럼 뭐가 다르냐? 부트스트랩 샘플을 사용하지 않는다. 결정트리를 만들 때 전체 훈련 세트를 사용한다. 또 노드를 분할할 때 가장 좋은 분할을 찾는게 아닌 랜덤으로 분할한다. splitter=’random’!
무작위로 분할하면 성능은 낮아지겠지 하지만 많은 트리를 앙상블하니까 과대적합을 막고! 검증 세트의 점수를 높일 수 있어!
1
2
3
4
5
6
from sklearn.ensemble import ExtraTreesClassifier
et=EctraTrees(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
엑스트라 트리가 무작위성이 크기 때문에 랜덤 포레스트보다 더 많은 결정 트리를 훈련해야 한다. 결정 트리는 최적을 분할을 찾는데 시간을 많이 소모하는 반면 엑스트리는 랜덤하게 분할하니 빠른 계산 속도를 가졌다!!
1
2
3
4
5
# 중요도 확인
et.fit(train_input, train_target)
print(et.feature_importances_)
#[0.2018 0.5224 0.2757]
그레이디언트 부스팅
그레이디언트 부스팅은 깊이가 얕은 결정 트리를 사용하여 이전 트리의 오차를 보완하는 방식으로 앙상블 하는 방법이다. 깊이 3으로 결정 트리 100개를 사용한다. 깊이가 얕기 때문에 과대적합에 강하다!! 일반화 성능도 뛰어나다
경사하강법을 사용해 트리를 앙상블에 추가한다. 분류에서는 로지스틱 손실함수이고 회귀에서는 평균 제곱 오차 함수를 사용한다.
결정 트리를 계속 추가하면서 가장 낮은 곳을 찾아 이동하자.
1
2
3
4
5
6
from sklearn.ensemble import GradientBoostingClassifier
gb=GradientBoostingClassifier(random_state=42)
scores=cross_validate(gb, train_input, train_target, return train_socre=True, n_jobs=-1)
print(np.mean(scores['train_socre']), np.mean(scores['test_score']))
#0.888 0.872
과대적합이 아니다! 결정 트리 개수를 늘려도! 매우 강하다고! 학습률을 증가시키고 트리 개수를 더 늘리자! 아주 성능이 좋아지겠지
1
2
3
4
5
gb=GradientBoostingClassifier(n_estimators=500, learning_rate=0.2, random_state=42)
scores=cross_validate(gb, train_input, train_target, return_train_socre=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
#0.946 0.878
고대적합을 잘 억제하고 있군
1
2
3
4
5
#특성 중요도
gb.fit(train_input, train_target)
print(gb.feature_importances_)
#[0.1587 0.6801 0.1611]
그레이디언트 부스팅이 랜덤 포레스트보다 일부 특성(당도)에 집중하는 것을 볼 수 있다
subsample의 기본값이 1.0으로 전체 훈련 세트를 사용한다. subsample이 1보다 작으면 훈련 세트 일부를 사용한다. 마치 미니배치 경사 하강법과 확률적 경사하강법과 비슷하다
그레이디언트 부스팅이 랜덤 포레스트보다 조금 더 높은 성능을 얻을 수 있다. 하지만 순서대로 트리를 추가하는 관계로 훈련 속도는.. 느리다!
히스토그램 기반 그레이디언트 부스팅
히스토그램 기반 그레이디언트 부스팅은 정형 데이터를 다루는 머신러닝 알고리즘 중에 가장 인기가 높다!
최적의 분할을 빨리 찾기 우해 특성을 256개 구간으로 먼저 나누자
입력에 누락된 특성이 있더라도 이를 전처리할 필요 없게 256개 구간 중 하나를 떼어 놓고 누락된 값을 위해 사용하자
1
2
3
4
5
6
7
from sklearn.experimental import enable_hist_grdient_boosting
from sklearn.ensemble import HistGradientBoostingClassifier
hgb=HistGradientBoostingClassifier(random_state=42)
scores=cross_validate(hgb, train_input, train_targetm, return_train_score=True)
print(np.mean(score['train_score']),np.mean(scores['test_score']))
#0.932 0.880
과대적합을 잘 억제했다. 그레이디언트 부스팅보다 조금 더 성능이 높다!
1
2
3
4
5
#특성 중요도 확인하기
hgb.fit(train_input, train_target)
print(rf.feature_importances_)
#[0.231 0.500 0.267]
그레이티언트 부스팅은 당도에 좀 더 집중했지만 여기는 랜덤 포레스트와 비슷하게 다른 특성에도 관심을 보인다. 다양한 특성을 골고루 잘 평가하는군
1
2
3
4
#성능 최종 확인
hgb.score(test_input, testtarget)
#0.872
사이킷런 말고 히스토그램 기반 그레이디언트 부스팅 알고리즘을 구현한 라이브러리가 또 있다. 대표적으로 XGBoost가 있다. tree_method=’hist’하면 히스토그램 기반 그레이디언트 부스팅을 사용할 수 있다.
1
2
3
4
5
6
from sgboost 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.882 0.870
또 있지! LightGBM!! 빠밤 아주 빠르고 최신 기술을 많이 적용하고 있다고!
1
2
3
4
5
6
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.933 0.878
4개의 앙사을 모두 다뤘다!! 끝!!
마무리
키워드
앙상블 학습 랜덤 포레스트 엑스트라 트리 그레이디언트 부스팅 히스토그램 기반 그레이디언트 부스팅
핵심 패키지와 함수
scikit-learn
RandomForestClassifier ExtraTreeClassifier GradientBoostingClassifier HistGradientBoostingClassigier
참고 자료
혼자공부하는 머신러닝+딥러닝


