ボストン市の住宅価格で機械学習をはじめよう! – 機械学習入門

回帰分析(regression analysis)はデータから数値を予測するのに利用されます。たとえば、その日の最高気温とビールの売上げのデータを分析して、明日の予想最高気温からビールの売上げを予測する、といったときには回帰分析が役に立ちます。

有名な「ボストンの住宅価格データセット(Boston house-prices)」を使用して、Python で回帰分析をする方法を学んでいきましょう。

機械学習は「教師あり学習」、「教師なし学習」、「強化学習」の3種類がありますが、回帰分析はその中の教師あり学習(supervised learning)のひとつです。

回帰分析の手順

回帰分析は以下の手順で行います。

  1. 何を分析するかを決める
  2. データを集める
  3. データの分析と前処理をする
  4. 分析アルゴリズムを選ぶ
  5. モデルの実装とトレーニングをする
  6. モデルの評価をする

すでにデータがあり、そのデータから何を分析するかを決める、といったように手順が逆になることもあります。また、実際には上から順にスムーズに進むことは稀で、手順を行ったり来たりします。

この記事では手順3まで、手順4以降は次回に続きます。順に見てきましょう。

何を分析するかを決める

ボストンの住宅価格データセットでは、部屋数や犯罪発生率などのデータから住宅価格の予測を行います。機械学習の用語で表現すると、部屋数や犯罪発生率が説明変数特徴量)、住宅価格が目的変数です。

データを集める

すでにデータがあるのでこの手順は不要ですが、実際のプロジェクトではデータを集める必要があります。

データの分析と前処理をする

さて、ここからが本題です。

機械学習モデルは入力データをもとに学習(トレーニング)を行います。そのためデータの品質が十分でなかったり、手当たり次第に放り込んだりすると、精度の低いモデルになってしまいます。

機械学習モデルのトレーニングをする前に、データをよく分析することが重要です。

前処理とは?

機械学習ではデータの品質がとても重要です。記入漏れやミスだらけのデータでは、どんなに優れたアルゴリズムを使っても良い結果は得られません。

機械学習のアルゴリズムにデータを入力する前にデータを精査して、アルゴリズムに入力できるよう、あらかじめデータの修正・削除・変換などを行います。これを前処理と呼びます。

必要なライブラリ

Python3 と以下のライブラリを使用します。あらかじめインストールしておきましょう。

以下のソースコードは Jupyter(Jupyter Notebook)または Google Colaboratory で動作を確認しています。

データの読み込み

ボストンの住宅価格(Boston house – prices)は、1978年に D.Harrison と D.L. Rubinfeld によって収集された、ボストン近郊の住宅情報に関するデータセットです。とても有名なデータセットなので、データサイエンスや機械学習の教科書・書籍で一度は目にしたことがあるかもしれません。

ボストンの住宅価格は、Python の機械学習ライブラリ scikit-learn (サイキットラーン)の sklearn.datasets.load_boston 関数により読み込むことができます。

from sklearn.datasets import load_boston
dataset = load_boston()

dataset.DESCR を表示すると、データセットの概要が表示されます。

print(dataset.DESCR)
print(dataset.DESCR) の冒頭箇所

データ数(サンプルサイズ)は506件。予測に使う13個の属性(下表のCRIMからLSTATまで)、目的となる1個の属性(下表のMEDV)からなるデータセットです。

各属性についての日本語訳すると、以下のようになるかと思います(訳は適当です、すみません・・・)。

CRIM 犯罪発生率(町ごとの一人当たり犯罪率)
ZN 25,000 平方フィート以上の住宅区画の割合
INDUS 小売業以外の商業が占める土地面積の割合
CHAS チャールズ川沿いかどうかのダミー変数 (1: 川沿い、 0: それ以外)
NOX 窒素酸化物の濃度(pphm単位)
RM 1戸あたりの平均部屋数
AGE 1940年よりも前に建てられた物件の割合
DIS ボストンにある5つの雇用施設までの重み付きの距離
RAD 環状高速道路へのアクセス指数
TAX 10,000ドルあたりの固定資産税の割合
PTRATIO 町ごとの生徒と教師の比率
B 1000(Bk – 0.63)^2 の値。BKは町ごとの黒人の割合。
LSTAT 低所得者の割合 (%)
MEDV 住宅価格の中央値(単位 1000ドル)

MEDVは住宅価格の「中央値」とありますが、価格に関する詳細データはないため、単に住宅価格とみなして大丈夫です。

平均部屋数、住宅価格の中央値という説明から推測すると、(集合住宅や区画内の家をまとめていたり)必ずしも 1データ = 1家 でないのでしょう。D.Harrison と D.L. Rubinfeld がどのようにデータを集めたかを調べるとはっきりするかと思います。筆者はそこまでは調べていないので・・・あくまで推測です。

念のため目的を再確認すると、CRIM から LSTAT まで13の特徴量をもとに機械学習のモデルを作り、住宅価格 MEDEV を予測することです。

pandas で分析する準備

Python では pandas によりデータの精査や前処理を行うのが一般的です。まずは load_boston 関数で取得した dataset を pandas の DataFrame にセットします。

import pandas as pd
df = pd.DataFrame(dataset.data, columns=dataset.feature_names)
df['MEDV'] = dataset.target

下準備は完了です。データの精査を行っていきましょう。

最初の5行を確認

実際にどのようなデータが入っているかをまずチェックしましょう。df.head() により最初の5行を確認できます。

df.head()

df.head(10) のように行数を指定することも可能です。df.tail() を使うと最後の5行を確認できます。

エクセルだとイメージしやすいかも?

Microsoft Excel(エクセル) だとイメージがわきやすいかもしれません。下図はボストンの住宅価格CSVファイルをエクセルで開いたときのスクリーンショットです。

Excel で開いたときの冒頭箇所

CRIM から MEDV まで合計14列。その下に実測値が506行記入された表にすぎません。

データの概要を把握

pandas にはデータの概要を瞬時に把握できる pandas.DataFrame.info()pandas.DataFrame.describe() という2つのメソッドがあります。

df.info()

どの属性も506件、float64型のデータということがわかります。

ボストンの住宅価格は理想的なデータですが、実際のデータでは記入漏れ(欠損値)はつきものです。また、本来数値が記入される項目に文字列が記入されている、といったことは日常茶飯事です。df.info() によりデータの型や件数をざっと確認しましょう。

df.describe()

わずか1行のコードで、属性ごとにデータの平均値や標準偏差といった要約統計量をまとめて確認できます。

欠損値のチェック

先程の df.info() によっても把握できますが、欠損値の有無を調べたい場合には df.isnull().sum() や df.isnull().any() という処理がよく使われます。覚えておくとよいでしょう。

データを可視化して分析

df.info() や df.describe() の結果は有益ですが、それだけでデータの特徴を把握するのは至難の技です。図やグラフなど、何かしらの可視化を行って分析をするのが一般的です。

ここでは、よく使われる2つの方法を紹介します。

ペアプロット図(散布図行列)

ペアプロット図(散布図行列)を利用すると、説明変数・目的変数間の散布図とヒストグラムをまとめて確認することができます。言葉で説明するより見てもらうのが手取り早いでしょう。

# ペアプロット図や後述のヒートマップを描くには seaborn と matplotlib が必要です。
import seaborn as sns
import matplotlib.pyplot as plt

# seaborn のデフォルトのスタイルを適用
sns.set()

sns.pairplot(df)
plt.show()
ペアプロット図(散布図行列)

変数が多いため、とても壮大な図ですね・・・。RM、LSTAT、MEDEV の3つに絞って見やすくしてみましょう。

# RM, LSTAT, MEDV のペアプロット
sns.pairplot(df[['RM', 'LSTAT', 'MEDV']])
plt.show()
ペアプロット図(散布図行列)

一番下の段だけ簡単に見てみましょう。

一番下の段の左 RM と MEDV の散布図を見ると、(イレギュラーな点はありますが) RM が増加すると MEDV も増加する、つまり、RM と MEDV には正の相関が見てとれます。また、どことなく直線的な関係に見えます。

一番下の段の中央 LSTAT と MEDV の散布図を見ると、LSTAT が増加すると MEDV は減少する、つまり、負の相関が見てとれます。

一番下の段の右図は MEDV のヒストグラムです。右端の盛り上がりはあるものの、山なりの形をしていて、正規分布に近いように見えます。

このように視覚化すると、データの特徴が見えてきます。

補足

散布図やヒストグラムを1つずつ表示したい場合は以下のようにします。

# RM と MEDV の散布図
sns.scatterplot(x='RM', y='MEDV', data=df)
plt.show()
# MEDV のヒストグラム
sns.distplot(df['MEDV'])plt.show()

相関行列のヒートマップ

ペアプロット図とあわせて、相関行列のヒートマップを利用すると属性間の相関関係をより明確に把握できます。pandas.DataFrame.corr() で相関行列を取得して、seaborn.heatmap() の引数として渡せば、ヒートマップを描くことができます。

corr_matrix = df.corr(method="pearson")  # ピアソンの積率相関係数
plt.subplots(figsize=(12, 10)) # 図の大きさを適当に指定
heatmap = sns.heatmap(corr_matrix, vmin=-1, vmax=1, center=0, annot=True, fmt=".2f")
plt.show()
相関行列のヒートマップ

相関係数(ピアソンの積率相関係数)はデータ間の相関の度合いを表す数値で -1 から 1 までの値をとります。 1 に近い場合は正の相関、-1 に近い場合は負の相関があると判断でき、 0 に近い場合は相関関係がないと判断できます。

ペアプロット図では目視での推測でしたが、RM と MEDV の相関係数は 0.70 で正の相関があると判断できます。同様に LSTAT と MEDV の相関係数は -0.74 で負の相関があると判断できます。

相関係数の値だけでは相関を判断できないこともあります。相関係数についての詳細はWikipedia相関係数を参照ください。

このヒートマップで真っ先に気になるのは、説明変数 RAD と TAX の相関係数が 0.91 という高い値になっていることです。説明変数間に強い相関がある場合、アルゴリズムによっては分析結果に悪い影響を及ぼすことがあるので注意が必要です。詳しくは多重共線性というキーワードで検索してみてください。

事前のデータ分析については、ひとまず以上です。データ分析手法のほんの一部にすぎませんが、プログラミングに加えて数学の知識も必要だったりと、相当難しかったのではないでしょうか。データを pandas に入れて、あれこれ調べるのだな、それだけでもAIや機械学習について何も知らない状態からは大きな前進かと思います。

次回はボストンの住宅価格データセットに対して、実際に機械学習を行います。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です