主成分分析とは

主成分分析(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次元で表すということです.

3dimention_to_2dimention (2).png

本記事では,3次元を2次元に圧縮する例を紹介します.

主成分軸をどのように見つけるのか.

主成分を見つけるためには,分散が最大になるような軸を探します.
分散はどのようなものかといえば以下の式のようにデータxiとデータ平均μの二乗和を平均nで割ったものです.(端的に言ってしまえば,データの散らばり具合を定義していることになります.)

分散の定義

Var[X]=E[(Xμ)2]=1ni=n(xiμ)2

この時Xを確率変数といいます.右辺のxiと同じです.
最大となる分散を探すというのことは軸から最も離れた確率変数を探すということになります.
下の図のような具合にデータが散りばめられている時分散は大きくなります.

variance (1).png 

それに対して,ほぼありえないことですが,直線にぴったし確率変数が当てはまった場合は分散は0になります.(下の図)
variance2.png

固有値と固有ベクトル

固有値と固有ベクトルの定義

n次正方行列において,
Av=λv を満たす零ベクトルではないn次元実数ベクトル,
v0n とスカラーλ が存在するとき,

λ をAの固有値. vをAの(λに対する)固有ベクトルという.

これだけでは何を言っているか分からないので実際に計算をしてみる.
実際には行列に対して固有多項式を定義してやりそれを解くことによって求まる.

固有多項式の定義

n次正方行列Aに関して

|AλE|=0

をAの固有方程式という.


以下の2次正方行列の固有値と固有ベクトルを求めよ.

A=(abcd)

固有方程式は代入すればいいだけなので,

|AλE|=|(1232)(λ00λ)|=|(1λ232λ)|

あとはサラスの公式で計算すればいいだけなので,
=(1λ)(2λ)(23)
=λ23λ4
=(λ+1)(λ4)=0
よってλ=1,4

固有値λ1=1に対する固有ベクトル

p=(p1p2)
(1232)(p1p2)=(1)(p1p2)p1+2p2=p1,3p1+2p2=p2p1=p2

連立方程式を解くと
3p1=3p2=p1=p2となる.
よってスカラーκ0を用いてλ1に対応する固有ベクトルpは次式で与えられる.

p=κ(11)κ0(k0)

また固有値λ2=4に対する固有ベクトルは

q=(q1q2)

上と同じ手順に解くとλ2=4に対する固有ベクトルqが求まる.

q=κ(132)(k0)

寄与率と累積寄与率

次に寄与率についての説明です.第1主成分と第2主成分の定義は以下になります.
第1主成分の寄与率は第1主成分がデータ全体のデータの散らばり具合をどれくらいカバーしているかを表しています.第2主成分以降も同様です.

第1主成分の寄与率 = ()()+(2)
第2主成分の寄与率 = (2)()+(2)

一般に第i主成分までの定義は以下になります.
第i主成分の寄与率 = li = li
総分散 = Σi=1nli (ただし liは第i固有値)

累積寄与率

累積寄与率とは,第1主成分から第m主成分までの寄与率の和です.
第1主成分から第m主成分での圧縮がデータの散らばり具合をどの程度カバーしているかの説明する割合です.(1に近ければデータの散らばり具合を説明できている割合が高いことになります.)

第1主成分から第m主成分までの累積寄与率 = l1+l2++lm

(分散共分散行列で求めた固有値は,主成分方向の分散に対応します.)


実際に応用して見る.

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
pca_github_star.py
# 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()

主成分得点をプロットすると以下のグラフになる.

pca_kekka2.png

x軸に相当するのが給料と見ることができるでしょう.y軸に相当する方向の解釈が難しいですが,よーくデータ分布を見るとJavaができて給料がそこそこの人が高くなる傾向にあるように見ることができそうです.黒の人は給料は高いがpythonで勝負している人と解釈できそうだ.ピンクさんは給料が高くpythonよりもjavaが得意な人と見ることができそうです.
他の人たちもだいたい同じ規則でしたがっていそうです.

まとめ

最後のはデータをQiitaのアドベントカレンダーように急いで作ったのであくまで参考程度に解釈してほしい.自然のリアルなデータだと主成分分析は気づかない特徴を調査することができるので使えるだろう.またカーネルPCAなどもあるが私の現在のレベルでは難しいのでもう少しレベルアップしたらどこかで書きたい.
また,主成分分析では主成分軸を見つけて関係している因子を自分で解釈するが,逆の発想で因子を自分で仮定して推定する手法に因子分析というものがある.それはおいおい書けたら書きたいと思う.

参考文献

統計科学研究所R主成分分析.ppt から数式など参照させてもらいました.

固有値の計算手順や主成分分析の考え方などの文言など.
線形代数学に基づくデータ分析法: 原田 史子,島川 博光

1502080083
Research machine learning. I'm a student at HIU B4.