
์์ ๊ฑฐ ๋์ฌ ์์คํ
โข ๋์ ์ ์ญ์ ํค์ค์คํฌ ์์น ๋คํธ์ํฌ๋ฅผ ํตํด ํ์๊ฐ์
,๋์ฌ ๋ฐ ์์ ๊ฑฐ ๋ฐํ ํ๋ก์ธ์ค๊ฐ ์๋ํ๋๋ ์์ ๊ฑฐ๋ฅผ ๋์ฌํ๋ ์๋จ
โข ์ ์ธ๊ณ 500๊ฐ ์ด์์ ์์ ๊ฑฐ ๋์ฌ ํ๋ก๊ทธ๋จ์ด ์์
=> ์์ ๊ฑฐ ๋์ฌ ์์คํ
์์ ์์ฑ๋ ๋ฐ์ดํฐ๋ ์ฌํ ๊ธฐ๊ฐ, ์ถ๋ฐ ์์น, ๋์ฐฉ ์์น ๋ฐ ๊ฒฝ๊ณผ ์๊ฐ์ด ๋ช
์์ ์ผ๋ก ๊ธฐ๋ก๋๊ธฐ ๋๋ฌธ์ ์ผ์ ๋คํธ์ํฌ๋ก์ ๊ธฐ๋ฅํ๋ฉฐ, ์ด๋ ๋์์ ์ด๋์ฑ์ ์ฐ๊ตฌํ๋ ๋ฐ ์ฌ์ฉ ๊ฐ๋ฅ

๋ชจ๋ธ์ ํ์ตํด ๋์ฌ ํ์(count)๋ฅผ ์์ธก


>> date ์นผ๋ผ๋ง objectํ
๋
/์/์ผ/์๊ฐ์ด 4๊ฐ ์์ฑ์ผ๋ก ๋ถ๋ฆฌ
# ๋ฌธ์์ด์ datetime ํ์
์ผ๋ก ๋ณ๊ฒฝ.
bike_df['datetime'] = bike_df.datetime.apply(pd.to_datetime)
# datetime ํ์
์์ ๋
, ์, ์ผ, ์๊ฐ ์ถ์ถ
bike_df['year'] = bike_df.datetime.apply(lambda x : x.year)
bike_df['month'] = bike_df.datetime.apply(lambda x : x.month)
bike_df['day'] = bike_df.datetime.apply(lambda x : x.day)
bike_df['hour'] = bike_df.datetime.apply(lambda x: x.hour)
bike_df.head(3)
casual + registered = count
์๊ด๋๊ฐ ๋์ ๋ ์นผ๋ผ์ ์์ธก์ ์ ํดํ ์ฐ๋ ค๊ฐ ์์ผ๋ฏ๋ก ๋ ์นผ๋ผ ์ญ์
(1) ์๊ฐํ
fig, axs = plt.subplots(figsize=(16, 8), ncols=4, nrows=2)
cat_features = ['year', 'month','season','weather','day', 'hour', 'holiday','workingday']
# cat_features์ ์๋ ๋ชจ๋ ์นผ๋ผ๋ณ๋ก ๊ฐ๋ณ ์นผ๋ผ๊ฐ์ ๋ฐ๋ฅธ count์ ํฉ์ barplot์ผ๋ก ์๊ฐํ
for i, feature in enumerate(cat_features):
row = int(i/4)
col = i%4
# ์๋ณธ์ barplot์ ์ด์ฉํด ์นผ๋ผ๊ฐ์ ๋ฐ๋ฅธ count์ ํฉ์ ํํ
sns.barplot(x=feature, y='count', data=bike_df, ax=axs[row][col])

(8๊ฐ ์นผ๋ผ๊ณผ count ์๊ด๊ด๊ณ ๊ทธ๋ํ)
year๋ณ count๋ฅผ ๋ณด๋ฉด ์๊ฐ์ด ์ง๋ ์๋ก ์์ฐ๊ฑฐ ๋์ฌ ํ์๊ฐ ์ฆ๊ฐํ๊ณ ์์์ ์ ์ ์์ / month์ ๊ฒฝ์ฐ 6, 7, 8, 9๊ฐ ๋์/ season์ ์ฌ๋ฆ, ๊ฐ์์ด ๋์ / weather์ ๋ง๊ฑฐ๋, ์๊ฐ๊ฐ ์๋ ๊ฒฝ์ฐ๊ฐ ๋์ / hour์ ๊ฒฝ์ฐ๋ ์ค์ ์ถ๊ทผ ์๊ฐ๊ณผ ์คํ ํด๊ทผ ์๊ฐ์ด ์๋์ ์ผ๋ก ๋์ / day๋ ์ฐจ์ด๊ฐ ํฌ์ง ์์ผ๋ฉฐ / holiday ๋๋ workingday๋ ์ฃผ์ค์ผ ๊ฒฝ์ฐ ์๋์ ์ผ๋ก ์ฝ๊ฐ ๋์.
๊ฐ ํ๊ท๋ชจ๋ธ๋ณ๋ก RMSLE ์ถ๋ ฅ (์์ ๊ฑฐ ๋ฐ์ดํฐ ์ธํธ์ ๊ฐ์ฅ ์ ํฉํ ํ๊ท๋ชจ๋ธ ์ฐพ๊ธฐ)
RMSLE(Root Mean Square Log Error)
1) outlier์ ๋ ๋ฏผ๊ฐํจ (outlier ๊ฐ ์๋๋ผ๋ ๊ฐ์ ๋ณ๋ํญ์ด ํฌ์ง ์์)
2) ์๋์ Error๋ฅผ ์ธก์ ํจ (๊ฐ์ ์ ๋์ ํฌ๊ธฐ๊ฐ ์ปค์ง๋ฉด RMSE์ ๊ฐ๋ ์ปค์ง์ง๋ง, RMSLE๋ ์๋์ ํฌ๊ธฐ๊ฐ ๋์ผํ๋ค๋ฉด RMSLE์ ๊ฐ๋ ๋์ผํจ)
3) Under Estimation์ ํฐ ํจ๋ํฐ๋ฅผ ๋ถ์ฌํจ
log1p()๋ฅผ ์ด์ฉํด ์ธ๋ํ๋ก์ฐ๋ฅผ ๋ฐฉ์งํ๋ค(expm1()ํจ์๋ก ๋ณต์ = exp(X)+1)
rmsle ๊ตฌํ ํจ์
from sklearn.metrics import mean_squared_error, mean_absolute_error
# log ๊ฐ ๋ณํ ์ NaN๋ฑ์ ์ด์๋ก log() ๊ฐ ์๋ log1p() ๋ฅผ ์ด์ฉํ์ฌ RMSLE ๊ณ์ฐ
def rmsle(y, pred):
log_y = np.log1p(y)
log_pred = np.log1p(pred)
squared_error = (log_y - log_pred) ** 2
rmsle = np.sqrt(np.mean(squared_error))
return rmsle
# ์ฌ์ดํท๋ฐ์ mean_square_error() ๋ฅผ ์ด์ฉํ์ฌ RMSE ๊ณ์ฐ
def rmse(y,pred):
return np.sqrt(mean_squared_error(y,pred))
# MSE, RMSE, RMSLE ๋ฅผ ๋ชจ๋ ๊ณ์ฐ
def evaluate_regr(y,pred):
rmsle_val = rmsle(y,pred)
rmse_val = rmse(y,pred)
# MAE ๋ scikit learn์ mean_absolute_error() ๋ก ๊ณ์ฐ
mae_val = mean_absolute_error(y,pred)
print('RMSLE: {0:.3f}, RMSE: {1:.3F}, MAE: {2:.3F}'.format(rmsle_val, rmse_val, mae_val))
def get_top_error_data(y_test, pred, n_tops = 5):
# DataFrame์ ์ปฌ๋ผ๋ค๋ก ์ค์ ๋์ฌํ์(count)์ ์์ธก ๊ฐ์ ์๋ก ๋น๊ต ํ ์ ์๋๋ก ์์ฑ.
result_df = pd.DataFrame(y_test.values, columns=['real_count'])
result_df['predicted_count']= np.round(pred)
result_df['diff'] = np.abs(result_df['real_count'] - result_df['predicted_count'])
# ์์ธก๊ฐ๊ณผ ์ค์ ๊ฐ์ด ๊ฐ์ฅ ํฐ ๋ฐ์ดํฐ ์์ผ๋ก ์ถ๋ ฅ.
print(result_df.sort_values('diff', ascending=False)[:n_tops])
get_top_error_data(y_test,pred,n_tops=5)
์์ธก ์ค๋ฅ๊ฐ ํฌ๋ค๋ ๊ฒ์ ํ์ธ ๊ฐ๋ฅ
โถ๏ธ Target ๊ฐ์ ๋ถํฌ๊ฐ ์๊ณก๋ ํํ์ธ์ง ๋จผ์ ํ์ธํ๊ธฐ(์ ๊ท๋ถํฌ๊ฐ best)

0~200 ์ฌ์ด์ ์๊ณก๋ผ ์์

//์ฌ๊ธฐ์ ๋ ์ ๊ท๋ถํฌ๋ก ๋ณํํ๋ ์์ ์ ์ถ๊ฐํด๋ ์ฑ๋ฅ์ด ํฅ์๋๋ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ ์์๋ฏ
year, hour, month ๋ฑ์ ์ซ์๊ฐ์ผ๋ก ํํ๋์์ง๋ง ๋ชจ๋ ์นดํ
๊ณ ๋ฆฌํ ํผ์ฒ
์ซ์ํ ์นดํ
๊ณ ๋ฆฌ ๊ฐ์ ์ ํํ๊ท์ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ด ์ซ์ํ ๊ฐ์ ํฌ๊ฒ ์ํฅ์ ๋ฐ์ผ๋ฉด ์๋๋ฏ๋ก ์-ํซ ์ธ์ฝ๋ฉ์ ์ ์ฉํด ๋ณํ
#'year', 'month', 'day', 'hour' ๋ฑ์ ํผ์ฒ๋ค์ One Hot Encoding
X_features_ohe = pd.get_dummies(X_features, columns =['year', 'month', 'day', 'hour', 'holiday',
'workingday', 'season', 'weather'])
# ์-ํซ ์ธ์ฝ๋ฉ์ด ์ ์ฉ๋ ํผ์ฒ ๋ฐ์ดํฐ ์ธํธ ๊ธฐ๋ฐ์ผ๋ก ํ์ต/์์ธก ๋ฐ์ดํฐ ๋ถํ
X_train, X_test, y_train, y_test = train_test_split(X_features_ohe, y_target_log,
test_size =0.3, random_state=0)
# ๋ชจ๋ธ๊ณผ ํ์ต/ํ
์คํธ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ์
๋ ฅํ๋ฉด ์ฑ๋ฅ ํ๊ฐ ์์น๋ฅผ ๋ฐํ
def get_model_predict(model, X_train, X_test, y_train, y_test, is_expm1=False):
model.fit(X_train, y_train)
pred = model.predict(X_test)
if is_expm1:
y_test = np.expm1(y_test)
pred = np.expm1(pred)
print('###', model.__class__.__name__, '###')
evaluate_regr(y_test, pred)
#end of function get_model_predict
# ๋ชจ๋ธ๋ณ๋ก ํ๊ฐ ์ํ
lr_reg = LinearRegression()
ridge_reg = Ridge(alpha=10)
lasso_reg = Lasso(alpha = 0.01)
for model in [lr_reg, ridge_reg, lasso_reg]:
get_model_predict(model, X_train, X_test, y_train, y_test, is_expm1=True)
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from xgboost import XGBRegressor
from lightgbm import LGBMRegressor
#๋๋ค ํฌ๋ ์คํธ ,GBM , XGBoos(t, LightGBM model๋ณ๋ก ํ๊ฐ ์ํ
rf_reg = RandomForestRegressor(n_estimators=500)
gbm_reg = GradientBoostingRegressor(n_estimators=500)
xgb_reg = XGBRegressor(n_estimators = 500)
lgbm_reg = LGBMRegressor(n_estimators = 500)
for model in [rf_reg, gbm_reg, xgb_reg, lgbm_reg]:
#XGBoost์ ๊ฒฝ์ฐ DataFrame์ด ์
๋ ฅ๋ ๊ฒฝ์ฐ ๋ฒ์ ์ ๋ฐ๋ผ ์ค๋ฅ ๋ฐ์ ๊ฐ๋ฅ. ndarray๋ก ๋ณํ.
get_model_predict(model, X_train.values, X_test.values, y_train.values,
y_test.values, is_expm1=True)
์ฃผํ ๊ฐ๊ฒฉ ์์ธก
79๊ฐ์ ์ค๋ช
๋ณ์๊ฐ ๋ฏธ๊ตญ ์์ด์ค์ ์ฃผ์ ์์์ค์ ์๋ ์ฃผ๊ฑฐ์ฉ ์ฃผํ์ ๊ฑฐ์ ๋ชจ๋ ์ธก๋ณ์ ์ค๋ช
ํจ.
=> ๋ํ๋ ์ด๋ฅผ ์ด์ฉํด ๊ฐ ์ฃผํ์ ์ต์ข
๊ฐ๊ฒฉ์ ์์ธกํ๋ ๋ฐ ๋์ ํจ.

House Price - Advanced Regression Techniques


Target ๊ฐ์ SalePrice. 80๊ฐ ํผ์ฒ ์ค 43๊ฐ๊ฐ ๋ฌธ์ํ์ด๋ฉฐ Null๊ฐ์ด ๋ง์ ํผ์ฒ๋ ์กด์ฌ. (PoolQC, MiscFeature, Alley, Fence 1000๊ฐ๊ฐ ๋๋ ๋ฐ์ดํฐ๊ฐ Null)
plt.title('Original Sale Price Histogram')
plt.xticks(rotation=45)
sns.histplot(house_df['SalePrice'], kde=True)
plt.show()

ํ๊น ๋ฐ์ดํฐ ๊ฐ์ด ์ค์ฌ์์ ์ผ์ชฝ์ผ๋ก ์น์ฐ์น ํํ๋ก ์ ๊ท๋ถํฌ์์ ๋ฒ์ด๋ ์์.
log1p()๋ก ๋ก๊ทธ๋ณํ ํ ๋ค์ ๊ฒฐ๊ด๊ฐ์ expm1()๋ก ํ์ํ๋ฉด ๋จ.
plt.title('Log Transformed Sale Price Histogram')
log_SalePrice = np.log1p(house_df['SalePrice'])
sns.histplot(log_SalePrice, kde=True)
plt.show()
์ดํด๊ฐ ์๋จ. ๋ค์ ๋ณต๊ทํ๋ฉด ์๋ณธ์ด๋ ๋๊ฐ์์ ธ์ ์๋ฏธ ์์ด์ง๋ ๊ฑฐ ์๋?
์๋ณ ๐ฌ
ํ๋ จํ ๋๋ง ๋ก๊ทธ ๋ณํ์ ์ ์ฉํจ. ๊ทธ๋ฆฌ๊ณ ๊ณ์ ์ฒ๋ฆฌํ ๋ฐ์ดํฐ๋ ์๋ ์ค์ผ์ผ๋ก ๋ณต๊ทํ๊ธฐ
ํ๋ จํ ๋๋ง ์ ๊ทํ ๋ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฉํ๊ธฐ
PoolQC, MiscFeature, Alley, Fence, FireplaceQu ์ญ์
๋๋จธ์ง Nullํผ์ฒ๋ ์ซ์ํ์ ๊ฒฝ์ฐ ํ๊ท ๊ฐ์ผ๋ก ๋์ฒด
# SalePrice ๋ก๊ทธ ๋ณํ
original_SalePrice = house_df['SalePrice']
house_df['SalePrice'] = np.log1p(house_df['SalePrice'])
# Null ์ด ๋๋ฌด ๋ง์ ์ปฌ๋ผ๋ค๊ณผ ๋ถํ์ํ ์ปฌ๋ผ ์ญ์
house_df.drop(['Id','PoolQC' , 'MiscFeature', 'Alley', 'Fence','FireplaceQu'], axis=1 , inplace=True)
# Drop ํ์ง ์๋ ์ซ์ํ Null์ปฌ๋ผ๋ค์ ํ๊ท ๊ฐ์ผ๋ก ๋์ฒด
house_df['LotFrontage'].fillna(house_df['LotFrontage'].mean(),inplace=True)
house_df['MasVnrArea'].fillna(house_df['MasVnrArea'].mean(),inplace=True)
house_df['GarageYrBlt'].fillna(house_df['GarageYrBlt'].mean(),inplace=True)
# LotFrontage , MasVnrArea, GarageYrBlt has null
# Null ๊ฐ์ด ์๋ ํผ์ฒ๋ช
๊ณผ ํ์
์ ์ถ์ถ
null_column_count = house_df.isnull().sum()[house_df.isnull().sum() > 0]
print('## Null ํผ์ฒ์ Type :\n', house_df.dtypes[null_column_count.index])
์ฑ ์์ ์๋ฌ ๋ฐ์ํ๋ ๋ถ๋ถ ์์
get_dummies()๋ ์๋์ผ๋ก ๋ฌธ์์ด ํผ์ฒ๋ฅผ ์-ํซ ์ธ์ฝ๋ฉ ๋ณํํ๋ฉด์ Null ๊ฐ์ 0์ผ๋ก ๋ณํ, ๋ณ๋์ Null ๊ฐ์ ๋์ฒดํ๋ ๋ก์ง์ด ํ์ ์์.
ํ๊น๊ฐ์ธ SalePrice ๋ก๊ทธ ๋ณํ, ์์ธก๊ฐ ๋ก๊ทธ ๋ณํ๋ SalePrice ๊ฐ์ ๊ธฐ๋ฐ์ผ๋ก ์์ธกํ๋ฏ๋ก ์๋ณธ SalePrice ์์ธก๊ฐ์ ๋ก๊ทธ ๋ณํ ๊ฐ
>> ๋ฐ๋ผ์ ์์ธก ๊ฒฐ๊ณผ ์ค๋ฅ์ RMSE๋ง ์ ์ฉ ํ๋ฉด RMSLE๊ฐ ์๋์ผ๋ก ์ธก์
def get_rmse(model):
pred = model.predict(X_test)
mse = mean_squared_error(y_test, pred)
rmse = np.sqrt(mse)
print(model.__class__.__name__, '๋ก๊ทธ ๋ณํ๋ RMSE:', np.round(rmse, 3))
return rmse
from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
y_target = house_df_ohe['SalePrice']
X_features = house_df_ohe.drop('SalePrice',axis=1, inplace=False)
X_train, X_test, y_train, y_test = train_test_split(X_features, y_target, test_size=0.2, random_state=156)
# LinearRegression, Ridge, Lasso ํ์ต, ์์ธก, ํ๊ฐ
lr_reg = LinearRegression()
lr_reg.fit(X_train, y_train)
ridge_reg = Ridge()
ridge_reg.fit(X_train, y_train)
lasso_reg = Lasso()
lasso_reg.fit(X_train, y_train)
models = [lr_reg, ridge_reg, lasso_reg]
get_rmses(models)
[Output]
LinearRegression ๋ก๊ทธ ๋ณํ๋ RMSE: 0.01
Ridge ๋ก๊ทธ ๋ณํ๋ RMSE: 0.01
Lasso ๋ก๊ทธ ๋ณํ๋ RMSE: 0.018
[0.010481899993240616, 0.00997580081727205, 0.01795924469011489]
>> ๋ผ์ ํ๊ท์ ๊ฒฝ์ฐ ๋ง์ด ๋จ์ด์ง๋ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์
ํ๊ท ๊ณ์ ๊ฐ์ ์์ 10๊ฐ, ํ์ 10๊ฐ์ ํผ์ฒ์ ๋ํ ๋ง๋ ๊ทธ๋ํ ์ถ๋ ฅ

๋ผ์์ ์ ์ฒด์ ํ๊ท ๊ณ์๊ฐ์ด ๋งค์ฐ ์๊ณ , YearBuilt๊ฐ ๊ฐ์ฅ ํฌ๊ณ ๋ค๋ฅธ ํผ์ฒ์ ํ๊ท ๊ณ์๋ ๋๋ฌด ์์.
1. ํ์ต ๋ฐ์ดํฐ ๋ถํ ๋ฐฉ์ ๊ฐ์
5๊ฐ ๊ต์ฐจ ๊ฒ์ฆ ํด๋ ์ธํธ๋ก ํ๋ จ์ธํธ ๋ถํ
from sklearn.model_selection import cross_val_score
def get_avg_rmse_cv(models):
for model in models:
#๋ถํ ํ์ง ์๊ณ ์ ์ฒด ๋ฐ์ดํฐ๋ก cross_val_score() ์ํ. ๋ชจ๋ธ๋ณ CV RMSE๊ฐ๊ณผ ํ๊ท RMSE ์ถ๋ ฅ
rmse_list = np.sqrt(-cross_val_score(model, X_features, y_target,
scoring="neg_mean_squared_error", cv=5))
rmse_avg = np.mean(rmse_list)
print('\n{0} CV RMSE ๊ฐ ๋ฆฌ์คํธ: {1}'.format(model.__class__.__name__, np.round(rmse_list, 3)))
print('{0} CV ํ๊ท RMSE ๊ฐ: {1}'.format(model.__class__.__name__, np.round(rmse_avg, 3)))
# ์ ์์ ์์ ํ์ตํ ridge_reg, lasso_reg ๋ชจ๋ธ์ CV RMSE ๊ฐ ์ถ๋ ฅ
models = [ridge_reg, lasso_reg]
get_avg_rmse_cv(models)
2. ๋ฆฟ์ง์ ๋ผ์ ๋ชจ๋ธ์ ๋ํ ์ต์ alpha ํ์ดํผํ๋ผ๋ฏธํฐ ์ฐพ๊ธฐ
from sklearn.model_selection import GridSearchCV
def print_best_params(model, params):
grid_model = GridSearchCV(model, param_grid = params,
scoring = 'neg_mean_squared_error', cv=5)
grid_model.fit(X_features, y_target)
rmse = np.sqrt(-1*grid_model.best_score_)
print('{0} 5 CV ์ ์ต์ ํ๊ท RMSE ๊ฐ:{1}, ์ต์ alpha: {2}'.format(model.__class__.__name__,
np.round(rmse, 4), grid_model.best_params_))
ridge_params = {'alpha':[0.05, 0.1, 1, 5, 8, 10, 12, 15, 20]}
lasso_params = {'alpha': [0.001, 0.005, 0.008, 0.05, 0.03, 0.1, 0.5, 1, 5, 10]}
print_best_params(ridge_reg, ridge_params)
print_best_params(lasso_reg, lasso_params)
์ต์ alpha ๊ฐ์ผ๋ก ๋ชจ๋ธ์ ํ์ต/์์ธก/ํ๊ฐ๋ฅผ ์ฌ์ํ
1. ํผ์ฒ ๋ฐ์ดํฐ ์ธํธ์ ๋ฐ์ดํฐ ๋ถํฌ
ํผ์ฒ ๋ฐ์ดํฐ ์ธํธ์ ์ง๋์น๊ฒ ์๊ณก๋ ํผ์ฒ๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ ํ๊ท ์์ธก ์ฑ๋ฅ์ ์ ํ์ํฌ ์ ์์
skew()
skewness(์๋), ๋ฐ์ดํฐ ๋ถํฌ์ ๋น๋์นญ ์ ๋๋ฅผ ๋ณด์ฌ์ฃผ๋ ์์น
์๋ 1์ด์์ ๊ฐ์ ๋ฐํํ๋ ํผ์ฒ๋ง ์ถ์ถํด ์๊ณก ์ ๋๋ฅผ ์ํํ๊ธฐ ์ํด ๋ก๊ทธ ๋ณํ์ ์ ์ฉ. ์ซ์ํ ํผ์ฒ์ ์นผ๋ผ index ๊ฐ์ฒด๋ฅผ ์ถ์ถํด ์ซ์ํ ์นผ๋ผ ๋ฐ์ดํฐ ์ธํธ์ apply lambda์ skew()๋ฅผ ํธ์ถํด ์ซ์ํ ํผ์ฒ์ ์๊ณก ์ ๋ ์ถ๋ ฅ
from scipy.stats import skew
# object๊ฐ ์๋ ์ซ์ํ ํผ์ฒ์ ์นผ๋ผ index ๊ฐ์ฒด ์ถ์ถ.
features_index = house_df.dtypes[house_df.dtypes != 'object'].index
# house_df์ ์นผ๋ผ index๋ฅผ [ ]๋ก ์
๋ ฅํ๋ฉด ํด๋นํ๋ ์นผ๋ผ ๋ฐ์ดํฐ ์ธํธ ๋ฐํ. apply lambda๋ก skew( ) ํธ์ถ
skew_features = house_df[features_index].apply(lambda x : skew(x))
# skew(์๊ณก) ์ ๋๊ฐ 1 ์ด์์ธ ์นผ๋ผ๋ง ์ถ์ถ.
skew_features_top = skew_features[skew_features > 1]
print(skew_features_top.sort_values(ascending=False))
โ๏ธ ์-ํซ ์ธ์ฝ๋ฉ ์นดํ ๊ณ ๋ฆฌ ์ซ์ํ ํผ์ฒ๋ ์ ์ธ - ์ธ์ฝ๋ฉ ์ ๋น์ฐํ ์๊ณก๋ ๊ฐ๋ฅ์ฑ ํผ
์ถ์ถ๋ ์๊ณก ์ ๋๊ฐ ๋์ ํผ์ฒ๋ฅผ ๋ก๊ทธ๋ณํ
house_df[skew_features_top.index] = np.log1p(house_df[skew_features_top.index])
2. ์ด์์น ๋ฐ์ดํฐ
3๊ฐ ๋ชจ๋ธ์์ ๋ชจ๋ ๊ฐ์ฅ ํฐ ํ๊ท ๊ณ์ GrLivArea ํผ์ฒ์ ๋ฐ์ดํฐ ๋ถํฌ ๋ถ์

outlier ๋ฐ์ดํฐ๋ก ๊ฐ์ฃผํ๊ณ ์ ๋ถ ์ญ์
(๋จ ๋ชจ๋ ๋ก๊ทธ ๋ณํ๋ ๋ฐ์ดํฐ์ด๋ฏ๋ก ์ด๋ฅผ ๋ฐ์ํด ์ด์์น ๋ฐ์ดํฐ๋ก ๋ถ๋ฅํด์ผ ๋จ -> log1p(x)๋ก ์ ํ)
# GrLivArea์ SalePrice ๋ชจ๋ ๋ก๊ทธ ๋ณํ๋์์ผ๋ฏ๋ก ์ด๋ฅผ ๋ฐ์ํ ์กฐ๊ฑด ์์ฑ.
cond1 = house_df_ohe['GrLivArea'] > np.log1p(4000)
cond2 = house_df_ohe['SalePrice'] < np.log1p(500000)
outlier_index = house_df_ohe[cond1 & cond2].index
"๋จธ์ ๋ฌ๋ ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฉํ๊ธฐ ์ด์ ์ ์๋ฒฝํ๊ฒ ๋ฐ์ดํฐ์ ์ ์ฒ๋ฆฌ ์์ ์ ์ํํ๋ผ๋ ์๋ฏธ๋ ์๋๋๋ค. ์ผ๋จ ๋๋ต์ ๋ฐ์ดํฐ ๊ฐ๊ณต๊ณผ ๋ชจ๋ธ ์ต์ ํ๋ฅผ ์ํํ ๋ค ๋ค์ ์ด์ ๊ธฐ๋ฐํ ์ฌ๋ฌ ๊ฐ์ง ๊ธฐ๋ฒ์ ๋ฐ์ดํฐ ๊ฐ๊ณต๊ณผ ํ์ดํผ ํ๋ผ๋ฏธํฐ ๊ธฐ๋ฐ์ ๋ชจ๋ธ ์ต์ ํ๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ์ํํ๋ ๊ฒ์ด ๋ฐ๋์งํ ๋ชจ๋ธ ์์ฑ ๊ณผ์ " (p.390, ํ์ด์ฌ ๋จธ์ ๋ฌ๋ ์๋ฒฝ ๊ฐ์ด๋)
๊ฐ๋ณ ํ๊ท ๋ชจ๋ธ์ ์์ธก ๊ฒฐ๊ด๊ฐ์ ํผํฉํด ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ต์ข
ํ๊ท ๊ฐ์ ์์ธก
โข ์๋ก ๋ค๋ฅธ ๋ชจ๋ธ์ ์์ธก๊ฐ์ ํฉ์ณ๋ ๋จ!
- A๋ชจ๋ธ๊ณผ B ๋ชจ๋ธ, ๋ ๋ชจ๋ธ์ ์์ธก๊ฐ์ด ์๋ค๋ฉด A๋ชจ๋ธ ์์ธก ๊ฐ์ 40%, B ๋ชจ๋ธ ์์ธก๊ฐ์ 60%๋ฅผ ๋ํด์ ์ต์ข
ํ๊ท ๊ฐ์ผ๋ก ์์ธกํ๋ ๊ฒ
Ex) A ํ๊ท ๋ชจ๋ธ ์์ธก๊ฐ [100. 80, 60]
B ํ๊ท ๋ชจ๋ธ ์์ธก๊ฐ [120. 80, 50]
์ต์ข
ํ๊ท ์์ธก๊ฐ : [100*0.4 + 120*0.6, 80*0.4 + 80*0.6, 60*0.4 + 50*0.6] = [112, 80, 54]
pred = 0.4 * ridge_pred + 0.6 * lasso_pred
๊ฐ ๋ชจ๋ธ์ ์์ธก๊ฐ์ ๊ณ์ฐํ ๋ค ๊ฐ๋ณ ๋ชจ๋ธ๊ณผ ์ต์ข ํผํฉ ๋ชจ๋ธ์ RMSE ๊ตฌํ๊ธฐ
def get_rmse_pred(preds):
for key in preds.keys():
pred_value = preds[key]
mse = mean_squared_error(y_test , pred_value)
rmse = np.sqrt(mse)
print('{0} ๋ชจ๋ธ์ RMSE: {1}'.format(key, rmse))
# ๊ฐ๋ณ ๋ชจ๋ธ์ ํ์ต
ridge_reg = Ridge(alpha=8)
ridge_reg.fit(X_train, y_train)
lasso_reg = Lasso(alpha=0.001)
lasso_reg.fit(X_train, y_train)
# ๊ฐ๋ณ ๋ชจ๋ธ ์์ธก
ridge_pred = ridge_reg.predict(X_test)
lasso_pred = lasso_reg.predict(X_test)
# ๊ฐ๋ณ ๋ชจ๋ธ ์์ธก๊ฐ ํผํฉ์ผ๋ก ์ต์ข
์์ธก๊ฐ ๋์ถ
pred = 0.4 * ridge_pred + 0.6 * lasso_pred
preds = {'์ต์ข
ํผํฉ': pred,
'Ridge': ridge_pred,
'Lasso': lasso_pred}
#์ต์ข
ํผํฉ ๋ชจ๋ธ, ๊ฐ๋ณ๋ชจ๋ธ์ RMSE ๊ฐ ์ถ๋ ฅ
get_rmse_pred(preds)
๋ถ๋ฅ์์ ๋ฐฐ์ด ์คํํน ์์๋ธ ํ๋๋ ๊ธฐ์ต๋์ง ์๋๋ค...
2๊ฐ์ง ๋ชจ๋ธ ํ์, ๊ฐ๋ณ์ ์ธ ๊ธฐ๋ฐ ๋ชจ๋ธ๊ณผ ์ด ๊ฐ๋ณ ๊ธฐ๋ฐ ๋ชจ๋ธ์ ์์ธก ๋ฐ์ดํฐ๋ฅผ ํ์ต ๋ฐ์ดํฐ๋ก ๋ง๋ค์ด์ ํ์ตํ๋ ์ต์ข ๋ฉํ ๋ชจ๋ธ
from sklearn.model_selection import KFold
from sklearn.metrics import mean_absolute_error
# ๊ฐ๋ณ ๊ธฐ๋ฐ ๋ชจ๋ธ์์ ์ต์ข
๋ฉํ ๋ชจ๋ธ์ด ์ฌ์ฉํ ํ์ต ๋ฐ ํ
์คํธ์ฉ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๊ธฐ ์ํ ํจ์.
def get_stacking_base_datasets(model, X_train_n, y_train_n, X_test_n, n_folds ):
# ์ง์ ๋ n_folds๊ฐ์ผ๋ก KFold ์์ฑ.
kf = KFold(n_splits=n_folds, shuffle=False)
#์ถํ์ ๋ฉํ ๋ชจ๋ธ์ด ์ฌ์ฉํ ํ์ต ๋ฐ์ดํฐ ๋ฐํ์ ์ํ ๋ํ์ด ๋ฐฐ์ด ์ด๊ธฐํ
train_fold_pred = np.zeros((X_train_n.shape[0] ,1 ))
test_pred = np.zeros((X_test_n.shape[0],n_folds))
print(model.__class__.__name__ , ' model ์์ ')
for folder_counter , (train_index, valid_index) in enumerate(kf.split(X_train_n)):
#์
๋ ฅ๋ ํ์ต ๋ฐ์ดํฐ์์ ๊ธฐ๋ฐ ๋ชจ๋ธ์ด ํ์ต/์์ธกํ ํด๋ ๋ฐ์ดํฐ ์
์ถ์ถ
print('\t ํด๋ ์ธํธ: ',folder_counter,' ์์ ')
X_tr = X_train_n[train_index]
y_tr = y_train_n[train_index]
X_te = X_train_n[valid_index]
#ํด๋ ์ธํธ ๋ด๋ถ์์ ๋ค์ ๋ง๋ค์ด์ง ํ์ต ๋ฐ์ดํฐ๋ก ๊ธฐ๋ฐ ๋ชจ๋ธ์ ํ์ต ์ํ.
model.fit(X_tr , y_tr)
#ํด๋ ์ธํธ ๋ด๋ถ์์ ๋ค์ ๋ง๋ค์ด์ง ๊ฒ์ฆ ๋ฐ์ดํฐ๋ก ๊ธฐ๋ฐ ๋ชจ๋ธ ์์ธก ํ ๋ฐ์ดํฐ ์ ์ฅ.
train_fold_pred[valid_index, :] = model.predict(X_te).reshape(-1,1)
#์
๋ ฅ๋ ์๋ณธ ํ
์คํธ ๋ฐ์ดํฐ๋ฅผ ํด๋ ์ธํธ๋ด ํ์ต๋ ๊ธฐ๋ฐ ๋ชจ๋ธ์์ ์์ธก ํ ๋ฐ์ดํฐ ์ ์ฅ.
test_pred[:, folder_counter] = model.predict(X_test_n)
# ํด๋ ์ธํธ ๋ด์์ ์๋ณธ ํ
์คํธ ๋ฐ์ดํฐ๋ฅผ ์์ธกํ ๋ฐ์ดํฐ๋ฅผ ํ๊ท ํ์ฌ ํ
์คํธ ๋ฐ์ดํฐ๋ก ์์ฑ
test_pred_mean = np.mean(test_pred, axis=1).reshape(-1,1)
#train_fold_pred๋ ์ต์ข
๋ฉํ ๋ชจ๋ธ์ด ์ฌ์ฉํ๋ ํ์ต ๋ฐ์ดํฐ, test_pred_mean์ ํ
์คํธ ๋ฐ์ดํฐ
return train_fold_pred , test_pred_mean
ํจ์ ๋ด์์๋ ๊ฐ๋ณ ๋ชจ๋ธ์ด K-fold ์ธํธ๋ก ์ค์ ๋ ํด๋ ์ธํธ ๋ด๋ถ์์ ์๋ณธ์ ํ์ต ๋ฐ์ดํฐ๋ฅผ ๋ค์ ์ถ์ถํด ํ์ต๊ณผ ์์ธก์ ์ํํ ๋ค ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํฉ๋๋ค. ์ ์ฅ๋ ์์ธก ๋ฐ์ดํฐ๋ ์ถํ์ ๋ฉํ ๋ชจ๋ธ์ ํ์ต ํผ์ฒ ๋ฐ์ดํฐ ์ธํธ๋ก ์ด์ฉ๋ฉ๋๋ค. ํจ์ ๋ด์์ ํด๋ ์ธํธ ๋ด๋ถ ํ์ต ๋ฐ์ดํฐ๋ก ํ์ต๋ ๊ฐ๋ณ ๋ชจ๋ธ์ด ์ธ์๋ก ์ ๋ ฅ๋ ์๋ณธ ํ ์คํธ ๋ฐ์ดํฐ๋ฅผ ์์ธกํ ๋ค, ์์ธก ๊ฒฐ๊ณผ๋ฅผ ํ๊ท ํด ํ ์คํธ ๋ฐ์ดํฐ๋ก ์์ฑ
# ๊ฐ๋ณ ๋ชจ๋ธ์ด ๋ฐํํ ํ์ต ๋ฐ ํ
์คํธ์ฉ ๋ฐ์ดํฐ ์ธํธ๋ฅผ Stacking ํํ๋ก ๊ฒฐํฉ.
Stack_final_X_train = np.concatenate((ridge_train, lasso_train,
xgb_train, lgbm_train), axis=1)
Stack_final_X_test = np.concatenate((ridge_test, lasso_test,
xgb_test, lgbm_test), axis=1)
# ์ต์ข
๋ฉํ ๋ชจ๋ธ์ ๋ผ์ ๋ชจ๋ธ์ ์ ์ฉ.
meta_model_lasso = Lasso(alpha=0.0005)
#๊ธฐ๋ฐ ๋ชจ๋ธ์ ์์ธก๊ฐ์ ๊ธฐ๋ฐ์ผ๋ก ์๋กญ๊ฒ ๋ง๋ค์ด์ง ํ์ต ๋ฐ ํ
์คํธ์ฉ ๋ฐ์ดํฐ๋ก ์์ธกํ๊ณ RMSE ์ธก์ .
meta_model_lasso.fit(Stack_final_X_train, y_train)
final = meta_model_lasso.predict(Stack_final_X_test)
mse = mean_squared_error(y_test , final)
rmse = np.sqrt(mse)
print('์คํํน ํ๊ท ๋ชจ๋ธ์ ์ต์ข
RMSE ๊ฐ์:', rmse)
๊ฐ์ธ ๋ณดํ๋ฃ ์์ธก
์ฌ๋ฌ feature์ ๊ฐ์ง ์ฌ๋์ ๋ณดํ๋ฃ๋ฅผ ์์ธก (age, sex, bmi, children, smoker, region)
=> ์๋ฃ๋ณดํ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํด ํ ์ฌ๋์ด ๋ณดํ๋ฃ๋ฅผ ์ผ๋ง๋ ๋ผ์ง๋ฅผ ์์ธกํ๋ ํ๊ท ๋ฌธ์
๋ถ์ ๋ฐฉ๋ฒ

Age: ํผ๋ณดํ์์ ๋์ด
Sex: ํผ๋ณดํ์์ ์ฑ๋ณ
BMI: ํผ๋ณดํ์์ ์ฒด์ง๋ ์ง์
Children: ํผ๋ณดํ์์ ์๋
์ ์
Smoker: ํก์ฐ ์ฌ๋ถ (yes / no)
Region: ํผ๋ณดํ์๊ฐ ๊ฑฐ์ฃผํ๋ ์ง์ญ (Southeast / Southwest / Northeast / Northwest)
Charges: ๋ณดํ๋ฃ


ํผ์ฒ๋ค์ ๋ถํฌ ํ์ธ

(์ ๊ฐ์ ์ฌํญ๋ค์ ์๊ฐํด๋ณผ ์ ์์ -> ์ฐจ์ฐจ ๊ณ ๋ คํด๋ณผ ๊ฒ!)
์๊ด๊ด๊ณ
๋ ๋ณ์ ์ฌ์ด ์๊ด๊ด๊ณ ์ ๋๋ฅผ ๋ํ๋ด๋ ์์น
๋ ๋ณ์์ ๋ํ ์ฐ์ ๋์์ ์ ๋ค์ด ์ผ๋ง๋ ์ง์ ์ ๊ฐ๊น์ด๊ฐ์ ์ ๋๋ฅผ ๋ํ๋ด๋ ๋ฐ ์ฐ์ด๋ ์ฒ๋
(ํฐ ์๊ด๊ณ์ ๊ฐ์ด ํญ์ ๋ ๋ณ์ ์ฌ์ด ์ด๋ค ์ธ๊ณผ๊ด๊ณ๋ฅผ ์๋ฏธํ์ง ์์

age ํผ์ฒ์ charges ํผ์ฒ์ ์๊ด๊ด๊ณ ๊ณ์ ๋์ >> ๊ทธ๋ํ์์ ์ง์ ํ์ผ๋ก ๋งค์ฐ ๋๋ ทํจ
age ํผ์ฒ์ ๋ํ ๊ฐ์ ์ด โบ ์ ์ฒด ๋ชจ๋ธ์ ๊ฐ์ ์ผ๋ก ์ด์ด์ง!!
# ์ฐ๋ น๋ณ ๊ตฌ๊ฐ ์ค์
bins = [0, 20, 25, 30, 35, 40, 45, 50, 55, 60, np.inf]
age_bin = pd.cut(df['age'], bins=bins, labels=[i+1 for i in range(len(bins)-1)])
# len(bins)
# age_bin
df['age_bin'] = age_bin
df.head()
๋ถ๋ฅ ์ธ์ ์์ ๋ฐฐ์ ๋ box plot์ผ๋ก ์ด์์น๋ฅผ ํ์ธํด๋ณด์๋ฉด

bmi ์ด์์น ์์!! bmi ์ด์์น ์ ๊ฑฐ ํ์~!
๊ทธ๋ผ ์ด์์น๋ฅผ ์ด๋ป๊ฒ ์ ๊ฑฐํ๋๋?
์ ๋ช
ํ ์ด์์น ์ ๊ฑฐ ๊ธฐ๋ฒ
# IQR(Q3 - Q1)๋ก๋ถํฐ ์ด์์น ํ์
ํ๊ธฐ
bmi_q1 = df['bmi'].quantile(q=0.25)
bmi_q3 = df['bmi'].quantile(q=0.75)
iqr = bmi_q3 - bmi_q1
# (q1 - (iqr * 1.5))์ (q3 + (iqr * 1.5))๋ฅผ ๋ฒ์ด๋ ๊ฐ์ด ์ด์์น
condi1 = (df['bmi'] < (bmi_q1 - (1.5 * iqr)))
condi2 = (df['bmi'] > (bmi_q3 + (1.5 * iqr)))
outliers = df[condi1 | condi2]
outliers['bmi']


//ppt ์ ์๊ถ์ ์ ํํ ์์ต๋๋น~
#์ซ์ํ ๋ณ์์ ๋ํด Box-Cox transformation, Quantile transformation, ๊ทธ๋ฆฌ๊ณ ๋ก๊ทธ ๋ณํ
#Scaling
to_scale = ['age', 'bmi', 'children', 'charges']
df_to_scale = df[to_scale].copy()
quantile = QuantileTransformer(n_quantiles=100, random_state=42, output_distribution='normal') #1000๊ฐ ๋ถ์๋ฅผ ์ฌ์ฉํด ๋ฐ์ดํฐ๋ฅผ ๊ท ๋ฑ๋ถํฌ
power = PowerTransformer(method= 'yeo-johnson') #๋ฐ์ดํฐ์ ํน์ฑ๋ณ๋ก ์ ๊ท๋ถํฌํํ์ ๊ฐ๊น๋๋ก ๋ณํ
q_scaled = quantile.fit_transform(df_to_scale)
yj = power.fit_transform(df_to_scale)
q_scaled_df = pd.DataFrame(q_scaled, columns=to_scale)
scaled_df = pd.DataFrame(yj, columns=to_scale)
logged_df = pd.DataFrame(np.log1p(df_to_scale), columns=to_scale)
fig, ax = plt.subplots(4, 4, figsize=(40, 30))
for i in range(4):
idx = 0
for j in range(4): #subplot๋ค์ ์ด
colname = to_scale[idx]
if i == 0 :
ax[i][j].hist(df_to_scale[colname], bins = 30)
ax[i][j].set_xlabel(colname)
ax[i][j].set_ylabel('Frequency')
elif i == 1:
ax[i][j].hist(scaled_df[colname], bins = 30)
ax[i][j].set_xlabel(colname)
ax[i][j].set_ylabel('Transformed Frequency')
elif i == 2:
ax[i][j].hist(q_scaled_df[colname], bins = 30)
ax[i][j].set_xlabel(colname)
ax[i][j].set_ylabel('Transformed Frequency')
elif i == 3:
ax[i][j].hist(logged_df[colname], bins = 30)
ax[i][j].set_xlabel(colname)
ax[i][j].set_ylabel('Logged Frequency')
idx += 1

Target๊ฐ๊ณผ BMI๊ฐ ๊ฐ์ฅ ์ ๊ท๋ถํฌํ๋ QuantileTransformer๋ชจ๋ธ ์ ํ!
QuantileTransformer์ ์ด์ฉํด ํ๋ จ ์ธํธ, ํ ์คํธ ์ธํธ ์ฌ์ฒ๋ฆฌ
#Quantile Transformation
to_scale = ['age', 'bmi']
quantile = QuantileTransformer(n_quantiles=10, random_state=0, output_distribution='normal')
for col in to_scale:
quantile.fit(X_train[[col]])
X_train[col] = quantile.transform(X_train[[col]]).flatten()
X_test[col] = quantile.transform(X_test[[col]]).flatten()
์ด๋ BMI ํผ์ฒ๋ง ์ค์ผ์ผ์ ๋ณํํ์ผ๋ฏ๋ก ๋ค๋ฅธ ํผ์ฒ๋ค์ ๋จ์ ๋ถํฌ๋ฅผ BMI์ ๋ง์ถฐ์ฃผ๊ธฐ ์ํด standard scaling๋ ์งํ
์นดํ
๊ณ ๋ฆฌ ํผ์ฒ(๋ฌธ์์ด ํผ์ฒ)๋ฅผ ์ ์ํ์ผ๋ก ๋ณํ
/> sex, region, smoker ํผ์ฒ ๋ณํ ํ์

๋ง์ ํ๊ท ๋ชจ๋ธ๋ค์ ์ ์ฉํด ์ด๋ค ๋ชจ๋ธ์ด ๊ฐ์ฅ ์ฑ๋ฅ์ด ์ข์์ง๋ฅผ ํ๋จํ์!
# default ๋ชจ๋ธ์ ์ค์ ํ ๋ค, cross-validation์ ํตํด ์ฑ๋ฅ์ ํ๊ฐ
lr = LinearRegression()
enet = ElasticNet(random_state=42)
dt = DecisionTreeRegressor(random_state=42)
rf = RandomForestRegressor(random_state=42)
ada = AdaBoostRegressor(random_state=42)
gbr = GradientBoostingRegressor(random_state=42)
xgb = XGBRegressor(random_state=42)
lgbm = LGBMRegressor(random_state=42)
models = [lr, enet, dt, rf, ada, gbr, xgb, lgbm]
# ํ๊ฐ์งํ RMSE
for model in models:
name = model.__class__.__name__
scores = cross_val_score(model, X=X_train, y=y_train, cv=5, scoring='neg_mean_squared_error', n_jobs=-1)
mse = (-1) * np.mean(scores) # negative mean squared error๋ก ์ค์ ํ์ผ๋ฏ๋ก -1์ ๊ณฑํด ๋ถํธ๋ฅผ ๋ง์ถฐ์ค๋๋ค.
print('Model %s - RMSE: %.4f' % (name, np.sqrt(mse)))
[Output]
Model LinearRegression - RMSE: 6415.7267
Model ElasticNet - RMSE: 9609.0652
Model DecisionTreeRegressor - RMSE: 6377.2354
Model RandomForestRegressor - RMSE: 4917.3047
Model AdaBoostRegressor - RMSE: 5211.7117
Model GradientBoostingRegressor - RMSE: 4695.0703
Model XGBRegressor - RMSE: 5302.2534
Model LGBMRegressor - RMSE: 4827.5845
Gradient Boosting Regressor, LightGBM, Random Forest ํ์ดํผํ๋ผ๋ฏธํฐ ํ๋
