728x90

회귀 트리

 

분류 트리의 경우 리프 노드를 통해 데이터들을 분할시키켰다면

 

회귀 트리는 해당 리프 노드에 속하는 데이터의 평균 값으로 추정값을 구함.

 

 

 

 

회귀 트리 모델로 보스턴 집값을 예측해보자

 

 

라이브러리 임포트

from sklearn.datasets import load_boston
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import GradientBoostingRegressor
from lightgbm import LGBMRegressor
import pandas as pd
import numpy as np
import seaborn as sns

 

 

간단하게 랜덤 포레스트 모델로 성능 평가

 

boston = load_boston()
df = pd.DataFrame(data=boston.data, columns=boston.feature_names)
df["PRICE"] = boston.target

y = df["PRICE"]
X = df.iloc[:,:-1]

rf = RandomForestRegressor()
neg_mse_scores = cross_val_score(rf, X, y, scoring="neg_mean_squared_error", cv =5)
rmse_scores = np.sqrt(-1 * neg_mse_scores)
avg_rmse = np.mean(rmse_scores)

print("negative mse scores : ", np.round(neg_mse_scores, 2))
print("rmse scores : ",np.round(rmse_scores, 2))
print("avg socres : ", np.round(avg_rmse))

 

 

 

성능 평가 함수 구현 후

 

타 트리 회귀 모델간 성능 비교

 

def get_model_cv_prediction(model, X, y):
    neg_mse_scores = cross_val_score(model, X, y, scoring="neg_mean_squared_error", cv =5)
    rmse_scores = np.sqrt(-1 * neg_mse_scores)
    avg_rmse = np.mean(rmse_scores)
    print("### {} ###".format(model.__class__.__name__))
    print("negative mse scores : ", np.round(neg_mse_scores, 2))
    print("rmse scores : ",np.round(rmse_scores, 2))
    print("avg socres : ", np.round(avg_rmse))
    


dt = DecisionTreeRegressor()
rf = RandomForestRegressor()
gb = GradientBoostingRegressor()
lgb = LGBMRegressor()


models = [dt, rf, gb, lgb]
for model in models:
    get_model_cv_prediction(model, X, y )

 

 

 

랜덤 포레스트 모델에서 중요한 특징 시각화

rf.fit(X, y)

feature_series = pd.Series(data=rf.feature_importances_,index=X.columns)
feature_series = feature_series.sort_values(ascending=False)
sns.barplot(x = feature_series, y=feature_series.index)

 

 

 

 

가장 중요한 변수인 RM을 단일 독립변수로 사용하여 종속 변수 PRICE 간에

 

최대 깊이에 따라 어떻게 회귀 예측 결과가 달라지는지 살펴보고,

 

선형 회귀와도 비교해보자

 

 

 

 

 

 

 

기본적으로

 

RM이 5 ~ 8사이 분포하며, PRICE는 3 ~ 50까지 다양하게 분포

 

from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt


df_sample = df[["RM","PRICE"]]
df_sample = df_sample.sample(n=100)

plt.scatter(df_sample.RM,df_sample.PRICE)

 

 

 

 

 

 

선형 회귀의 경우 데이터들을 직선 형태로 적합시키고 있으나

 

랜덤 포레스트 모델의 경우 트리의 깊이에 따라 속하는 분류의 평균 값으로 회귀

 

랜덤 포래스트 최대 깊이 2의 경우 값이 4개로 회귀

 

최대 깊이가 6인 경우 매우 복잡한 경우의 수들로 회귀하는 모습을 보임

 

 

lr = LinearRegression()
rf_dep2 = DecisionTreeRegressor(max_depth=2)
rf_dep6 = DecisionTreeRegressor(max_depth=6)


X_train = df["RM"].values.reshape(-1, 1)
y_train = df["PRICE"].values.reshape(-1, 1)

lr.fit(X_train, y_train)
rf_dep2.fit(X_train, y_train)
rf_dep6.fit(X_train, y_train)


X_test = np.linspace(5, 8, 100).reshape(-1, 1)

pred_lr = lr.predict(X_test)
pred_rf_dep2 = rf_dep2.predict(X_test)
pred_rf_dep6 = rf_dep6.predict(X_test)


fig, (ax1, ax2, ax3) = plt.subplots(figsize=(14, 4), ncols=3)

ax1.set_title("linear regression")
ax1.scatter(df_sample.RM,df_sample.PRICE)
ax1.plot(X_test, pred_lr)

ax2.set_title("RF depth 2")
ax2.scatter(df_sample.RM,df_sample.PRICE)
ax2.plot(X_test, pred_rf_dep2, color="red")

ax3.set_title("RF depth 6")
ax3.scatter(df_sample.RM,df_sample.PRICE)
ax3.plot(X_test, pred_rf_dep6, color="green")

 

 

300x250

+ Recent posts