今日は多項式回帰でエイムズの住宅価格を予測したいと思います。
多項式回帰は、従属変数と独立変数とが非線形的な関係で表現されるような場合に適しており 引用: https://ja.wikipedia.org/wiki/多項式回帰
多項式回帰についてはWikipediaをご覧ください。
多項式回帰ですが、意外と好きなモデルです。
この前、欠損値処理でちょうど使いました。
データを確認していて多項式回帰の何次式だったら当てはまりよくなるかなと想像するのが楽しかったりします。
評価指標
住宅IdごとのSalePrice(販売価格)を予測するコンペです。
評価指標は予測SalePriceと実測SalePriceの対数を取ったRoot-Mean-Squared-Error(RMSE)の値のようです。
多項式回帰分析
分析用データの準備
事前に欠損値処理や特徴量エンジニアリングを実施してデータをエクスポートしています。
本記事と同じ結果にするためには事前に下記記事を確認してデータを用意してください。
(その3-2) エイムズの住宅価格のデータセットのデータ加工①
(その3-3) エイムズの住宅価格のデータセットのデータ加工②
学習用データとスコア付与用データの読み込み
import pandas as pd
import numpy as np
# エイムズの住宅価格のデータセットの訓練データとテストデータを読み込む
df = pd.read_csv("/Users/hinomaruc/Desktop/blog/dataset/ames/ames_train.csv")
df_test = pd.read_csv("/Users/hinomaruc/Desktop/blog/dataset/ames/ames_test.csv")
df.head()
Id LotFrontage LotArea LotShape Utilities LandSlope OverallQual OverallCond MasVnrArea ExterCond ... SaleType_New SaleType_Oth SaleType_WD SaleCondition_Abnorml SaleCondition_AdjLand SaleCondition_Alloca SaleCondition_Family SaleCondition_Normal SaleCondition_Partial SalePrice 0 1 65.0 8450 3.0 3.0 2.0 7 5 196.0 2.0 ... 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 208500 1 2 80.0 9600 3.0 3.0 2.0 6 8 0.0 2.0 ... 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 181500 2 3 68.0 11250 2.0 3.0 2.0 7 5 162.0 2.0 ... 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 223500 3 4 60.0 9550 2.0 3.0 2.0 7 5 0.0 2.0 ... 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 140000 4 5 84.0 14260 2.0 3.0 2.0 8 5 350.0 2.0 ... 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 250000 5 rows × 335 columns
# 描画設定
from IPython.display import HTML
import seaborn as sns
from matplotlib import ticker
import matplotlib.pyplot as plt
sns.set_style("whitegrid")
from matplotlib import rcParams
rcParams['font.family'] = 'Hiragino Sans' # Macの場合
#rcParams['font.family'] = 'Meiryo' # Windowsの場合
#rcParams['font.family'] = 'VL PGothic' # Linuxの場合
rcParams['xtick.labelsize'] = 12 # x軸のラベルのフォントサイズ
rcParams['ytick.labelsize'] = 12 # y軸のラベルのフォントサイズ
rcParams['axes.labelsize'] = 18 # ラベルのフォントとサイズ
rcParams['figure.figsize'] = 18,8 # 画像サイズの変更(inch)
多項式回帰に使用する変数を選ぶ
重回帰分析のときに使用した変数を利用したいと思います。(ただし、Neighborhoodのダミー変数を入れると精度が悪くなったので外しました。)
多項式回帰で学習を実施
# 説明変数
ana_cols=[
'TotalLivArea'
, 'OverallQual'
, 'TotalBathRms'
, 'GarageCars'
, 'BsmtQual'
, 'FullBath'
, 'GarageFinish'
, 'FireplaceQu'
, 'TotRmsAbvGrd'
]
# 説明変数と目的変数を指定
# 学習データ
X_train = df[ana_cols]
Y_train = df["SalePrice"] # 販売価格
# テストデータ
X_test = df_test[ana_cols]
# 多項式回帰用に説明変数を変換
from sklearn.preprocessing import PolynomialFeatures
#n=2で試してみます。
poly_reg = PolynomialFeatures(degree = 2)
X_train_poly = poly_reg.fit_transform(X_train)
X_test_poly = poly_reg.fit_transform(X_test)
# 多項式回帰のモデル作成
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X_train_poly,Y_train)
LinearRegression()
### モデルを適用し、SalePriceの予測をする
df_test["SalePrice"] = model.predict(X_test_poly)
df_test[["Id","SalePrice"]]
Id SalePrice 0 1461 108944.658065 1 1462 149998.097635 2 1463 176204.554156 3 1464 184123.457287 4 1465 181835.406584 ... ... ... 1454 2915 92864.108670 1455 2916 100606.761181 1456 2917 145681.573917 1457 2918 110397.724714 1458 2919 239170.667530 1459 rows × 2 columns
予測できていそうです。
Kaggleにスコア付与結果をアップロード
df_test[["Id","SalePrice"]].to_csv("ames_submission.csv",index=False)
!/Users/hinomaruc/Desktop/blog/my-venv/bin/kaggle competitions submit -c house-prices-advanced-regression-techniques -f ames_submission.csv -m "#3 polynomial regression"
100%|██████████████████████████████████████| 33.7k/33.7k [00:03<00:00, 9.15kB/s] Successfully submitted to House Prices - Advanced Regression Techniques
#3 polynomial regression 0.17609
重回帰よりもスコアが向上しました。
おまけ 多項式回帰 (n=3)を試してみる
# 説明変数と目的変数を指定
# 学習データ
X_train = df[ana_cols]
Y_train = df["SalePrice"] # 販売価格
# テストデータ
X_test = df_test[ana_cols]
# 多項式回帰用に説明変数を変換
from sklearn.preprocessing import PolynomialFeatures
#n=2で試してみます。
poly_reg = PolynomialFeatures(degree = 3)
X_train_poly = poly_reg.fit_transform(X_train)
X_test_poly = poly_reg.fit_transform(X_test)
# 多項式回帰のモデル作成
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X_train_poly,Y_train)
#モデルを適用し、SalePriceの予測をする
df_test["SalePrice"] = model.predict(X_test_poly)
# コンペ提出データの作成
df_test[["Id","SalePrice"]].to_csv("ames_submission.csv",index=False)
# コンペ提出
!/Users/hinomaruc/Desktop/blog/my-venv/bin/kaggle competitions submit -c house-prices-advanced-regression-techniques -f ames_submission.csv -m "#3 polynomial regression (n=3)"
100%|██████████████████████████████████████| 33.6k/33.6k [00:04<00:00, 8.23kB/s] Successfully submitted to House Prices - Advanced Regression Techniques
<div class="output_prompt">Out[0]</div>
<pre class="outputcell nohighlight">
#3 polynomial regression (n=3)
0.49355
</pre>
n=3は当てはまりが悪いようです。
使用ライブラリのバージョン
pandas Version: 1.4.3
numpy Version: 1.22.4
scikit-learn Version: 1.1.1
seaborn Version: 0.11.2
matplotlib Version: 3.5.2
まとめ
ボストンの住宅価格の予測のときも重回帰よりも多項式回帰の方が精度がよかったです。
重回帰でもbox-cox変換とかかけた上でモデリングすると精度があがるのでしょうか?
今度試してみます。
次回はニューラルネットワークを試してみようと思います。