kaggle House Priceに挑戦!
初めに
この記事では、kaggleのHouse Priceコンペについて説明していきます!なお、コードは以下を参考にして下さい。
ライブラリの読み込み
まず、必要なライブラリの読み込みを行います。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import sklearn
from sklearn import ensemble
from sklearn import linear_model
from sklearn import model_selection
from sklearn import preprocessing
pd.set_option('display.max_columns', 100)
pd.set_option('display.max_rows', 100)
データの読み込み
データの読み込みを行います。
# 学習データ、テストデータ、提出サンプルデータの読み込み
train = pd.read_csv('../input/house-prices-advanced-regression-techniques/train.csv')
test = pd.read_csv('../input/house-prices-advanced-regression-techniques/test.csv')
sample = pd.read_csv('../input/house-prices-advanced-regression-techniques/sample_submission.csv')
データの大きさを確認します。
# データサイズの確認
print('学習データのサイズ:', train.shape)
print('テストデータのサイズ:', test.shape)
データの欠損値や型を確認します。
# データの情報の確認
print(train.info())
print("-"*10)
print(test.info())
ここから、データには欠損値が多く含まれることが分かります。さらに、データの型がobjectとなっている変数が多くあり、数値変数に変換する必要があります。
次に、学習用データを説明変数と目的変数に分けます。
# 学習用データを特徴量と目的変数に分ける
train_x = train.drop(['SalePrice'], axis=1)
train_y = train['SalePrice']
# テストデータは特徴量のみなのでそのままで良い
test_x = test.copy()
特徴量の作成
まず、データの欠損値を確認します。
#学習データの欠損値を確認する
print('訓練データの欠損値:\n', train_x.isnull().sum().sort_values(ascending=False))
print('訓練データの欠損値(割合):\n',
(train_x.isnull().sum() / len(train_x)).sort_values(ascending=False))
print("-"*10)
#テストデータの欠損値を確認する
print('テストデータの欠損値:\n', test_x.isnull().sum().sort_values(ascending=False))
print('テストデータの欠損値(割合):\n',
(test_x.isnull().sum() / len(test_x)).sort_values(ascending=False))
変数Idは番号を振っているだけであり、家の価格に影響を及ぼさないと考えられるので、除外します。
# 変数Idを除外する
train_x = train_x.drop(['Id'], axis=1)
test_x = test_x.drop(['Id'], axis=1)
次に、欠損値の処理をします。学習用データとテストデータに同じ処理をするため、2つのデータを結合します。こうした方がコードが短くて済みます。
# 学習データとテストデータを結合する
all_x = pd.concat([train_x, test_x])
欠損値が多すぎる変数は削除したいと思います。ここでは、欠損値が半分以上占める変数は削除します。(半分にしたのはなんとなくです)
# 欠損値が半分以上占める特徴量は除外する
miss_cols = []
for col in all_x.columns:
if all_x[col].isnull().sum()/len(all_x) > 0.5:
miss_cols.append(col)
all_x = all_x.drop(miss_cols, axis=1)
削除しなかった変数の中で、欠損のある変数について処理を行います。数値変数については中央値で補完したいと思います。
# 数値変数かつ欠損値を含む特徴量を中央値で補完する
# 数値変数かつ欠損値を含む特徴量を抜き出す
num_miss_cols = []
for col in all_x.columns:
if all_x[col].dtype in ['int64', 'float64'] and all_x[col].isnull().sum() > 0:
num_miss_cols.append(col)
# 欠損値を中央値で補完する
from sklearn.impute import SimpleImputer
imp_mean = SimpleImputer(missing_values=np.nan, strategy='median')
imp_mean.fit(all_x[num_miss_cols])
all_x[num_miss_cols] = imp_mean.transform(all_x[num_miss_cols])
カテゴリ変数については最頻値で補完したいと思います。
# カテゴリ変数かつ欠損値を含む列を最頻値で補完する
# カテゴリ変数かつ欠損値を含む特徴量を抜き出す
cat_miss_cols = []
for col in all_x.columns:
if all_x[col].dtype == 'object' and all_x[col].isnull().sum() > 0:
cat_miss_cols.append(col)
# 欠損値を最頻値で補完する
from sklearn.impute import SimpleImputer
imp_most_frequent = SimpleImputer(missing_values=np.nan, strategy='most_frequent')
imp_most_frequent.fit(all_x[cat_miss_cols])
all_x[cat_miss_cols] = imp_most_frequent.transform(all_x[cat_miss_cols])
欠損値の処理ができたので、結合したデータを学習用データとテストデータに再分割します。
# 学習データとテストデータに再分割する
train_x = all_x.iloc[:train_x.shape[0], :]
test_x = all_x.iloc[train_x.shape[0]:, :]
次に、カテゴリ変数を数値変数に変換していきます。ここでは、ラベルエンコーディングします。
# 質的変数をラベルエンコーディングする
# 質的変数を抜き出す
cat_cols = []
for col in train_x.columns:
if train_x[col].dtype == 'object':
cat_cols.append(col)
# 学習データとテストデータを結合してラベルエンコーディングする
from sklearn.preprocessing import LabelEncoder
all_x = pd.concat([train_x, test_x])
for col in cat_cols:
le = LabelEncoder()
all_x[col] = le.fit_transform(all_x[col])
# 学習データとテストデータに再分割
train_x = all_x.iloc[:train_x.shape[0], :]
test_x = all_x.iloc[train_x.shape[0]:, :]
これで、前処理が完了しました。最後に標準化をしておきます。
# 標準化
scaler = preprocessing.StandardScaler()
scaler.fit(train_x)
train_x = scaler.transform(train_x)
test_x = scaler.transform(test_x)
モデルの作成と評価、提出
分割方法を指定します。
# 分割方法の指定
kf = model_selection.KFold(n_splits=5, shuffle=True, random_state=0)
交差検証法を用いて、精度を確認します。
# モデルの作成と評価(RandomForestRegressor)
rfr = ensemble.RandomForestRegressor()
rfr_results = model_selection.cross_validate(rfr, train_x, train_y, scoring='neg_root_mean_squared_error',cv=kf)
rfr_results['test_score'].mean()
モデルのチューニングを行います。GridSearchCVを用いました。
# モデルの作成と評価 - チューニングあり(RandomForestRegressor)
param_grid = {
'n_estimators': [50, 100, 200],
'max_depth': [None, 2, 5],
}
tune_rfr = model_selection.GridSearchCV(rfr, param_grid=param_grid, scoring = 'neg_root_mean_squared_error', cv = kf)
tune_rfr.fit(train_x, train_y)
print("最もよいパラメータ: ", tune_rfr.best_params_)
print("検証データの平均値: ", tune_rfr.cv_results_['mean_test_score'][tune_rfr.best_index_])
チューニングの結果、最も精度の高かったモデルを用います。学習用データ全体でモデルの学習をして、テストデータに対して予測を行います。
# 学習データ全体でモデルの学習をする
tune_rfr.best_estimator_.fit(train_x, train_y)
# テストデータに対して予測する
predict = tune_rfr.best_estimator_.predict(test_x)
最後に提出ファイルを作成します。
# 提出用ファイルの作成
submit_1 = pd.DataFrame({'Id': test['Id'], 'SalePrice': predict})
submit_1.to_csv('submission.csv', index=False)
最後に
今回は各変数について細かい分析を行っていないので、もう少し深く分析をする記事も書きたいと思ってます!
Discussion