TOP
class="layout-aside-left paging-number">
본문 바로가기
[파이썬 Projects]/<파이썬 머신러닝>

[머신러닝] 회귀 트리

by 기록자_Recordian 2024. 10. 23.
728x90
반응형
이전 내용
 

[머신러닝] 로지스틱 회귀

이전 내용 [머신러닝] 회귀 - 규제 선형 모델: 릿지, 라쏘, 엘라스틱넷이전 내용 [머신러닝] 회귀 - 다항 회귀와 과대(과소) 적합이전 내용 [머신러닝] 회귀 - LinearRegression 클래스사이킷런 LinearReg

puppy-foot-it.tistory.com


회귀 트리

 

트리 기반의 회귀는 회귀 트리를 이용하는 것인데, 회귀를 위한 트리를 생성하고 이를 기반으로 회귀 예측을 하는 것이다.

 

[분류 트리와 회귀 트리의 차이]

분류 트리와 회귀 트리는 모두 기계 학습의 다양한 유형의 예측 작업에 사용되는 의사 결정 트리 유형이며, 주요 차이점은 다음과 같다.

1.출력 유형:

  • 분류 트리: 범주형 출력에 사용. 목표는 데이터를 사전 정의된 카테고리 또는 클래스로 분류하는 것이다. 예를 들어 이메일이 "스팸"인지 "스팸 아님"인지 결정하는 것은 분류 작업이다.
  • 회귀 트리: 연속 출력에 사용. 목표는 수치를 예측하는 것이다. 예를 들어 크기, 위치 등의 특성을 기반으로 주택 가격을 예측하는 것은 회귀 작업이다.

2. 결정 기준:

  • 분류 트리: 유사한 범주를 그룹화하여 노드의 순도를 높이는 것을 목표로 지니 계수 또는 엔트로피와 같은 측정값을 기반으로 데이터를 분할.
  • 회귀 트리: 평균 제곱 오차(MSE) 또는 기타 오류 감소 기준을 기반으로 데이터를 분할하고 예측 값과 실제 값 간의 차이를 최소화하는 데 중점.

3. 리프 노드: 예측 결정 값을 만드는 과정 차이

  • 분류 트리: 클래스 레이블 결정. 리프 노드에는 클래스 레이블(예: "스팸" 또는 "스팸 아님") 포함
  • 회귀 트리: 리프 노드에 속한 데이터 값의 평균값을 구해 회귀 예측값 계산하여 최종적으로 리프 노드에 결정 값으로 할당.

결정 트리, 랜덤 포레스트, GBM, XGBoost, LightGBM 등의 분류의 모든 트리 기반 알고리즘은 분류 뿐만 아니라 회귀도 가능한데, 이는 CART(Classification And Regression Trees)에 기반하고 있기 때문이다.

 

사이킷런에서는 결정 트리, 랜덤 포레스트, GBM에서 CART 기반의 회귀 수행을 할 수 있는 Estimator 클래스를 제공하며,

XGBoost, LightGBM도 사이킷런 래퍼 클래스를 통해 이를 제공한다.

알고리즘 회귀 Estimator 클래스 분류 Estimator 클래스
Decision Tree(결정 트리) DecisionTreeRegressor DecisionTreeClassifier
Gradient Boosting GradientBoostingRegressor GradientBoostingClassifier
XGBoost XGBRegressor XGBClassifier
LightGBM LGBMRegressor LGBMClassifier

 


랜덤포레스트를 이용한 보스턴 주택 가격 예측 수행

 

사이킷런의 랜덤 포레스트 회귀 트리인 RandomForestRegressor 를 이용해 보스턴 주택 가격 예측 수행

# 랜덤포레스트를 이용한 보스턴 주택 가격 예측 수행
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestRegressor
import numpy as np
import pandas as pd
from scipy import stats
from sklearn import datasets
import warnings
warnings.filterwarnings('ignore')

# boston 데이터 세트 로드
boston = datasets.fetch_openml('boston', return_X_y=True, as_frame=True)
bostonDF = pd.DataFrame(boston[0], columns=boston[0].columns)

# Categorical 데이터 타입을 numeric 타입으로 변환 (필요한 경우)
for col in bostonDF.columns:
    if pd.api.types.is_categorical_dtype(bostonDF[col]):
        bostonDF[col] = bostonDF[col].astype(float)

# boston 데이터 세트의 target 배열은 주택 가격임. 이를 PRICE 칼럼으로 DF에 추가함.
bostonDF['PRICE'] = boston[1]

# boston 데이터 세트의 target 배열
y_target = bostonDF['PRICE']
X_data = bostonDF.drop(['PRICE'], axis=1, inplace=False)

rf = RandomForestRegressor(random_state=0, n_estimators=1000)
neg_mse_scores = cross_val_score(rf, X_data, y_target, scoring="neg_mean_squared_error", cv=5)
rmse_scores = np.sqrt(-1 * neg_mse_scores)
avg_rmse = np.mean(rmse_scores)

print('5 교차 검증의 개별 Negative MSE scores: ',np.round(neg_mse_scores, 2))
print('5 교차 검증의 개별 RMSE scores: ',np.round(rmse_scores, 2))
print('5 교차 검증의 평균 RMSE : {0:.3f}'.format(avg_rmse))

 

[랜덤 포레스트, 결정 트리, GBM, XGBoost, LightGBM 모두 이용한 가격 예측]

입력 모델과 데이터 세트를 입력받아 교차 검증으로 평균 RMSE 를 계산해주는 get_model_cv_prediction() 함수를 만들어 수행

# 랜덤 포레스트, 결정 트리, GBM, XGBoost, LightGBM 모두 이용한 가격 예측
def get_model_cv_prediction(model, X_data, y_target):
    neg_mse_scores=cross_val_score(model, X_data, y_target, scoring="neg_mean_squared_error", cv=5)
    rmse_scores = np.sqrt(-1 * neg_mse_scores)
    avg_rmse = np.mean(rmse_scores)
    print('##### ', model.__class__.__name__, ' #####')
    print('5 교차 검증의 평균 RMSE : {0:.3f}'.format(avg_rmse))

# 다양한 회귀 트리 생성 및 예측
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import GradientBoostingRegressor
from xgboost import XGBRegressor
from lightgbm import LGBMRegressor

dt_reg = DecisionTreeRegressor(random_state=0, max_depth=4)
rf_reg = RandomForestRegressor(random_state=0, n_estimators=1000)
gb_reg = GradientBoostingRegressor(random_state=0, n_estimators=1000)
xgb_reg = XGBRegressor(n_estimators=1000)
lgb_reg = LGBMRegressor(n_estimators=1000)

# 트리 기반의 회귀 모델을 반복하면서 평가 수행
models = [dt_reg, rf_reg, gb_reg, xgb_reg, lgb_reg]
for model in models:
    get_model_cv_prediction(model, X_data, y_target)

 

[feature_importances_ 를 이용하여 피처별 중요도 시각화]

회귀 트리 Regressor 클래스는 선형 회귀아 다른 처리 방식이므로 회귀 계수를 측정하는 coef_ 속성이 없기 때문에 feature_importances_를 이용해 피처별 중요도를 시각화해 본다.

# feature_importances_ 를 이용하여 피처별 중요도 시각화
import seaborn as sns
%matplotlib inline

rf_reg = RandomForestRegressor(n_estimators=1000)

# 앞에서 만들어진 X_data, y_target 데이터 세트를 적용해 학습
rf_reg.fit(X_data, y_target)

features_series = pd.Series(data=rf_reg.feature_importances_, index=X_data.columns)
features_series = features_series.sort_values(ascending=False)
sns.barplot(x=features_series, y=features_series.index)

[회귀 트리 Regressor 의 예측값 판단 비교 - 선형 회귀와 비교]

결정 트리의 하이퍼 파라미터인 max_depth의 크기를 변화시키면서 어떻게 회귀 트리 예측선이 변화하는지 살펴본다.

Price와 가장 밀접한 양의 상관관계를 가지는 RM 칼럼만 이용해 선형 회귀와 결정 트리 회귀로 PRICE 예측 회귀선 표현.

▶ 데이터 세트의 개수를 100개만 샘플링하고 RM과 PRICE 칼럼만 추출하고 이 데이터 세트르 산점도 형태로 표현

# 회귀 트리 Regressor 의 예측값 판단 비교 - 선형 회귀와 비교
bostonDF_sample = bostonDF[['RM', 'PRICE']]
bostonDF_sample = bostonDF_sample.sample(n=100, random_state=0)
print(bostonDF_sample.shape)
plt.figure()
plt.scatter(bostonDF_sample.RM, bostonDF_sample.PRICE, c="darkorange")

 

◆ max_depth를 각각 2, 7로 해서 학습하고, 학습된 Regressor에 RM 값을 4.5 ~ 8.5까지의 100개 테스트 데이터 세트로 제공했을 때 예측값을 계산하고 Regressor에서 예측한 Price 회귀선 그리

import numpy as np
from sklearn.linear_model import LinearRegression

# 선형 회귀와 결정 트리 기반의 Regressor 생성. DecisionTreeRegressor 의 max_depth는 각각 2, 7
lr_reg = LinearRegression()
dt_reg2 =DecisionTreeRegressor(max_depth=2)
dt_reg7 =DecisionTreeRegressor(max_depth=7)

# 실제 예측을 적용할 테스트용 데이터 세트 4.5~8.5 까지 100개 데이터 세트로 생성
X_test = np.arange(4.5, 8.5, 0.04).reshape(-1, 1)

# 보스턴 주택 가격 데이터에서 시각화를 위해 피처는 RM만, 결정 데이터인 PRICE 추출
X_feature = bostonDF_sample['RM'].values.reshape(-1, 1)
y_target = bostonDF_sample['PRICE'].values.reshape(-1, 1)

# 학습과 예측 수행
lr_reg.fit(X_feature, y_target)
dt_reg2.fit(X_feature, y_target)
dt_reg7.fit(X_feature, y_target)

pred_lr = lr_reg.predict(X_test)
pred_dt2 = dt_reg2.predict(X_test)
pred_dt7 = dt_reg7.predict(X_test)

# price 회귀선 그리기
fig, (ax1, ax2, ax3) = plt.subplots(figsize=(14,4), ncols=3)

# X축 값을 4.5 ~ 8.5로 변환하며 입력했을 때 선형 회귀와 결정 트리 회귀 예측선 시각화
# 선형 회귀로 학습된 모델 회귀 예측선
ax1.set_title('Linear Regression')
ax1.scatter(bostonDF_sample.RM, bostonDF_sample.PRICE, c="darkorange")
ax1.plot(X_test, pred_lr, label="linear", linewidth=2)

# DecisionTreeRegressor의 max_depth를 2로 했을 때 회귀 예측선
ax2.set_title('Decision Tree Regression:\n max_depth=2')
ax2.scatter(bostonDF_sample.RM, bostonDF_sample.PRICE, c="darkorange")
ax2.plot(X_test, pred_dt2, label="max_depth:2", linewidth=2)

# DecisionTreeRegressor의 max_depth를 7로 했을 때 회귀 예측선
ax3.set_title('Decision Tree Regression:\n max_depth=7')
ax3.scatter(bostonDF_sample.RM, bostonDF_sample.PRICE, c="darkorange")
ax3.plot(X_test, pred_dt7, label="max_depth:3", linewidth=2)

 

선형 회귀는 직선으로 예측 회귀선을 표현하는 데 반해, 회귀 트리의 경우 분할되는 데이터 지점에 따라 브랜치를 만들면서 계단 형태로 회귀선을 만든다.

Decision Tree Regression의 max_depth=7인 경우, 학습 데이터 세트의 이상치(outlier)도 학습하면서 복잡한 계단 형태의 회귀선을 만들어 과적합이 되기 쉬운 모델이 되었다.


다음 내용

 

 


[출처]

파이썬 머신러닝 완벽 가이드

rpago.tistory.com
towards-ai 네이버 블로그
sanghyu.tistory.com
velog.io

728x90
반응형