PHONE APPLI Engineer blog

エンジニアブログ

主成分分析で住宅価格を考察してみた!

こんにちは。株式会社 PHONE APPLI リサーチデベロップメント 森本と申します。
この記事では統計分析初学者の方に向けて、自分が勉強した分析手法を紹介します。

今回は、主成分分析を用いてカリフォルニアの住宅データを変換します。

はじめに

まず、今回使うデータセットを紹介します。
今回は California Housing というデータセットを用いて分析をします。

これはカリフォルニアの住宅価格に関するデータセットで、属性は以下です。

説明変数:

MedInc median income in block 収入の中央値
HouseAge median house age in block ブロック内の家の中央年齢
AveRooms average number of rooms 平均部屋数
AveBedrms average number of bedrooms ベッドルームの平均数
Population block population ブロック人口
AveOccup average house occupancy 平均住宅占有率
Latitude house block latitude 家屋の緯度
Longitude house block longitude ハウスブロックの経度

これに加え、目的変数に ”価格” のデータがあるサンプル数 20640 のデータセットです。

主成分分析について

次に、今回扱う主成分分析について解説をします。
用語の意味に関しては、後述する "用語の説明" に記載いたしますのでご参照ください。

主成分分析の流れ

1. データを正規化 / 標準化する
この手順は単位が揃っているものであれば必要ありませんが、
単位の異なるデータを扱うケースでは、多くの場合スケーリングが必要です。

2. 分散を考える
分散の値から、平均からどれだけ離れているか (どのくらいばらつきがあるか) が分かります。
主成分分析では、分散を基準にデータの価値を考えます。
価値とはつまり、ばらつきがある程そのデータには特色や個性があり、平均などの指標以外で考えなくてはならないということです。

3. 第 1 主成分軸をとる
もっとも分散が大きくなるように新しい軸をとっていきます。
分散が最大ということは価値の合計が最も大きいものであり、
逆に、軸を変換した際に失われる価値の損失が最も小さいものとも言えます。
この新しい軸を第 1 主成分軸と言います。


図1. 第 1 主成分軸

4. 第 2 主成分軸をとる
2 番目に分散が大きくなるように新しい軸をとっていきます。
第 2 主成分軸をとる際には第 1 主成分と直交します。

図2. 第 2 主成分軸(濃), 第 1 主成分軸(薄)

5. 第 n 主成分軸をとる
前述のように分散が最大になる軸を取り続け、 n 次元データであれば第 n 主成分軸までとります。

主成分分析の種類

最後に、主成分分析の種類について説明します。
実は主成分分析には "分散共分散行列" を用いる方法と "相関行列" を用いる方法の 2 種類あります。

分散共分散行列を用いた主成分分析は前述の 1. ~ 4. までの通りですが、
相関行列を用いた主成分分析については、相関係数が小さいほど価値が高いと捉えるものであり、
各サンプルを標準偏差で割る為、スケーリングが完了しているというメリットがあります。

用語の説明

正規化 / 標準化
正規化: 最大値 1 , 最小値 0 にするスケーリング手法。
標準化: 平均 0 , 分散 1 にするスケーリング手法。
各数式は以下です。


図3. 正規化 ( 𝑥_𝑚𝑖𝑛 : 最小値 , 𝑥_𝑚𝑎𝑥 : 最大値)


図4. 標準化 ( : 平均 , σ : 標準偏差)

分散
各データと平均の差 (偏差) を 2 乗したものの平均。
数式は以下です。


図5. 分散

標本サイズ n ではなく、 n-1 で計算した不偏分散という概念も存在しています。

ちなみに...
偏差を 2 乗する理由は、偏差がマイナスの値になることを避けつつ、平均値との距離を考えているからです。

標準偏差
分散の平方根をとったもの。
数式は以下です。


図6. 標準偏差

分散では偏差を 2 乗すると単位が変わってしまう為、平均との比較などでは標準偏差を用いることが多いです。 標本サイズ n ではなく、 n-1 で計算した不偏標準偏差という概念も存在している。

分散共分散行列
共分散: "値 x の偏差と値 y の偏差" の積の平均。
数式は以下です。


図7. 共分散

各値の共分散の全て組み合わせを行列で表したものが分散共分散行列です。
n 次の分散共分散行列は、n × n の行列になります。


図8. 分散共分散行列 (2次元)

相関行列 
相関係数: 共分散をそれぞれの標準偏差で割ったもの。
数式は以下です。


図9. 相関係数

各値の相関係数の全ての組み合わせを行列で表したものが相関行列です。
最大値 1 、最小値 -1 にスケーリングされており、行列の対角成分が全て 1 となります。
n 次の相関行列は、n × n の行列になります。


図10. 相関行列 (2次元)

固有値 / 固有ベクトル
固有値: ある行列と固有ベクトルの積をとったときのベクトルが大きくなる倍率。
固有ベクトル: ある行列と積をとっても、定数 (固有値) 倍されるだけで向きが変わらないベクトル。

固有値問題
固有方程式 (特性方程式) と呼ばれる式を用いて、行列に対する固有値 / 固有ベクトルを導くこと。

主成分軸をとるために最も大きな分散を計算する際には、ラグランジュの未定乗数法などといった公式を用いて導出するのですが、計算していくと固有方程式に帰着していきます。
そのため主成分分析は、分散共分散行列を対角化する固有値問題になることが知られています。

主成分軸
主成分分析の際、新たにとる軸のこと。
n 番目に引いた軸のことを第 n 主成分軸といいます。

主成分得点
各サンプルが主成分軸上でとる値。
各主成分とサンプルの関係が把握できます。

寄与率
各主成分の固有値がデータ全体の情報を占める割合。
寄与率が大きいほど元データをよく説明できており、 寄与率が大きい方から足し合わせた累積寄与率という概念も存在します。

主成分負荷量
主成分得点と各サンプルの相関係数。 主成分分析における固有ベクトル

主成分負荷量が大きいほど、主成分をよく説明しています。
主成分得点だと各変数が増加した際、主成分軸上でいくつ増加するかがわかりますが、
単位が違うと一概に比較できなくなってしまいます。
主成分負荷では、各サンプルの相関係数をとることにより、単位の異なる指標でも主成分軸に対しどのくらいの影響を持っているかがわかるようになっています。

実装

ここから実際に python で実装した結果を載せていきます。

import pandas as pd
import inspect
import sklearn
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import fetch_california_housing
ライブラリをインポート

housing = fetch_california_housing()
データセットを展開

housing_df = pd.DataFrame(housing.data, columns=housing.feature_names)
housing_df['Price'] = housing.target
データセットをデータフレーム化、目的変数の "Price" をデータフレーム に追加

図10. California Housing

std = StandardScaler()
data_std = std.fit_transform(housing_df)
pd.DataFrame(data_std)
データを標準化

図11. 標準化データ

pca = PCA()
pca.fit (data_std)
feature = pca.transform(data_std)
主成分分析を実行し、ここから各パラメータについて見ていきます。

pd.DataFrame(feature, columns=["PC{}".format(x + 1) for x in range(len(housing_df.columns))])


図12. 主成分得点

pd.DataFrame(pca.explained_variance_ratio_, index=["PC{}".format(x + 1) for x in range(len(housing_df.columns))])


図13. 寄与率

pd.DataFrame(pca.explained_variance_, index=["PC{}".format(x + 1) for x in range(len(housing_df.columns))])


図14. 固有値

vec = pd.DataFrame(pca.components_, columns=housing_df.columns, index=["PC{}".format(x + 1) for x in range(len(housing_df.columns))])
vec.T


図15. 固有ベクトル (見やすいように結果を転置して表示)

以上の結果から、次元削減の観点では PC1~7 までを主成分分析後の分析で用いると、
元データを 約98% 説明できているので、十分に結果を得ることができそうです。
主成分分析のパラメータから言えることは、
Price に深く関係している PC3 とPC7 は MedInc、 HouseAge、AveRooms、 AveBedrms の負荷量が大きいため、この辺りが価格に影響しそうだと考えられます。

ちなみに...

check = housing_df.iloc[:,:].apply(lambda x: (x- x.mean())/ x.std(),axis =0)

fit_transform で本当に標準化できているのか確認のため、
公式 (図4. ) から標準化をしてみると、図11. とは若干値が異なってしまいました。

図16. 公式から標準化

print(inspect.getsource(pd.DataFrame.std))
公式の中で標準偏差を出すために使っている pd.DataFrame.std の中身を確認してみると、
デフォルトで ddof = 1 (不偏標準偏差) になっているため、若干値が異なる結果となっていました。

図17. pandas.DataFrame.std 中身

check = housing_df.iloc[:,:].apply(lambda x: (x-x.mean())/x.std(ddof=0), axis=0)
ddof = 0 (標準偏差) で改めて計算してみると、結果は fit_transform と一致しました。

余談

今回使用したデータセットの地域である、カリフォルニアについて調べてみました。
あの有名なハリウッドサインやグリフィスの天文台、ゴールデンゲートブリッジなどが名所としてあるようです。ゴールデンゲートブリッジはドラマのフルハウスでよく見たので個人的に印象深く感じました。

最後に

今回は主成分分析を用いて、カリフォルニアの住宅価格データを変換しました。
主成分分析は、元々のデータでは見えなかった部分を違う視点から捉えることにより、
新しい発見や結論を導くということがおもしろい部分だと思っています。

ここからさらに違う分析手法を用いていくと、よりおもしろい結果が得られるかもしれません。
主成分分析後に使えるクラスター分析については過去記事で紹介しているので、
ご興味ございましたらご一読ください。
階層型クラスター分析: phoneappli.hatenablog.com
非階層型クラスター分析: phoneappli.hatenablog.com

本記事がカリフォルニアで起こった裁判の "蜜蜂は魚である" という判決のように、
物事を多角的な視点で捉える手助けとなれば幸いです。