見出し画像

【Python学習日記3】         ボストンの住宅価格予測

 こんにちは。プログラミングスクールでPythonを使ったデータ分析を学習中の ひよっこ分析者B(Book358)です。今回はscikit-learnの「ボストンの住宅価格データセット」を用いて、相関性の高い特徴量から住宅価格を予測するモデルを構築してみました。

※ 開発環境
   Python3,Windows11 ,Chrome,Google Colaboratory


1. 概要


1.1 題目

 ボストンの住宅価格予測

1.2 目的

 「ボストンの住宅価格データセット」を用いて、住宅価格を予測する機械学習モデルを構築すること

1.3 データセット

 ボストン市の住宅価格データ
    CRIM:人口 1 人当たりの犯罪発生数
     ZN:25,000 平方フィート以上の住居区画の占める割合
  INDUS:小売業以外の商業が占める面積の割合
         CHAS:チャールズ川によるダミー変数 (1: 川の周辺, 0: それ以外)
     NOX:NOx の濃度
            RM:住居の平均部屋数
           AGE:1940 年より前に建てられた物件の割合
            DIS:5つのボストン市の雇用施設からの距離 (重み付け済)
          RAD:環状高速道路へのアクセスしやすさ
           TAX:$10,000 ドルあたりの不動産税率の総計
   PTRATIO:町毎の児童と教師の比率
               B:町毎の黒人 (Bk) の比率を次の式で表したもの
        1000(Bk – 0.63)^2
        LSTAT:給与の低い職業に従事する人口の割合 (%)
     MEDVT:「住宅価格 (1000ドル単位)」の中央値

2. バージョン1.1をインストール

 scikit-learnのバージョン1.2以降は「boston house prices dataset」がサポートされていない為、それ以前のバージョンをインストールします。

!pip install scikit-learn==1.1

3. ライブラリのインポート


 使用するライブラリをインポート。

import pandas as pd
import numpy as np
from sklearn.datasets import load_boston
from sklearn.decomposition import PCA
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.metrics import r2_score
from sklearn.metrics import mean_squared_error

4. データの確認


 以下の手順で、データセットを確認します。

4.1 データセットの読込

 インポートした「load_boston (ボストンの住宅価格データセット)」を読込みます。

data = load_boston()
data

4.2 住宅価格以外の項目

 住宅価格以外の項目を「x」に代入します。

x = pd.DataFrame(data=data.data, columns=data.feature_names) 
x.head(3)
Table1 住宅価格以外の項目 (x)

4.3 住宅価格

 住宅価格を「y」に代入します。

y = pd.DataFrame(data=data.target, columns=["MEDV"]) 
y.head(3)
Table2 住宅価格 (y)

4.4 相関係数を可視化

 「x」と「y」を結合した「全データ」の相関係数をヒートマップで可視化します。

df = pd.concat([x, y], axis=1)
corr = df.corr()
sns.heatmap(corr, vmin=-1, vmax=1, annot=True, fmt='.2f', annot_kws={"fontsize":8})
plt.show()
Fig.1 相関係数

4.5 強い相関関係にある項目

 住宅価格(MEDV)と強い相関関係(正の相関:0.5以上, 負の相関:0.5未満)にある項目を抽出します。

corr_high = corr[(corr['MEDV']>0.5) | (corr['MEDV']<-0.5)]['MEDV']
corr_high
columns = corr_high.index.values
corr2 = corr.loc[columns][columns]
corr2[(corr2>0.5) | (corr2<-0.5)]
Table3 相関係数 (強い相関のある項目)

4.6 データをグラフ化

 住宅価格と最も強い相関関係にある項目2つ「RM (住居の平均部屋数)」と「LSTAT (給与の低い職業に従事する人口の割合)」に的を絞り、データをグラフ化します。

df2 = df.loc[:, ['RM', 'LSTAT', 'MEDV']]
sns.pairplot(df2)
plt.legend()
Fig.2 住宅価格(MEDV)との関係性

4.7 データの傾向

 Fig2(住宅価格(MEDV)との関係性)のグラフから、以下の傾向があると考えられます。
 ・部屋数(RM)が多い程、住宅価格は上がる (正の相関)
 ・給与が低い人たちの割合(LSTAT)が高い程、住宅価格は下がる (負の相関)

5. モデル構築

 以下の手順で、回帰のアルゴリズムにGradientBoostingRegressor (勾配ブースティング)を用いたモデルを構築します。

5.1 特徴量を作成

 強い相関性のある項目「RM (住居の平均部屋数)」と「LSTAT (給与の低い職業に従事する人口の割合)」の2つを特徴量「X」に代入します。
(正解ラベルは「住宅価格 (y)」)

X = x[['RM', 'LSTAT']]
X.head(3)
Table4 特徴量 (X)

5.2 前処理

 データの前処理として、PCA(主成分分析)を行います。

pca = PCA()
pca.fit(X)
pca.fit(y)

5.3 データ分割

 交差検証(ホールドアウト)を行う為、全データを訓練データ(train_x, train_y)と検証データ(test_x, test_y)に分割します。

train_x, test_x, train_y, test_y = train_test_split(X, y, test_size=0.3, random_state=1)

5.4 機械学習

 機械学習に用いるアルゴリズム(勾配ブースティング)を定義し、.fit()で学習してモデルを構築します。

model = GradientBoostingRegressor()
model.fit(train_x, train_y)

6. モデルの評価

6.1 予測値を算出

 .predictでtrain(訓練データ), test(検証データ)それぞれの予測値を算出し、「pred_train_y」と「pred_test_y」に代入します。

pred_train_y = model.predict(train_x)
pred_test_y = model.predict(test_x)

6.2 評価指標(R2, RMSE)を算出

 「r2_score」でR2(決定係数), 「np.sqrt(mean_squared_error)」でRMSE (二乗平均平方根誤差)を算出します。

print('train')
print('————————————')
print('  R2:{:.3f}'.format(r2_score(train_y, pred_train_y)))
print('RMSE:{:.3f}'.format(np.sqrt(mean_squared_error(train_y, pred_train_y))))
print()
print('test')
print('————————————')
print('  R2:{:.3f}'.format(r2_score(test_y, pred_test_y)))
print('RMSE:{:.3f}'.format(np.sqrt(mean_squared_error(test_y, pred_test_y))))

R2 (決定係数)
 ・推定された回帰式の当てはまりの良さ
 ・1に近いほど予測精度が高い
RMSE (二乗平均平方根誤差)
 ・平均化された誤差の値
 ・0に近いほど予測精度が高い

7. 考察

 今回の「ボストンの住宅価格データセット」では、「部屋数が多く、給与が低い人たちの割合が低い地域の住宅価格が高い」という傾向が見受けられました。勾配ブースティングによる予測モデルの精度(検証データ)はR2が0.75, RMSEが4.75でした。(あまり高くはないです)
 引き続き、色々なデータセットでモデル構築の実践をして、Pythonを使ったデータ分析を学習していこうと思います。