主成分分析とは
主成分分析(Principle Component Analysis)とは,どういったものなのかを説明したいと思います.主成分分析は多次元のデータを圧縮する方法です.
主成分分析とは直接は関係ありませんが,次元圧縮の一例として例えばプログラマのスキルとしてpython, C++, Javaの熟練度を測るためにGithub上でのstar⭐️の数でスキルを評価できると仮定しましょう.
それはつまり3次元のデータを1次元に要約(圧縮)したことになります.
他にも体重と身長の2次元データを一次元にするモデルとしてBMIなどもその一例です.
座標で考えると,例えば3次元のデータ(x,y,z座標)を二次元のデータ(l,m座標)に要約(圧縮)するようなものです.
この時l(エル)を第1主成分,mを第2主成分と呼びます.
イメージとしては,三次元空間にある赤い点を主成分軸(この場合第1・第2主成分)にして2次元で表すということです.
本記事では,3次元を2次元に圧縮する例を紹介します.
主成分軸をどのように見つけるのか.
主成分を見つけるためには,分散が最大になるような軸を探します.
分散はどのようなものかといえば以下の式のようにデータとデータ平均の二乗和を平均nで割ったものです.(端的に言ってしまえば,データの散らばり具合を定義していることになります.)
分散の定義
この時Xを確率変数といいます.右辺のと同じです.
最大となる分散を探すというのことは軸から最も離れた確率変数を探すということになります.
下の図のような具合にデータが散りばめられている時分散は大きくなります.
それに対して,ほぼありえないことですが,直線にぴったし確率変数が当てはまった場合は分散は0になります.(下の図)
固有値と固有ベクトル
固有値と固有ベクトルの定義
n次正方行列において,
を満たす零ベクトルではないn次元実数ベクトル,
とスカラー が存在するとき,
をAの固有値. をAの(に対する)固有ベクトルという.
これだけでは何を言っているか分からないので実際に計算をしてみる.
実際には行列に対して固有多項式を定義してやりそれを解くことによって求まる.
固有多項式の定義
次正方行列Aに関して
をAの固有方程式という.
例
以下の2次正方行列の固有値と固有ベクトルを求めよ.
固有方程式は代入すればいいだけなので,
あとはサラスの公式で計算すればいいだけなので,
よって
固有値に対する固有ベクトル
連立方程式を解くと
となる.
よってスカラーを用いてに対応する固有ベクトルは次式で与えられる.
また固有値に対する固有ベクトルは
上と同じ手順に解くとに対する固有ベクトルが求まる.
寄与率と累積寄与率
次に寄与率についての説明です.第1主成分と第2主成分の定義は以下になります.
第1主成分の寄与率は第1主成分がデータ全体のデータの散らばり具合をどれくらいカバーしているかを表しています.第2主成分以降も同様です.
第1主成分の寄与率 =
第2主成分の寄与率 =
一般に第i主成分までの定義は以下になります.
第i主成分の寄与率 = =
総分散 = (ただし は第i固有値)
累積寄与率
累積寄与率とは,第1主成分から第m主成分までの寄与率の和です.
第1主成分から第m主成分での圧縮がデータの散らばり具合をどの程度カバーしているかの説明する割合です.(1に近ければデータの散らばり具合を説明できている割合が高いことになります.)
第1主成分から第m主成分までの累積寄与率 =
(分散共分散行列で求めた固有値は,主成分方向の分散に対応します.)
実際に応用して見る.
PythonとJavaのソースコードのGithub上でのスターの総数と給料という3次元のデータを2次元に次元圧縮する例を考えてみました.あたいはある程度相関があるように適当に調整しました.(現実とはおそらく異なるでしょう....)
pythonのscikit-learnのPCAのライブラリを使用しました.
点の色 | Pythonのstar⭐️の総数 | Javaのstar⭐️の総数 | 給料(万円) |
---|---|---|---|
青 | 70 | 30 | 700 |
緑 | 32 | 60 | 480 |
赤 | 32 | 20 | 300 |
黄色 | 20 | 120 | 600 |
茶色 | 40 | 120 | 630 |
グレー | 40 | 30 | 520 |
ディープピンク | 300 | 1100 | 1200 |
黒 | 2000 | 400 | 1500 |
オレンジ | 40 | 180 | 800 |
# coding: utf-8
import matplotlib.pyplot as plt
import numpy as np
# 主成分分析をするライブラリ
from sklearn.decomposition import PCA
# [Pythonのコードのスター総数, Javaのコードのスターの総数, 年収]
X = np.array([[70, 30, 700],[32, 60, 480],[32, 20, 300],[20, 120, 600],[40, 120, 630], [40, 30, 520], [300, 1100, 1200], [2000, 400, 1500],[40, 180, 800]])
pca = PCA(n_components=2)
pca.fit(X)
# 各主成分によってどの程度カバー出来ているかの割合
print(pca.explained_variance_ratio_)
# [ 0.80636224 0.17927921]
# 次元削減をXに適用する.
pca_point = pca.transform(X)
color = ['blue', 'green', 'red', 'yellow', 'brown', 'gray', 'deeppink', 'black','orange']
plt.scatter(*pca_point.T, color=color)
plt.show()
主成分得点をプロットすると以下のグラフになる.
x軸に相当するのが給料と見ることができるでしょう.y軸に相当する方向の解釈が難しいですが,よーくデータ分布を見るとJavaができて給料がそこそこの人が高くなる傾向にあるように見ることができそうです.黒の人は給料は高いがpythonで勝負している人と解釈できそうだ.ピンクさんは給料が高くpythonよりもjavaが得意な人と見ることができそうです.
他の人たちもだいたい同じ規則でしたがっていそうです.
まとめ
最後のはデータをQiitaのアドベントカレンダーように急いで作ったのであくまで参考程度に解釈してほしい.自然のリアルなデータだと主成分分析は気づかない特徴を調査することができるので使えるだろう.またカーネルPCAなどもあるが私の現在のレベルでは難しいのでもう少しレベルアップしたらどこかで書きたい.
また,主成分分析では主成分軸を見つけて関係している因子を自分で解釈するが,逆の発想で因子を自分で仮定して推定する手法に因子分析というものがある.それはおいおい書けたら書きたいと思う.
参考文献
統計科学研究所R主成分分析.ppt から数式など参照させてもらいました.
固有値の計算手順や主成分分析の考え方などの文言など.
線形代数学に基づくデータ分析法: 原田 史子,島川 博光