T-QARD Harbor

               

機械学習でカリフォルニアの住宅価格を予測する

Open in Colab

概要

データ分析には, 様々なモデルがを用いることができます. 今回は, California House Priceのデータ分析を, いくつかのモデルで行います.

方法

次のモデルを用いて, California House Priceのデータの分析を行います.

  • RIDGE
  • LASSO
  • 単純ベイズ
  • SVM

実験

ライブラリとデータの準備

ここでは, Google Colaboratoryにデフォルトで入っている, California House Priceのデータを用いて, カリフォルニアの住宅の価格予測を行います.
まずは, 必要なライブラリをインストールします.

import warnings

warnings.filterwarnings("ignore")

import pandas as pd
import numpy as np

from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error

California House Priceのデータを準備します. ここで使うデータは, Google Colaboratoryにてデフォルトで用意されているものです.

train_df = pd.read_csv("./sample_data/california_housing_train.csv")
test_df = pd.read_csv("./sample_data/california_housing_test.csv")

データの中身を表示します.

train_df.head()
Out[ ]:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value
0 -114.31 34.19 15.0 5612.0 1283.0 1015.0 472.0 1.4936 66900.0
1 -114.47 34.40 19.0 7650.0 1901.0 1129.0 463.0 1.8200 80100.0
2 -114.56 33.69 17.0 720.0 174.0 333.0 117.0 1.6509 85700.0
3 -114.57 33.64 14.0 1501.0 337.0 515.0 226.0 3.1917 73400.0
4 -114.57 33.57 20.0 1454.0 326.0 624.0 262.0 1.9250 65500.0

データに対して, 前処理をおこないます.

train_df.fillna(train_df.mean(), inplace=True)
test_df.fillna(train_df.mean(), inplace=True)

訓練データについて, 予測したいものと, 予測するために用いるデータ(特徴量)とに分けます. それぞれを表示してみます.

X_train = train_df.drop("median_house_value", axis=1)
y_train = train_df["median_house_value"]

X_train.head()
Out[ ]:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income
0 -114.31 34.19 15.0 5612.0 1283.0 1015.0 472.0 1.4936
1 -114.47 34.40 19.0 7650.0 1901.0 1129.0 463.0 1.8200
2 -114.56 33.69 17.0 720.0 174.0 333.0 117.0 1.6509
3 -114.57 33.64 14.0 1501.0 337.0 515.0 226.0 3.1917
4 -114.57 33.57 20.0 1454.0 326.0 624.0 262.0 1.9250

y_train.head()
Out[ ]:
0    66900.0
1    80100.0
2    85700.0
3    73400.0
4    65500.0
Name: median_house_value, dtype: float64

テストデータについても, 同様にします.

X_test = test_df.drop("median_house_value", axis=1)
y_test = test_df["median_house_value"]

RIDGE

まずは, リッジ回帰を行ってみます. 参考サイト:https://panda-clip.com/boston-ridge/

予測の精度は, 決定係数という指標で示しています. 決定係数R2とは, 各データの回帰直線からの距離の総和を考えることで求まります. 決定係数の値が大きい程, 予測の精度が高いと言うことができます. さらに, RMSEも表示しています. これは, 予測値と正解値の差を2乗して, 全てのデータについて和を取ったもので, この値が小さい程, 予測の精度が高いと言えます.

from sklearn import linear_model

# Ridge回帰
reg = linear_model.Ridge(alpha=0).fit(X_train, y_train)

print("alpha=0")
print("訓練データへの決定係数 :{:.7f}".format(reg.score(X_train, y_train)))
print("テストデータへの決定係数:{:.7f}".format(reg.score(X_test, y_test)))
y_pred_reg = reg.predict(X_test)
print("RMSE:{:.3f}".format(np.sqrt(mean_squared_error(y_pred_reg, y_test))))

reg = linear_model.Ridge(alpha=0.1).fit(X_train, y_train)

print("alpha=0.1")
print("訓練データへの決定係数 :{:.7f}".format(reg.score(X_train, y_train)))
print("テストデータへの決定係数:{:.7f}".format(reg.score(X_test, y_test)))
y_pred_reg = reg.predict(X_test)
print("RMSE:{:.3f}".format(np.sqrt(mean_squared_error(y_pred_reg, y_test))))

reg = linear_model.Ridge(alpha=0.5).fit(X_train, y_train)

print("alpha=0.5")
print("訓練データへの決定係数 :{:.7f}".format(reg.score(X_train, y_train)))
print("テストデータへの決定係数:{:.7f}".format(reg.score(X_test, y_test)))
y_pred_reg = reg.predict(X_test)
print("RMSE:{:.3f}".format(np.sqrt(mean_squared_error(y_pred_reg, y_test))))

reg = linear_model.Ridge(alpha=1).fit(X_train, y_train)

print("alpha=1")
print("訓練データへの決定係数 :{:.7f}".format(reg.score(X_train, y_train)))
print("テストデータへの決定係数:{:.7f}".format(reg.score(X_test, y_test)))
y_pred_reg = reg.predict(X_test)
print("RMSE:{:.3f}".format(np.sqrt(mean_squared_error(y_pred_reg, y_test))))
alpha=0
訓練データへの決定係数 :0.6413379
テストデータへの決定係数:0.6195058
RMSE:69765.360
alpha=0.1
訓練データへの決定係数 :0.6413379
テストデータへの決定係数:0.6195058
RMSE:69765.353
alpha=0.5
訓練データへの決定係数 :0.6413379
テストデータへの決定係数:0.6195062
RMSE:69765.324
alpha=1
訓練データへの決定係数 :0.6413378
テストデータへの決定係数:0.6195066
RMSE:69765.288

上の結果の通り, 回帰のパラメータαを変化させても, あまり予測の精度に影響はありません. 中では, テストデータへの決定係数が最も大きく, RMSEが最も小さい, alpha=1の予測が一番精度が高いと言えます.

# 通常の最小二乗法による線形回帰
reg2 = linear_model.LinearRegression().fit(X_train, y_train)

y_pred_reg2 = reg2.predict(X_test)
print("RMSE:{:.3f}".format(np.sqrt(mean_squared_error(y_pred_reg2, y_test))))
RMSE:69765.360

上で試した, Ridge回帰のalpha=1の場合の方が, RMSEが小さいことが分かります.

LASSO

次に, LASSO回帰を行います. 参考サイト:https://qiita.com/muscle_nishimi/items/901ed94f3cdf1c8d893a

上のRidge回帰では, 学習パラエータであるalphaを, こちら側が指定して学習を行っていましたが, 今度は, 最も良い値を探し, それを学習に採用する方法を取ります. 次の関数で, 最も良いパラメータを求めます.

from sklearn.linear_model import Lasso
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler


def lasso_tuning(train_x, train_y):
    # alphaパラメータのリスト
    param_list = [0.001, 0.01, 0.1, 1.0, 10.0, 100.0, 1000.0]

    for cnt, alpha in enumerate(param_list):
        # パラメータを設定したラッソ回帰モデル
        lasso = Lasso(alpha=alpha)
        # パイプライン生成
        pipeline = make_pipeline(StandardScaler(), lasso)

        # 学習
        pipeline.fit(X_train, y_train)

        # RMSE(平均誤差)を計算
        train_rmse = np.sqrt(mean_squared_error(y_train, pipeline.predict(X_train)))
        test_rmse = np.sqrt(mean_squared_error(y_test, pipeline.predict(X_test)))
        # ベストパラメータを更新
        if cnt == 0:
            best_score = test_rmse
            best_param = alpha
        elif best_score > test_rmse:
            best_score = test_rmse
            best_param = alpha

    # ベストパラメータのalphaと、そのときのMSEを出力
    print("alpha : " + str(best_param))
    print("RMSE : " + str(round(best_score, 4)))

    # ベストパラメータを返却
    return best_param


# best_alphaにベストパラメータのalphaが渡される。
best_alpha = lasso_tuning(X_train, y_train)
alpha : 100.0
RMSE : 69757.3352

上で試したRidgeよりもRMSEが低く, 予測の精度が高いことがわかります.

単純ベイズ

from sklearn.naive_bayes import GaussianNB

gnb = GaussianNB().fit(X_train, y_train)

y_pred_gnb = gnb.predict(X_test)
np.sqrt(mean_squared_error(y_pred_gnb, y_test))
Out[ ]:
100358.485516954

単純ベイズでの学習では, 誤差が非常に大きくなりました.

サポートベクトルマシン

from sklearn.svm import SVC

svc = SVC(kernel="linear", random_state=None).fit(X_train, y_train)

y_pred_svc = svc.predit(X_test)
np.sqrt(mean_squared_error(y_pred_svc, y_test))

あとがき

LASSOで行ったパラメータチューニングが今回最も精度の高い予測を導いたことから, データ分析の際は, パラメータの最適化をするとよい事がわかりました.