はじめに
SAMURAI ENGINEERのデータサイエンスコースの最終課題として、
kaggleのコンペ 「House Prices」に参加したので内容をレポートでまとめました。
コンペの概要
アイオワ州エイムズにある住宅価格を予測するモデルを構築する。
モデルの性能はRMSEで評価される。
分析するデータ
以下のkaggleページにある学習用データとテスト用データを利用。
https://www.kaggle.com/competitions/house-prices-advanced-regression-techniques/data
実行環境
PC: MacBook Air
開発環境: Google Coraboratory
言語: Python
ライブラリ: Pandas, Numpy, Matplotlib
分析の流れ
- データ、ライブラリの読み込み
- データ内容の確認
- データの前処理
- 決定木による予測モデルの作成と予測の実施
- 予測データの提出
- 予測モデルの評価結果の確認
- 予測モデルの改善
- 特徴量の見直し
- ランダムフォレストによる予測モデルの作成
- LightGBMによる予測モデルの作成
分析の過程
データ、ライブラリの読み込み
import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline
df_train = pd.read_csv("train.csv")
df_test = pd.read_csv("test.csv")
データ内容の確認
カラムの内容
df_train.head()
df_test.head()
基本統計量
df_train.describe()
df_test.describe()
欠損値
df_train.isnull().sum()
df_test.isnull().sum()
結果
データの前処理
パラメータの選択
79の説明変数から、特に住宅価格に影響を与えそうなものかつ欠損のないものを選び、モデル構築に使うパラメータを選択。
選択したパラメータとデータタイプ:
MSSubClass: 住宅のタイプ(1階建、2階建など) / int
LandContour: 土地の平坦さ / string
LotArea: 住宅の面積 / int
YearBuilt: 住宅が建てられた年 / int
YearRemodAdd: 住宅がリフォームされた年 / int
MiscVal: 住宅設備の価値 / int
stringからintへの変換
ダミー変数への置換
codes = pd.get_dummies(df_train["LandContour"])
df_train = pd.concat([df_train, codes], axis = 1)
codes2 = pd.get_dummies(df_test["LandContour"])
df_test = pd.concat([df_test, codes2], axis = 1)
予測モデルの作成と予測の実施
学習データの特徴量と目的変数の取得
selected_columns = ["MSSubClass", "LotArea", "Bnk", "HLS","Low", "Lvl", "YearBuilt","YearRemodAdd", "MiscVal" ]
x = df_train [selected_columns]
y = df_train["SalePrice"]
scikit-learnライブラリからモジュールのインポート
from sklearn.tree import DecisionTreeRegressor
model = DecisionTreeRegressor(max_depth = 5, min_samples_leaf = 1, min_samples_split= 2)
model.fit(x, y)
決定木の可視化
from sklearn.tree import export_graphviz
import pydotplus
from six import StringIO
from IPython.display import Image
dot_data = StringIO()
export_graphviz(model, out_file = dot_data, filled = True, rounded = True)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
Image(graph.create_png())
残差プロット
y_pred = model.predict(x)
plt.scatter(y_pred, y_pred-y, color = "blue")
plt.hlines(y=0, xmin = -10, xmax = 20, color = "black")
plt.title("Residual Plot")
plt.xlabel("predicted Values")
plt.ylabel("Residuals")
plt.grid()
plt.show()
結果
RMSEの算出
from sklearn.metrics import mean_squared_error
print("MSE: (train)", mean_squared_error(y, model.predict(x)))
mse =mean_squared_error(y, model.predict(x))
rmse = np.sqrt(mse)
print(rmse)
結果
MSE: (train) 2329037399.4442697
RMSE: 48260.101527496496
r2スコアの算出
from sklearn.metrics import r2_score
print("r^2 (train):", r2_score(y, model.predict(x)))
結果
r^2 (train): 0.6307094541182758
テストデータを使った予測の実施
x_test = df_test [selected_columns]
predict_x_test=model.predict(x_test)
print(predict_x_test)
結果
[148366.69620253 148366.69620253 241307.25641026 ... 218872.
199595. 231351.28571429]
予測データの提出
submission = pd.DataFrame({"Id": df_test["Id"], "SalePrice": predict_x_test })
submission.to_csv("submission_House_Price_DecisionTree_v1.csv", index = False)
上で作成したcsvデータをkaggleでsubmit
予測モデルの評価結果の確認
予測モデルの改善
学習データの特徴量の見直し
version2: 特徴量として使用する説明変数を以下に変更
MSSubClass: 住宅のタイプ(1階建、2階建など) / int
MSZoning: 住宅のある地域の種別 /string
LandContour: 土地の平坦さ / string
LotArea: 住宅の面積 / int
LotShape: 土地の形 / string
OverallQual: 住宅に使われている材料のグレード / int
OverallCond: 住宅の状態のグレード / int
1stFlrSF: 1階部分の面積 / int
2ndFlrSF: 2階部分の面積 / int
YearBuilt: 住宅が建てられた年 / int
YearRemodAdd: 住宅がリフォームされた年 / int
MiscVal: 住宅設備の価値 / int
version2のモデルを作成
MSE: (train) 1062672498.378301
RMSE: 32598.65792296212
r^2 (train): 0.8315033897208962
version3: 特徴量として使用する説明変数を以下に変更
MSZoning: 住宅のある地域の種別 /string
LotArea: 住宅の面積 / int
LotShape: 土地の形 / string
OverallQual: 住宅に使われている材料のグレード / int
OverallCond: 住宅の状態のグレード / int
1stFlrSF: 1階部分の面積 / int
2ndFlrSF: 2階部分の面積 / int
YearBuilt: 住宅が建てられた年 / int
YearRemodAdd: 住宅がリフォームされた年 / int
version3のモデルを作成
MSE: (train) 824685794.8220115
RMSE: 28717.34310172185
r^2 (train): 0.8692383954747174
ランドムフォレストによる予測モデルの作成
from sklearn.ensemble import RandomForestRegressor
model = RandomForestRegressor(n_estimators = 100, random_state = 0)
model.fit(x,y)
from sklearn.tree import export_graphviz
import pydotplus
from six import StringIO
from IPython.display import Image
dot_data = StringIO()
export_graphviz(model.estimators_[0], out_file = dot_data, filled = True, rounded =True)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
Image(graph.create_png())
y_pred = model.predict(x)
from sklearn.metrics import mean_squared_error
print("MSE: (train)", mean_squared_error(y, model.predict(x)))
mse =mean_squared_error(y, model.predict(x))
rmse = np.sqrt(mse)
print(rmse)
MSE: (train) 141429420.63457957
11892.41021133141
from sklearn.metrics import r2_score
print("r^2 (train):", r2_score(y, model.predict(x)))
r^2 (train): 0.9775750496911977
LightGBMによる予測モデルの作成
! pip install lightgbm
import lightgbm as lgb
model = lgb.LGBMRegressor(bagging_freq=6, min_child_samples = 5, random_seed = 0, lambda_l1 = 0.007271571727189536, lambda_l2 = 1.2587243723353944e-06, feature_fraction = 0.89999999999999, bagging_fraction = 0.864171352999215)
model.fit(x,y)