[혼공머신] Ch.5 트리 알고리즘_3. 트리의 앙상블
<혼자 공부하는 머신러닝 + 딥러닝>의 'Ch.5 트리 알고리즘_3. 트리의 앙상블'의 내용을 요약 및 정리한 내용입니다.
https://product.kyobobook.co.kr/detail/S000001810330
혼자 공부하는 머신러닝+딥러닝 | 박해선 - 교보문고
혼자 공부하는 머신러닝+딥러닝 | 혼자 해도 충분하다! 1:1 과외하듯 배우는 인공지능 자습서이 책은 수식과 이론으로 중무장한 머신러닝, 딥러닝 책에 지친 ‘독학하는 입문자’가 ‘꼭 필요한
product.kyobobook.co.kr
1. 앙상블 학습이 무엇인지 이해하고 다양항 앙상블 학습 알고리즘을 실습을 통해 배웁니다.
1. 정형 데이터와 비정형 데이터
이전에는 생선의 길이, 높이, 무게 등을 데이터로 사용했습니다. 해당 데이터는 CSV 파일에 가지런히 정리되어 있는 형태였습니다. 이번에 사용하고 있는 와인 데이터 역시 CSV 파일입니다.
이런 형태의 데이터를 정형 데이터라고 부릅니다. 이는 어떤 구조로 되어 있다는 의미입니다. 이런 데이터는 CSV나 데이터베이스, 혹은 엑셀에 저장하기 쉽습니다.온라인 쇼핑몰에 진열된 상품과 우리가 구매한 쇼핑 정보는 모두 데이터베이스에 저장되는 정형 데이터에 속합니다. 프로그래머가 다루는 대부분의 데이터가 정형 데이터 입니다.
그럼 정형 데이터의 반대는 무엇일까요? 이는 비정형 데이터입니다. 비정형 데이터는 데이터베이스나 엑셀로 표현하기 어려운 것들입니다. 우리 주위에서 찾아보면 글과 같은 텍스트 데이터, 디지털카메라로 찍은 사진, 핸드폰으로 듣는 디지털 음악등이 이에 해당합니다.
지금까지의 머신러닝 알고리즘은 정형 데이터에 잘 맞습니다. 그 중에서 정형 데이터를 다루는데 가장 성과를 내눈 알고리즘이 앙상블 학습 입니다. 이 알고리즘은 대부분 결정 트리를 기반으로 만들어져 잇습니다. 이번에 자루는 알고리즘들이 앙상블 학습에 속합니다.
그럼 비정형 데이터에는 어떤 알고리즘을 사용할까요? 바로 신경망 알고리즘입니다. 비정형 데이터는 규칙성을 찾기 어려워 전통적인 머신러닝 방법으로는 모델을 만들기 까다로습니다. 하지만 신경망 알고리즘의 놀라운 발전으로 인해 사진을 인식하고 텍스트를 이해하는 모델을 만들 수 있게 되었습니다.
이제 사이킷런에서 제공하는 앙상블 학습 알고리즘을 알아보겠습니다.
2. 랜덤 포레스트
랜덤 포레스트는 앙상블 학습의 대표 주자 중 하나로 안정적인 성능 덕분에 널리 사용되고 있습니다. 앙상블 학습을 적용할 때 가장 먼저 랜덤 포레스트를 시도해 보길 권합니다.
이름 자체로 유추할 수 있듯 랜덤 포레스트는 결정 트리를 랜덤하게 만들어 결정 트리(나무)의 숲을 만듭니다. 그리고 각 결정 트리의 예측을 사용해 최종 예측을 만듭니다. 그럼 랜덤 포레스트가 어떻게 숲을 구성하는지 알아보겠습니다.
먼저 랜덤 포레스트는 각 트리를 훈련하기 위한 데이터를 랜덤하게 만드는데, 이 데이터를 만드는 방법이 독특합니다. 우리가 입력한 훈련 데이터에서 랜덤하게 샘플을 추출하여 훈련 데이터를 만듭니다. 이때 한 샘플이 중복되어 추출될 수도 있습니다.
이렇게 만들어진 샘플을 부트스트랩 샘플이라고 부릅니다. 기본적으로 부트스트랩 샘플은 훈련 세트와 크기와 같게 만듭니다.
또한 각 노드를 분할할 때 전체 특성 중에서 일부 특성을 무작위로 고른 다음 이 중에서 최선의 분할을 찾습니다. 분류 모델인 RandomForestClassifier는 기본적으로 전체 특성 개수의 제곱근만큼의 특성을 선택합니다. 즉 4개의 특성이 있다면 노드마다 2개를 랜덤하게 선택하여 사용합니다. 다만 회귀 모델인 RandomForestRegressor는 전체 특성을 사용합니다.
사이킷런의 랜덤 포레스트는 기본적으로 100개의 결정 트리를 이런 방식으로 훈련합니다. 그다음 분류일 때는 각 트리의 클래스별 확률을 평균하여 가장 높은 확률을 가진 클래스를 예측으로 삼습니다. 회귀일 때는 단순히 각 트리의 예측을 평균합니다.
랜덤 포레스트는 랜덤하게 선택한 샘플과 특성을 사용하기 때문에 훈련 세트에 과대적합되는 것을 막아주고 검증 세트와 테스트 세트에서 안정적인 성능을 얻을 수 있습니다. 종종 기본 매개변수 설정만으로도 아주 좋은 결과를 냅니다.
그럼 사이킷런의 RandomForestClassifier 클래스를 화이트 와인을 분류하는 문제에 적용해보겠습니다.
먼저 와인 데이터 셋을 판다스로 불러오고 훈련 세트와 테스트 세트로 나눕니다.
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)
cross_validate() 함수를 사용해 교차 검증을 수행해 보겠습니다. RandomForestClassifiers는 기본적으로 100개의 결정 트리를 사용하므로 n_jobs 매개변수를 -1로 지정하여 모든 CPU 코어를 사용하는 것이 좋습니다. cross_validate()함수의 n_jobs 매개변수도 -1로 지정하여 최대한 병렬로 교차검증을 수행하겠습니다. 또 return_train_score 매개변수를 True로 지정하여 검증 점수뿐 아니라 훈련 세트에 대한 점수도 같이 반환하겠습니다. 훈련 세트와 검증 세트의 점수를 비교하면 과대적합을 파악하는데 용이합니다.
출력된 결과를 보면 훈련 세트에 다소 과대적합된 것 같습니다. 여기에서는 알고리즘을 조사하는 것이 목적이므로 매개변수를 조정하지 않고 진행하겠습니다.
랜덤 포레스트는 결정 트리의 앙상블이기 때문에 DecisionTreeClassifier가 제공하는 중요한 매개변수를 모두 제공한다는 특징이 있습니다. 또한 결정 트리의 큰 장점 중 하나인 특성 중요도를 계산합니다. 랜덤 포레스트의 특성 중요도는 각 결정 트리의 특성 중요도를 취합한 것입니다. 위의 랜덤 포레스트 모델을 훈련 세트에 훈련한 후 특성 중요도를 출력해 보겠습니다.
이 결과를 '결정 트리'에서 만든 특성 중요도와 비교해 보겠습니다. 결정 트리에서 특성 중요도는 다음과 같았습니다.
각각 [알코올 도수, 당도, pH] 였는데, 두 번째 특성인 당도의 중요도가 감소하고 알코올 도수와 pH의 특성의 중요도가 족므 상승했습니다. 이런 이유는 랜덤 포레스트가 특성의 일부를 랜덤하게 선택하여 결정 트리를 훈련하기 때문입니다. 그 결과 하나의 특성에 과도하게 집중하기 않고 좀 더 많은 특성이 훈련에 기여할 기회를 얻습니다. 이는 과대적합을 줄이고 일반화 성능을 높이는데 도움이 됩니다.
RandomForestClassifier에는 자체적으로 모델을 평가하는 점수를 얻는 기능도 존재합니다. 랜덤 포레스트는 훈련 세트에서 중복을 허용하여 부트스트랩 샘플을 만들어 결정트리를 훈련한다고 했습니다. 이때 부트스트랩 샘플에 포함되지 않고 남는 샘플 역시 존재합니다. 이런 샘플을 OBB 샘플이라고 합니다. 이 남는 샘플을 사용하여 부트스트랩 샘플로 훈련한 결정 트리를 마치 검증 세트와 같은 역할로 평가할 수 있습니다.
이 점수를 얻으려면 RadomForestClassifer 클래스의 oob_score 매개변수를 True로 지정해야 합니다. 이렇게 하면 랜덤 포레스트는 각 결정 트리의 OOB 점수를 평균하여 출력합니다. obb_score = True 로 지정하고 모델을 훈련하여 OOB 점수를 출력해 보겠습니다.
교차 검증에서 얻은 점수와 매우 비슷한 결과를 얻었습니다. OOB 점수를 사용하면 교차 검증을 대신할 수 있어서 결과적으로 훈련 세트에 더 많은 샘플을 사용할 수 있습니다.
다음은 랜덤포레스트와 아주 비슷한 엑스트라 트리를 알아보겠습니다.
3. 엑스트라 트리
엑스트라 트리는 랜덤 포레스트와 매우 비슷하게 동작합니다 기본적으로 100개의 결정 트리를 훈련합니다. 랜덤 포레스트와 동이랗게 결정트리가 제공하는 대부분의 매개변수를 지원합니다. 또한 전체 특성 중에 일부 특성을 랜덤하게 선택하여 노드를 분할하는 데 사용합니다.
랜덤 포레스트와 엑스트라 트리의 차이점은 부트스트랩 샘플을 사용하지 않는다는 점입니다. 즉 각 결정 트리를 만들 때 전체 훈련 세트를 사용합니다. 대신 노드를 분할할 때 가장 좋은 분할을 찾는 것이 아니라 무작위로 분할합니다.
하나의 결정 트리에서 특성을 무작위로 분할한다면 성능이 낮아지겠지만 많은 트리를 앙상블 하기 때문에 과대적합을 막고 검증 세트의 점수를 높이는효과가 있습니다. 사이킷런에서 제공하는 엑스트라 트리를 ExtraTreesClassifier입니다. 이 모델의 교차검증 점수를 확인해 보겠습니다.
랜덤 포레스트와 비슷한 결과를 얻었습니다. 이 예제는 특성이 많이 않아 두 모델의 차이가 크지 않습니다. 보통 엑스트리 트리가 무작위성이 좀 더 크기 때문에 랜덤 포레스트보다 더 많은 결정 트리를 훈련해야 합니다. 하지만 랜덤하게 노드를 분할하기 때문에 계산 속도가 엑스트라 트리의 장점입니다.
엑스트라 트리도 역시 특성 중요도를 제공합니다. 순서는 [알코올 도수, 당도, pH]이며, 결과를 보면 엑스트라 트리도 결정 트리보다 당도에 대한 의존성이 낮습니다.
엑스트리 트리의 회귀 버전은 ExtraTreesRegressor 클래스입니다.
지금까지 비슷하지만 조금 다른 2개의 앙상블 학습을 알아보았습니다. 이제 이 둘과 다른 방식을 사용하는 앙상블 학습에 대해 알아보겠습니다. 먼저 그레이디언트 부스팅입니다.
4. 그레이디언트 부스팅
그레이디언트 부스팅은 깊이가 얕은 결정 트리를 사용하여 이진 트리의 오차를 보완하는 방식으로 앙상블하는 방법입니다. 사이킷런의 GradientBoostingClassifier는 기본적으로 깊이가 3인 결정 트리를 100개 사용합니다. 깊이가 얕은 결정 트리를 사용하기 때문에 과대적합에 강하고 일반적으로 높은 일반화 성능을 기대할 수 있습니다.
해당 방법은 경사 하강법을 사용하여 트리를 앙상블에 추가합니다. 분류에서는 로지스틱 손실 함수를 사용하고 회귀에서는 평균 제곱 오차 함수를 사용합니다.
경사 하강법은 손실 함수를 산으로 정의하면 가장 낮은 곳으로 찾아 내려오는 과정과 같습니다. 이때 가장 낮은 곳을 찾아 내려오는 방법은 모델의 가중치와 절편을 조금씩 바꾸는 것입니다. 그레이디언트 부스팅은 결정 트리를 계속 추가하면서 가장 낮은 곳을 찾아 이동합니다.
또한 경사하강법에서 손실함수의 낮은 곳으로 천천히 조금씩 이동하는 것처럼 그레이디언트 부스팅도 마찬가지입니다. 그래서 깊이 낮은 트리를 사용하는 것입니다. 또한 학습률 매개변수로 속도를 조절하는 것 역시 마찬가지 입니다.
그레이디언트 부스팅의 개념에 대해 살펴보았으니 이제 사이킷런에서 제공하는 GradientBoostingClassifier를 사용해 와인 데이터셋의 교차 검증 점수를 확인해보겠습니다.
거의 과대적합이 되지 않았습니다. 그레이디언트 부스팅은 결정 트리의 개수를 늘려도 과대적합에 매우 강합니다. 학습률을 증가시키고 트리의 개수를 늘리면 조금 더 성능이 향상될 수 있습니다.
결정 트리의 개수를 500개로 5배나 늘렸지만 과대적합을 잘 억제하고 있습니다. 학습률 learning_rate의 기본값은 0.1입니다. 그레이디언트 부스팅도 특성 중요도를 제공합니다. 결과에서 볼 수 있듯이 그레이디언트 부스팅은 랜덤 포레스트보다 일부 특성에 더 집중합니다.
재미있는 매개변수가 하나 있습니다. 트리 훈련에 사용할 subsample입니다. 이 매개변수의 기본값은 1.0으로 전체 훈련 세트를 사용합니다. 하지만 subsample이 1보다 작으면 훈련 세트의 일부를 사용합니다. 이는 마치 경사 하강법 단계마다 일부 샘플을 랜덤하게 선택하여 진행하는 확률적 경사 하강법 혹은 미니배치 경사 하강법과 비슷합니다.
일반적으로 그레이디언트 부스팅이 랜덤 포레스트보다 조금 더 높은 성능을 얻을 수 있습니다. 하지만 순서대로 트리르 추가가하기 때문에 훈련 속도가 느리다는 단점이 있습니다. 즉 GradientBoostingClassifier에는 n_jobs 매개변수가 없습니다. 그레이디언트 부스팅의 회귀 버전은 GradientBoostingRegression입니다. 그레이디언트 부스팅의 속도와 성능을 더욱 개선한 것이 다음에 나오는 히스토그램 기반 그레이디언트 부스팅입니다.
5. 히스토그램 기반 그레이디언트 부스팅
히스토그램 그레이디언트 부스팅은 정형 데이터를 다루는 머신러닝 알고리즘 중에 가장 인기가 높은 알고리즘입니다. 히스토그램 기반 그레이디언트 부스팅은 먼저 입력 특성을 256개의 구간으로 나눕니다. 따라서 노드를 분할할 때 최적의 분할을 매우 빠르게 찾을 수 있습니다. 히스토그램 기반 그레이디언트 부스팅은 256개의 구간 중에서 하나을 떼어 놓고 누락된 값을 위해서 사용합니다. 따라서 입력에 누락된 특성이 있더라고 이를 따로 전처리를 하지 않아도 됩니다.
사이킷런의 히스토그램 기반 그레이디언트 부스팅 클래스는 HistGradientBoostingClassifier입니다. 일반적으로 HistGradientBoostingClassifier는 기본 매개변수에서 안정적인 성능을 얻을 수 있습니다. HistGraidientBoostingClassifier에는 트리의 개수를 지정하는데 n_estimators 대신에 부스팅 반복 횟수를 지정하는 max_iter를 사용합니다. 성능을 높이려면 max_iter 매개변수를 테스트하는 것이 좋습니다.
이제 와인 데이터셋에 HistGradientBoostingClassifier 클래스를 적용해 보겠습니다.
결과를 보면 과대적합을 잘 억제하면서 그레디언트 부스팅보다 조금 더 높은 성능을 제공합니다. 특성 중요도를 확인해 보겠습니다.
히스토그램 기반 그레이디언트 부스팅의 특성 중요도를 계산하기 위해 permutation_importance()함수를 사용하겠습니다. 이 함수는 특성을 하나씩 랜덤하게 섞어서 모델의 성능이 변화하는지를 관찰하여 어떤 특성이 중요한지를 계산합니다. 훈련 세트뿐만 아니라 테스트 세트에도 적용할 수 있고 사이킷런에서 제공하는 추정기 모델에 모두 사용할 수도 있습니다.
먼저 히스토그램 기반 그레이디언트 부스팅 모델을 훈련하고 훈련 세트에서 특성 중요도를 계산해보겠습니다. n_repeats 매개변수는 랜덤하게 섞을 횟수를 의미합니다. 여기서는 10으로 지정했습니다. 기본값은 5입니다.
perutation_importance()함수가 반환하는 객체는 반복하여 얻은 특성 중요도, 평균, 표준편차를 담고 있습니다. 평균을 출력해보면 랜덤 포레스트와 비슷한 비율임을 알 수 있습니다. 이번에는 테스트 세트에서 특성 중요도를 계산해 보겠습니다.
테스트 세트의 결과를 보면 그레이디언트 부스팅과 비슷하게 조금 더 당도에 집중하고 있다는 것을 알 수 있습니다. 이런 분석을 통해 모델을 실전에 투입했을 때 어떤 특성에 관심을 둘지 예상할 수 있습니다.
그럼 HistGradientBoostingClassifier 를 사용해 테스트 세트에서의 성능을 최종적으로 확인해보겠습니다.
테스트 세트에서는 약 87% 정확도를 얻었습니다. 실전에 투입하면 성능은 이보다는 조금 더 낮을 것입니다. 앙상블 모델은 확실히 단일 결정 트리보다 좋은 결과를 얻을 수 있습니다.
히스토그램 기반 그레이디언트 부스팅의 회귀 버전은 HistGradientBoostingRegression 클래스에 구현되어 있습니다. 사이킷런에서 제공하는 히스토그램 기반 그레이디언트 부스팅은 비교적 새로운 기능에 속합니다. 하지만 사이킷런 외에도 그레이디언트 부스팅 알고리즘을 구현한 라이브러리도 존재합니다. 이는 XGBoost와 LightGBM 입니다.
XGBoost 도 역시 코랩에서 사용할 수 있을 뿐만 아니라 사이킷런의 cross_validate()함수와도 함께 사용할 수 있습니다. XGBoost는 다양한 부스팅 알고리즘을 지원합니다. tree_method 매개변수를 'hist'로 지정하면 히스토그램 기반 그레이디언트 부스팅을 사용할 수 있습니다. XGBoosting을 사용해 와인데이터의 교차검증 점수를 확인한 결과은 다음과 같습니다.
다음은 마이크로소프트에서 만든 LightGBM 입니다. LightGBM은 빠르고 최신 기술을 많이 적용하고 있어 인기가 점점 높아지는 라이브러리 중 하나입니다. LightGBM 역시 코랩에 이미 설치되어 있어 바로 테스트해 볼 수 있습니다.
이제 히스토그램 기반 그레이디언트 부스팅까지 4개의 앙상블을 모두 다루어 보았습니다 :)
6. 앙상블 학습을 통한 성능 향상
이번에는 앙상블 학습을 배웠습니다. 결정 트리 기반의 앙상블 학습은 강결하고 뛰어난 성능을 제공하기 때문에 인기가 아주 높습니다. 사이킷런에서 제공하는 앙상블 학습 알고리즘 중 랜덤 포레스트, 엑스트라 트리, 그레이디언트 부스팅, 히스토그램 기반 그레이디언트 부스팅을 다뤘습니다.
랜덤 포레스트는 가장 대표적인 앙상블 학습 알고리즘입니다. 성능이 좋고 안정적이기 때문에 첫 번째 시도로 시도해 볼 수있는 앙상블 학습 중 하나입니다. 랜덤 포레스트는 결정 트리를 훈련하기 위해 부스스트랩 샘플을 만들고 전체 특성 중 일부를 랜덤하게 선택하여 결정 트리를 만듭니다.
엑스트라 트리를 랜덤 포레스트와 매우 비슷하지만 부트스트랩 샘플을 사용하지 않고 노드를 분할할 때 최선이 아니라 랜덤하게 분할합니다. 이런 특징 때문에 랜덤 포레스트보다 훈련 속도가 빠르지만 보통 더 많은 트리가 필요합니다.
그레이디언트 부스팅은 깊이가 얕은 트리를 연속적으로 추가하여 손실 함수를 최소화하는 앙상블 방법입니다. 성능이 뛰어나지만 병렬로 훈련할 수 없기 때문에 랜덤 포레스트나 엑스트라 트리보다 훈련 속도가 조금 느립니다. 그레이디언트 부스팅에서 학습률 매개변수를 조정하여 모델의 복잡도를 제어할 수 있습니다. 학습률 매개변수가 크면 복잡하고 훈련 세트에 과대적합된 모델을 얻을 수 있습니다.
마지막으로 갖아 뒤어난 앙상블 학습으로 평가받는 히스토그램 기반 그레이디언트 부스팅 알고리즘을 살펴보았습니다. 히스토그램 기반 그레이디언트 부스팅은 훈련 데이터를 256개의 구간으로 변환하여 사용하기 때문에 노드 분할 속도가 매우 빠릅니다. 코랩에서는 사이킷런뿐만 아니라 히스토그램 기반 그레이디언트 부스팅 라이브러리인 XGBoost와 LightGBM이 이미 설치되어 있어 바로 시험해 볼 수 있습니다.
이렇게 다양한 앙상블 학습 방법을 배웠습니다. 앙상블 학습과 그리드 서치, 랜덤 서치를 사용한 하이퍼파라미터 튜닝을 사용하면 최고 수준의 성능을 내는 머신러닝 모델을 얻을 수 있었습니다.
Q. 확인 문제
다음은 아래 중 무엇에 관련된 설명인가요?
1. 전체 특성 중에 일부 특성을 랜덤하게 선택하여 사용함 2. 부트스트랩 샘플을 사용하지 않음 3. 빠른 계산 속도가 장점 |
① 랜덤 포레스트
② 엑스트라 트리
③ 그레이디언트 부스팅
④ XGBoost
⑤ LightLGB
A. 정답
옆을 드래그하면 정답이 나옵니다 :)
A : ② 엑스트라 트리