Pythonの機械学習入門(3)~住宅価格を線形回帰で予測

Pythonの機械学習ライブラリ「scikit-learn」の使い方を簡単に説明します。今回は機械学習を用いて住宅価格の値を予測します。

住宅価格データの入手

先ずは、機械学習で使用する住宅価格データを入手します。今回はscikit-learnに内蔵されているデータセットを使用します。

使用するのはボストンの地域別の住宅価格データです。データのレコード数は506、カラム数は14です。

データには下記のような項目が存在します。今回予測するのは14番目の「MEDV」の値です。

列番号 項目名 意味
1 CRIM 一人あたりの犯罪率
2 ZN 25,000平方フィート以上の住宅地の割合
3 INDUS 非小売業種が占める土地の割合
4 CHAS チャールズ川のダミー変数(河川境界線の場合は1、そうでない場合は0)
5 NOX 酸化窒素濃度
6 RM 住居あたりの平均部屋数
7 AGE 1940年以前に建設された所有者占有物件の割合
8 DIS 5つのボストン雇用センターまでの加重距離
9 RAD 環状高速道路へのアクセスの容易さ
10 TAX 1万ドルあたりの不動産税率
11 PTRATIO 児童と先生の比率
12 B 黒人の比率(BK)の指標。1000(Bk – 0.63)^2
13 LSTAT 貧困層の人口比率(%)
14 MEDV 住宅価格の中央値(単位:1000$)

データの読込み

# 住宅価格データの読込み
boston = load_boston()

データの読込みはscikit-learnのdatasets内のload_boston関数を使用します。

特徴量データと教師データに分離

# 特徴量データと教師データに分離
X = pd.DataFrame(boston.data).values
y = pd.DataFrame(boston.target).values

データを特徴量データ教師データに分離します。Xは特徴量データで、506×13の行列データです。これは、13の特徴量(CRIMからLSTATまで)から成るレコードが506個あることを意味します。

yは教師データで、506×1の行列データです。これは、住宅価格(MEDV)のレコードが506個あることを意味します。

以降で、ボストン地域の13の特徴量に応じて、住宅価格を予測することになります。

※boston.dataは13の特徴量データ、boston.targetは住宅価格データ(MEDV)が格納

※DataFrameは行列データに変換するメソッド

※valuesはpandasからnumpyにデータを変換するメソッド

学習データとテストデータに分割

#学習データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2)

機械学習の性能を検証するために、学習に使用するデータセット(X_train、y_train)と、テストに使用するデータセット(X_test、y_test)に分割しておきます。

今回は学習データ:テストデータ=8:2にしました。比率はパラメータのtest_sizeで自由に設定できます。テストデータは慣習的におよそ20~25%くらいに設定します。

モデルの学習

# モデルの学習
pipe = Pipeline([('pre', StandardScaler()), ('est', LinearRegression())])
pipe.fit(X_train, y_train)

今回は住宅価格を予測するために、線形回帰(Linear Regression)の学習アルゴリズムを使用しました。

機械学習の分類のアルゴリズムはいくつかあり、データ数やデータの特性に応じて最適なものを選択する必要があります。

※線形回帰は、観測値と予測値の残差の二乗和が最小になるように近似直線を求めるアルゴリズムです。データの各項目間に線形の相関が存在する際に有効な手法です。

なお、今回は各データ項目の単位やスケールがそれぞれ異なるため、上手く機械学習させるためにデータの前処理を行う必要があります。

そこで、データの前処理とモデルの学習を一括で行う「パイプライン」という仕組みを使用しました。

データの前処理には「標準化(StandardScaler)」を、学習アルゴリズムには「線形回帰(LinearRegression)」を設定しました。

次にfitメソッドにて学習データセットを与えて学習させます。

これで、学習済みの「モデル」(または「学習器」)が完成しました。以降は、このモデルを用いて性能を評価したり、未知のデータに対する予測を行います。

※標準化の式は「(x – μ)/ σ」(x:データの値、μ:平均、σ:標準偏差)

モデルの性能評価

# モデルの性能評価
y_pred = pipe.predict(X_test)
r2 = r2_score(y_test, y_pred)
print ("R2スコア = ", r2)

ここで、学習済みのモデルの性能を評価します。新しいデータセットに対して、住宅価格をどれだけ正しく予測できるかを確認します。

predictメソッドにて特徴量のテストデータを与えて、予測した住宅価格をy_predに保存します。

そして、r2_scoreメソッドでy_predと、実際の住宅価格データのy_testの決定係数(当てはまりの良さ)を算出します。最も当てはまる場合は、値は1となります。

ソースコードを実行する度に、決定係数の値が変化します。これは、学習データとテストデータに分割したtrain_test_splitメソッドがランダムにデータを分割するからです。

概ね0.7~0.8の値になると思います。そこそこ当てはまりが良い学習モデルを作成できました。

r2 score

未知のデータの予測

# 未知のデータの予測
data = [[0.09, 13.0, 8.0, 0.0, 0.53, 6.1, 65.0, 5.8, 5.0, 305.0, 16.3, 396.2, 13.21]]
X_pred = np.array(data)
y_pred = pipe.predict(X_pred)
print (y_pred[0,0])

上手く学習できたモデルを使って、実際に未知のデータを予測してみましょう。実際のレコードに近い13の特徴量の値を入力したレコードを1つ作成します。

scikit-learn上で扱えるデータフォーマットに変換するためにnumpyを適用します。そして、predictメソッドにて住宅価格の予測を実行しました。

実行結果を表示させると、住宅価格を取得することができました。実際のレコードに近い住宅価格が得られたと思います。

まとめ

今回はPythonの機械学習ライブラリ「scikit-learn」を使用して、住宅価格を予測するモデルを作成しました。

押さえておきたいポイントとしては、

  • データを「特徴量データ」と「教師データ」に分離した
  • モデルの性能を評価するために、「学習データ」と「テストデータ」に分割した
  • 上手く学習させるためにデータの前処理(標準化)を行った
  • 学習済みのモデルを使って、「未知のデータ」に対して分類を実行した

参考文献

scikit-learn に付属しているデータセット
(https://pythondatascience.plavox.info/scikit-learn/scikit-learnに付属しているデータセット)