KaggleのHouse Prices CompetitionをXGBoostで解く

machinelearning

以前TitanicをやったXGBoostでHome Prices Competitionに挑戦する。

KaggleのTitanicのチュートリアルをXGBoostで解く - sambaiz-net

import pandas as pd
df_train = pd.read_csv('house-prices/train.csv')
df_test= pd.read_csv('house-prices/test.csv')

前処理

目的変数であるSalePriceと相関のある変数を抽出する。XGBoostは欠損値をそのまま扱うことができるので特に何もしていない。

KaggleのHome Prices CompetitionのKernelからデータの探り方を学ぶ - sambaiz-net

use_columns = df_train.corr()['SalePrice'].drop('SalePrice').where(lambda x: abs(x) > 0.5).dropna().keys()
# Index(['OverallQual', 'YearBuilt', 'YearRemodAdd', 'TotalBsmtSF', '1stFlrSF', 'GrLivArea', 'FullBath', 'TotRmsAbvGrd', 'GarageCars', 'GarageArea'], dtype='object')
def preprocess(df):
  return df[use_columns].copy()

df_train_p = preprocess(df_train)
df_train_p['SalePrice'] = df_train['SalePrice']
df_test_p = preprocess(df_test)

ハイパーパラメータの最適化

ベイズ最適化でハイパーパラメータを決める。 他にもいろいろなパラメータがあるが、やみくもに増やしても提出した後のスコアが良くならなかった。

ベイズ最適化でランダムフォレストとXGBoostの良いハイパーパラメータを探す - sambaiz-net

! pip install bayesian-optimization

import xgboost as xgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from bayes_opt import BayesianOptimization

num_boost_round=500

def optimize_params(df):
  def train(
      learning_rate, 
      colsample_bytree,
      sub_sample):
    train_x = df.drop('SalePrice', axis=1)
    train_y = df.SalePrice
    (train_x, test_x ,train_y, test_y) = train_test_split(train_x, train_y, test_size = 0.3)
    dtrain = xgb.DMatrix(train_x, label=train_y)
    param = {
        'learning_rate': learning_rate, 
        'colsample_bytree': colsample_bytree,
        'sub_sample': sub_sample}
    bst = xgb.train(param, dtrain, num_boost_round)
    preds = bst.predict(xgb.DMatrix(test_x))
    # Root-Mean-Squared-Error (RMSE) between the logarithm of the predicted value and the logarithm of the observed sales price
    return -np.sqrt(mean_squared_error(
        np.log(np.clip(np.nan_to_num(test_y), 1e-6, None)),
        np.log(np.clip(np.nan_to_num(preds), 1e-6, None))
    ))
  bo = BayesianOptimization(
    train,
    {'learning_rate': (0.01, 0.5), # default=0.3
     'colsample_bytree': (0.1, 1.0),  # default=1
     'sub_sample': (0.1, 1.0), # default=1
    })
  bo.maximize(n_iter=50, alpha=1e-5)
  return bo.max['params']

params = optimize_params(df_train_p)

結果こんな感じ。

print(params)
# => {'colsample_bytree': 1.0, 'learning_rate': 0.01, 'sub_sample': 0.28979827351242066}

実行

学習して予測結果を出力する。

bst = xgb.train(
    params, 
    xgb.DMatrix(df_train_p.drop('SalePrice', axis=1).values, label=df_train_p.SalePrice),
    num_boost_round)

preds = bst.predict(xgb.DMatrix(df_test_p.values))
submit_data = pd.Series(preds, name='SalePrice', index=df_test['Id'])
submit_data.to_csv('submit.csv', header=True)

スコアは 0.15509 だった。