본문 바로가기
Minding's Programming/Kaggle and Dacon

[Kaggle] House Prices Prediction : 보스턴 주택가격 예측 - 2. Modeling & Prediction

by Minding 2021. 4. 14.
728x90
반응형

[파이썬 라이브러리를 활용한 머신러닝] 책을 공부하던 때 처음 접해보았던

머신러닝 회귀 문제의 대표문제, Kaggle의 House Prices 예측 데이터셋을 다시 한번 살펴보는 시간을 가졌다.

 

데이터셋은 Kaggle에서 다운로드 가능하다.

www.kaggle.com/c/house-prices-advanced-regression-techniques

 

House Prices - Advanced Regression Techniques

Predict sales prices and practice feature engineering, RFs, and gradient boosting

www.kaggle.com

처음 공부 할 당시에는 tensorflow를 활용한 선형회귀만을 다루었는데, 이번에는 앙상블 기법을 통해 접근해보았다.

 

앙상블 기법을 활용한 모델링 및 예측 모델은 Kaggle의 munmun2004님의 커널을 참고했다.

www.kaggle.com/munmun2004/house-prices-for-begginers

 

[한글커널][House Prices]보스턴 집값 예측 for Begginers

Explore and run machine learning code with Kaggle Notebooks | Using data from House Prices - Advanced Regression Techniques

www.kaggle.com


데이터 처리 EDA와 Feature Engineering는

[Kaggle] House Prices Prediction : 보스턴 주택가격 예측 - 1. EDA & Feature Engineering 에서 다루었다.

 

 

모델링 하기 전, 학습에 쓸 train dataset과 검증에 쓸 test dataset을 나누어 준다.

또한, train dataset에 주택가격인 price를 합쳐주고, 학습과정에서 필요하지 않은 칼럼을 drop해준다.

train_df = df[:train.shape[0]]
test_df = df[train.shape[0]:]
train_df = pd.concat([train_df, price], axis=1, sort=False)

# 학습 과정에서 필요없는 변수 drop
train_df = train_df.drop(['SalePrice', 'Id'], axis=1) # log변환을 한 price가 있기 때문
test_df = test_df.drop(['Id'], axis=1)

 

 

3. 학습 모델링

 

3-1. 모델 임포트

from sklearn.model_selection import KFold, cross_val_score, GridSearchCV
from sklearn.metrics import mean_squared_error
from sklearn.pipeline import make_pipeline
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from xgboost import XGBRegressor
from lightgbm import LGBMRegressor
from sklearn.linear_model import ElasticNet, Lasso, LinearRegression

 

3-2. RobustScaler

중앙값과 IQR(사분면도) 이용하여 아웃라이어의 영향을 최소화하도록 한다.

from sklearn.preprocessing import RobustScaler

rbst_scaler=RobustScaler()
X_rbst=rbst_scaler.fit_transform(train_df)
test_rbst=rbst_scaler.transform(test_df)

 

3-3. KFold 검증

데이터가 적을경우, train dataset이 제대로 학습되었는지 확인할 validation set이 부족해 학습검증이 어렵다.

이럴 때 데이터를 k개로 나누어 돌아가며 학습, 검증을 하는 방식인 KFold검증 방식을 통해 학습에 쓸 모델을 정한다.

from sklearn.model_selection import GridSearchCV, cross_val_score, StratifiedKFold

kfold = KFold(n_splits=4)

random_state = 1
reg = []

reg.append(Lasso(random_state = random_state))
reg.append(ElasticNet(random_state = random_state))
reg.append(RandomForestRegressor(random_state=random_state))
reg.append(GradientBoostingRegressor(random_state=random_state))
reg.append(XGBRegressor(silent=True,random_state=random_state))
reg.append(LGBMRegressor(verbose_eval=False,random_state = random_state))

# print(reg)

reg_results = []

for regre in reg :
    reg_results.append(np.mean(np.sqrt(-cross_val_score(regre, X_rbst, y = price,scoring = 'neg_mean_squared_error',
                                       cv = kfold, n_jobs=-4))))
reg_means = []
reg_std = []
for reg_result in reg_results:
    reg_means.append(reg_result.mean())
    reg_std.append(reg_result.std())
reg_re = pd.DataFrame({"CrossValMeans":reg_means,"CrossValerrors": reg_std})
reg_re

Cross_val_score의 평균값인 CrossValMeans값을 비교하여 사용할 모델을 선정한다.

앙상블 기법을 사용할 것이기 때문에 수치가 낮은 순대로 3개의 모델을 골랐다. (Gradient Boosting, Lightbgm, XGBoost)

그러나, XGBoost의 파라미터튜닝에 있어 문제가 생겨 RandomForestRegressor를 사용했다. (추후에 다시 시도해 보아야겠다ㅜ)

 

3-4. GridSearchCV

사용자가 지정한 하이퍼파라미터의 조합 중 최상의 효과를 보여주는 조합을 알려주는 GridSearch를 사용하였다.

# Gradient boosting 파라미터 튜닝
GBC = GradientBoostingRegressor()
gb_param_grid = {'n_estimators' : [100,200,300],
              'learning_rate': [0.1, 0.05, 0.01],
              'max_depth': [4, 8],
              'min_samples_leaf': [100,150],
              'max_features': [0.3, 0.1] 
              }
gsGBC = GridSearchCV(GBC,param_grid = gb_param_grid, cv=kfold, scoring="neg_mean_squared_error", n_jobs= 4, verbose = 1)
gsGBC.fit(X_rbst,price)
GBC_best = gsGBC.best_estimator_

# 최고 점수
gsGBC.best_score_

>>>
Fitting 4 folds for each of 72 candidates, totalling 288 fits
[Parallel(n_jobs=4)]: Using backend LokyBackend with 4 concurrent workers.
[Parallel(n_jobs=4)]: Done  42 tasks      | elapsed:    3.1s
[Parallel(n_jobs=4)]: Done 192 tasks      | elapsed:   12.4s
[Parallel(n_jobs=4)]: Done 288 out of 288 | elapsed:   18.0s finished
-0.016817684583404532
GBC_best

>>>
GradientBoostingRegressor(alpha=0.9, ccp_alpha=0.0, criterion='friedman_mse',
                          init=None, learning_rate=0.05, loss='ls', max_depth=8,
                          max_features=0.1, max_leaf_nodes=None,
                          min_impurity_decrease=0.0, min_impurity_split=None,
                          min_samples_leaf=100, min_samples_split=2,
                          min_weight_fraction_leaf=0.0, n_estimators=300,
                          n_iter_no_change=None, presort='deprecated',
                          random_state=None, subsample=1.0, tol=0.0001,
                          validation_fraction=0.1, verbose=0, warm_start=False)

 

#LGBMClassifier 파라미터 튜닝
LGB = LGBMRegressor()
lgb_param_grid = {
    'num_leaves' : [1,5,10],
    'learning_rate': [1,0.1,0.01,0.001],
    'n_estimators': [50, 100, 200, 500, 1000,5000], 
    'max_depth': [15,20,25],
    'num_leaves': [50, 100, 200],
    'min_split_gain': [0.3, 0.4]
}
gsLGB = GridSearchCV(LGB,param_grid = lgb_param_grid, cv=kfold, scoring="neg_mean_squared_error", n_jobs= 4, verbose = 1)
gsLGB.fit(X_rbst,price)
LGB_best = gsLGB.best_estimator_

# 최고 점수
gsLGB.best_score_

>>>
Fitting 4 folds for each of 432 candidates, totalling 1728 fits
[Parallel(n_jobs=4)]: Using backend LokyBackend with 4 concurrent workers.
[Parallel(n_jobs=4)]: Done  92 tasks      | elapsed:    1.6s
[Parallel(n_jobs=4)]: Done 692 tasks      | elapsed:   17.6s
[Parallel(n_jobs=4)]: Done 1236 tasks      | elapsed:   43.3s
[Parallel(n_jobs=4)]: Done 1648 tasks      | elapsed:  1.6min
[Parallel(n_jobs=4)]: Done 1728 out of 1728 | elapsed:  1.9min finished
-0.018979949885224997
LGB_best

>>>
LGBMRegressor(boosting_type='gbdt', class_weight=None, colsample_bytree=1.0,
              importance_type='split', learning_rate=0.1, max_depth=15,
              min_child_samples=20, min_child_weight=0.001, min_split_gain=0.3,
              n_estimators=50, n_jobs=-1, num_leaves=50, objective=None,
              random_state=None, reg_alpha=0.0, reg_lambda=0.0, silent=True,
              subsample=1.0, subsample_for_bin=200000, subsample_freq=0)

 

#RandomForest 파라미터 튜닝
RF = RandomForestRegressor()
rf_param_grid = {
        'n_estimators' : [1,10, 100],
           'max_depth' : [6, 8, 10, 12],
           'min_samples_leaf' : [8, 12, 18],
           'min_samples_split' : [8, 16, 20]
}
gsRF = GridSearchCV(RF,param_grid = rf_param_grid, cv=kfold, scoring="neg_mean_squared_error", n_jobs= 4, verbose = 1)
gsRF.fit(X_rbst,price)
RF_best = gsRF.best_estimator_

# 최고 점수
gsRF.best_score_

>>>
Fitting 4 folds for each of 108 candidates, totalling 432 fits
[Parallel(n_jobs=4)]: Using backend LokyBackend with 4 concurrent workers.
[Parallel(n_jobs=4)]: Done 128 tasks      | elapsed:    6.5s
[Parallel(n_jobs=4)]: Done 320 tasks      | elapsed:   17.9s
[Parallel(n_jobs=4)]: Done 432 out of 432 | elapsed:   24.8s finished
-0.020608555225522757
RF_best

>>>
RandomForestRegressor(bootstrap=True, ccp_alpha=0.0, criterion='mse',
                      max_depth=12, max_features='auto', max_leaf_nodes=None,
                      max_samples=None, min_impurity_decrease=0.0,
                      min_impurity_split=None, min_samples_leaf=8,
                      min_samples_split=8, min_weight_fraction_leaf=0.0,
                      n_estimators=100, n_jobs=None, oob_score=False,
                      random_state=None, verbose=0, warm_start=False)

 

 

4. Prediction (예측)

 

4-1. Voting

앙상블 기법 중 하나인 Voting기법은 여러 모델의 결과값을 투표방식을 통해 최종 예측값을 산출해내는 방식이다.

from sklearn.ensemble import VotingRegressor

votingC = VotingRegressor(estimators=[('LGB', LGB_best), ('GBC',GBC_best), ('RF', RF_best)], n_jobs=4)
votingC = votingC.fit(X_rbst, price)
# test 데이터에 대해 예측
test_SalePrice = pd.Series(votingC.predict(test_rbst), name="SalePrice")

최종 예측값들을 제출할 csv에 저장하기 전에, Id와 SalePrice항목을 지수변환으로 바꾸어주어야 한다. (로그변환을 했기때문!)

submission = pd.DataFrame({
    "Id" :test['Id'],
    "SalePrice": np.expm1(test_SalePrice)
})


submission.to_csv('voting.csv', index=False)

 

4-2. Stacking

Stacking 기법은 각 모델들의 예측값을 meta data로 모은 다음, 그 데이터를 통해 최종 예측값을 도출해내는 방식이다.

from mlxtend.regressor import StackingRegressor
from sklearn.linear_model import LogisticRegression
from sklearn.utils.testing import ignore_warnings

params = {'meta_regressor__C': [0.1, 1.0, 10.0, 100.0],
          'use_features_in_secondary' : [True, False]}

clf1 = LGB_best
clf2 = GBC_best
clf3 = RF_best

lr = LogisticRegression()
st_re= StackingRegressor(regressors=[clf1, clf2, clf3], meta_regressor=RandomForestRegressor())
st_mod = st_re.fit(X_rbst, price)
st_pred = st_mod.predict(test_rbst)
submission = pd.DataFrame({
    "Id" :test['Id'],
    "SalePrice": np.expm1(st_pred)
})
submission.head()
submission.to_csv('stacking.csv', index=False)

 


최종 스코어는 Voting기법을 사용했을 때 0.13510, Stacking기법을 사용했을 때 0.13757을 기록했다.

 

참고했던 munmun2004님의 커널과 비교하니, Data handling과정에서 꼼꼼함이 부족했던 것 같다.

 

다음은 Dacon의 랜드마크 사진 분류를 시도해볼 예정이다.

728x90
반응형

댓글