일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 의사결정나무
- post pruning
- Adaboost
- 경사하강법
- 회귀분석
- 체인지업후기
- 부스팅
- LeastSquare
- 사후 가지치기
- cost complexity pruning
- 중선형회귀
- AdaBoostClassifier
- 최소제곱법
- 아다부스트
- KNearestNeighbors
- 선형회귀
- pre pruning
- gradientdescent
- MultipleLinearRegression
- 실제데이터활용
- C4.5
- 부스팅기법
- 사전 가지치기
- 캘리포니아주택가격예측
- boosting
- AdaBoostRegressor
- 군집화기법
- LinearRegression
- 선형모형
- 정보이득
- Today
- Total
데이터 분석을 향한 발자취 남기기
[Boosting] AdaBoost Regressor 본문
지난번 AdaBoost 알고리즘을 분류에 대해서 공부해보았다. 이번 장에서는 AdaBoost를 회귀에 적용하는 알고리즘에 대해서 알아보고자 한다.
AdaBoost Classifier 관련 정리 ↓
https://footprints-toward-data-analysis.tistory.com/11
[Boosting] AdaBoost Classifier
Boosting의 대표적인 알고리즘인 AdaBoost 알고리즘에 대해서 알아보고자 한다. AdaBoost는 분류와 회귀 문제에 모두 사용할 수 있는 앙상블 모델로 오늘은 분류 문제를 다뤄보고자 한다. 1. AdaBoost Classi
footprints-toward-data-analysis.tistory.com
1. AdaBoost Regressor Algorithm
2. Simple example
3. Sklearn AdaBoost Regressor 비교
1. AdaBoost Regressor Algorithm
분류와 동일하게 회귀에서도 매번 데이터의 가중치를 수정하면서 weak learner들을 학습한다. 이때, 분류기가 잘못 분류한 데이터의 가중치는 증가시키고 잘 분류한 데이터의 가중치는 감소시킨다. 이를 통해, 다음 weak learner가 예측하기 어려운 데이터에 집중할 수 있도록 한다.
AdaBoost Regressor Algorithm은 다음과 같다.
* weak learner
일반적으로 Decision Tree Regressor(max_depth = 3)를 사용하며, 그외 Linear Regression이나 Support Vector Regression을 사용하기도 한다.
2. Simple example
AdaBoost Regressor 알고리즘에 대해 예제를 이용하여 이해해보고자 한다. 다음 그림과 같이 50개의 simulation 데이터를 생성하였다.

- $t = 1$
50개 데이터에 대해서, 초기 가중치는 모두 동일하게 $w_1(i) = \frac{1}{50} = 0.02, i = 1, \cdots, 50$로 설정한다.

설정한 가중치 $w_1(i)$를 이용해 훈련 데이터와 동일한 크기인 50개 샘플 데이터를 선택한다. 이를 이용해 회귀 모델을 훈련하고 전체 훈련 데이터에 대한 예측값을 비교하였다. 이때, 회귀 모델로 Decision Tree Regressor (max_depth = 4)를 사용하였다.

생성된 예측값을 이용해 각 데이터에 대한 손실을 계산한다. 이때 손실 값$L_{t}^{(i)}$은 $D_{t}$로 인해 $0 \leq L_{t}^{(i) } \leq 1$에 존재한다. 아래 그래프를 통해, 손실값이 예측값과 실제값 차이 절댓값을 0과 1사이 값으로 변환되어 계산되었음을 볼 수 있다.
이제 이를 이용해 평균 손실 $\bar{L}_{1}$과 $\beta_{1}$를 계산한다.
손실이 더 큰 예제는 상대적으로 더 큰 가중치를 부여하고 손실이 작은 예제는 상대적으로 작은 가중치를 부여하여 가중치를 업데이트한다. 이를 통해, 샘플 데이터 $D_{2}$를 생성할 때, 손실이 컸던 예제들이 더 많이 선택될 수 있도록 한다.
위 그림을 보면 손실의 분포에 따라 가중치가 부여되었음을 볼 수 있다.
이러한 작업을 총 10번 반복하면 10개의 회귀모델이 생성된다. 동일한 작업이므로 이를 생략하고, 이를 결합하여 어떻게 예측하는지 자세히 알아보고자 한다.
- Step3. 각 테스트 데이터에 대해 예측값을 생성하고 가중 중앙값으로 계산한다.
위 식을 이용해, 이해하기에 조금 어려워 예제를 통해서 정리하려고 한다.
만약, (x, y) = (1.2244898, 1.7469284)로 주어졌다고 가정하자. 그러면, 먼저 생성한 10개 회귀분석기를 이용해 예측값을 생성한다. 생성된 10개 예측값을 작은 값부터 차례대로 나열한다. 최종 예측 시, 훈련을 통해 각 모델에 대해 구한 가중치 $\beta$를 이용한다!! $\frac{1}{2}\sum_{t=1}^{10}\beta$를 계산하여, 이보다 누적 합이 처음으로 커지는 지점이 바로 가중 중앙값이다. 이를 이용해 최종 예측한다.
즉, 5.360835보다 큰 $\beta$ 누적합을 갖는 모델은 10번, 4번, 1번, 3번, 9번이다. 이 중 누적 합이 처음으로 5.360835보다 커지는 지점은 10번째 모델이므로 이 모델의 예측값으로 최종 예측한다.
→ (x, y) = (1.2244898, 1.7469284) 의 예측값: 1.83813
3. Sklearn AdaBoost Regressor 비교
직접 짠 AdaBoost 회귀 모델(Hand)과 sklearn의 AdaBoostRegressor를 비교해보려고 한다.
트리의 깊이는 4, 생성할 총 트리의 개수는 10으로 주고 예측했을 때, 결과는 다음과 같다.
그 결과, 두 모델 모두 데이터의 분포를 잘 따르고 있음을 볼 수 있다. 특히, Hand가 Sklearn에 비해 MAE, RMSE 측면에서 더 좋은 성능을 보였음을 알 수 있다.
AdaBoost Regressor 훈련 및 성능 비교 코드 ↓
import numpy as np
from sklearn.ensemble import AdaBoostRegressor
from sklearn.tree import DecisionTreeRegressor
import matplotlib.pyplot as plt
from sklearn.metrics import mean_absolute_error, mean_squared_error
import pandas as pd
from collections import Counter
'''
AdaBoost 훈련
'''
# 데이터
rng = np.random.RandomState(123)
X = np.linspace(0, 6, 50)[:, np.newaxis]
y = np.sin(X).ravel()+np.sin(6*X).ravel() + rng.normal(0, 0.1, X.shape[0])
# 트리 개수, 깊이 설정
T, tree_depth = 10, 4
# 가중치 초기화
w = [1/len(y) for i in range(len(X))]
confi_list = []
model_list = []
np.random.seed(123)
for i in range(T):
# w 확률에 따라 훈련 데이터로부터 샘플 데이터 인덱스 추출
train_sample_idx = np.random.choice(range(len(y)), size = len(y), replace = True, p = w)
train_sample = X[train_sample_idx]
train_sample_y = y[train_sample_idx]
# 회귀모델 훈련
weak_learner = DecisionTreeRegressor(max_depth = tree_depth).fit(train_sample, train_sample_y)
# 기존 훈련 데이터에 대한 예측값 생성
train_sample_pred = weak_learner.predict(X)
# 관찰 오류 계산
abs_diff = abs(y - train_sample_pred)
D = max(abs_diff)
loss = abs_diff/D
# 모델 오류 계산
mean_loss = np.sum(loss * w)
if mean_loss >= 0.5:
i = i-1
break
# 베타 계산
confidence = mean_loss/(1-mean_loss)
# 가중치 업데이트
w = w * confidence**(1-loss)
w = w/sum(w)
model_list.append(weak_learner)
confi_list.append(np.log(1/(confidence)))
confi_list = np.array(confi_list)
def adaboost_pred (pred, weight):
sort_pred = np.sort(pred, axis = 1)
# 예측값 정렬 순서
sort_idx = np.argsort(pred, axis = 1)
# 예측값의 가중치 정렬
pred_confi = np.array(confi_list)[sort_idx]
total = np.sum(pred_confi, axis = 1)[0]
# 가중 중앙값의 위치 담기
j_idx_list = []
for i in pred_confi:
sum_j = 0
for j_idx, j in enumerate(i):
sum_j += j
if sum_j >= 0.5 * total:
j_idx_list.append(j_idx)
break
# 가중 중앙값으로 예측
fin_pred_list = [x[xi] for x, xi in zip(sort_pred, j_idx_list)]
return fin_pred_list
# 데이터에 대한 각 회귀모델의 예측값
train_pred = np.array([x.predict(X) for x in model_list]).T
# 최종 예측값
hand_train_pred = adaboost_pred(train_pred, confi_list)
'''
Sklearn vs Hand
'''
# sklearn 모델 생성
sk_ada = AdaBoostRegressor(DecisionTreeRegressor(max_depth = tree_depth), n_estimators = T, random_state = 123).fit(X, y)
sk_pred = sk_ada.predict(X)
plt.figure()
plt.scatter(X, y)
plt.plot(X, hand_train_pred, color = "black", label = "Hand")
plt.plot(X, sk_pred, color = "red", label = "Sklearn")
plt.legend()
plt.tight_layout()
print("sklearn", "MAE:", round(mean_absolute_error(y, sk_pred), 3), "RMSE:", round(mean_squared_error(y, sk_pred, squared = False), 3))
print("hand", "MAE:", round(mean_absolute_error(y, hand_train_pred), 3), "RMSE:", round(mean_squared_error(y, hand_train_pred, squared = False), 3))
오늘은 AdaBoost를 회귀문제에 어떻게 적용하는지 알아보았다. 손실이나 최종 예측 부분에서 분류와 조금 다르지만 전체적인 과정은 매우 비슷함을 알 수 있다. 다음에는 AdaBoost 분류 문제를 실제 데이터에 적용하고 이에 대한 코드에 대해 정리하고자 한다.
'손으로 직접 해보는 모델정리 > 앙상블 모델' 카테고리의 다른 글
[Boosting] Gradient Boosting Regressor (0) | 2023.04.28 |
---|---|
[Boosting] AdaBoost Classifier with Citrus (0) | 2023.04.12 |
[Boosting] AdaBoost Classifier (0) | 2023.03.24 |
앙상블 학습 방법 (0) | 2023.03.24 |