技術メモ

役に立てる技術的な何か、時々自分用の覚書。幅広く色々なことに興味があります。

scikit-learnで主成分分析(累積寄与率を求める)

pythonのライブラリでおなじみ、scikit-learnで主成分分析をする方法。
最終的には累積寄与率をプロットできるようにしたい。

タスクとしては基本的な手書き文字認識を題材にする。

基本

import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style("whitegrid")

import sklearn.decomposition # PCAで使うはこれだけ
import sklearn.datasets


data = sklearn.datasets.load_digits(n_class=5) # sklearnに付属の手書き文字データ
pca = sklearn.decomposition.PCA(n_components=2)
pca.fit(data.data)

ここで用意したデータはscikitlearnに付属している手書き文字データ。今回はプロットしやすいようにラベル数は5個にしておいた。
基本的な(主成分分析を扱う)部分は最後の2行だけ。

※seabornって何?って思った人はこちら:グラフが綺麗に描けるpythonのライブラリseabornを使うとグラフを描くのが楽しくなる - 技術メモ

2成分プロット

第一主成分と第二主成分を軸にとって二次元プロットする方法。

pca_point = pca.fit_transform(data.data)
color = ["r","c","m","b","g"]
plt.scatter(*pca_point.T, marker=".", color=map(lambda x:color[x], data.target))
plt.xlabel("PC1")
plt.ylabel("PC2")
plt.show()

重要なところは最初の一行。元データを主成分でなす空間に射影する関数。
f:id:swdrsker:20161216022815p:plain
第2主成分まででも結構分けられるんだね。

寄与率・累積寄与率

第一成分、第二成分の基底ベクトルの具体的な値を見る

pca.components_

寄与率を見て、累積寄与率をプロットしてみる。

pca = sklearn.decomposition.PCA()
pca.fit(data.data)
ev_ratio = pca.explained_variance_ratio_
ev_ratio = np.hstack([0,ev_ratio.cumsum()])
plt.plot(ev_ratio)
plt.show()

今回は第3成分以降も取りたかったので引数は与えない形にした。
寄与率は3行目の方法で出てくる。これはnumpyのarrayで格納されているので、numpyの累積和を求める関数(cumsum())が使えるというのがポイント。また、あえて先頭に0を加えることで原点を通るようにしている。
f:id:swdrsker:20161216022840p:plain:w500

感想

こんな簡単に分析できるなんてscikit-learnすごい!グリッドを入れたらグラフが見やすい!seabornすごい!グラフが綺麗に描けるpythonのライブラリseabornを使うとグラフを描くのが楽しくなる - 技術メモ

補足

手書き文字データの中身を見てみる
plt.figure()
for i in range(1,11):
    plt.subplot(2,5,i)
    plt.imshow(data.images[i], cmap="gray")
plt.show()

f:id:swdrsker:20170614175630p:plain

参考サイト:
PythonでMNISTを利用する方法まとめ - Qiita
sklearn.datasets.load_digits — scikit-learn 0.20.1 documentation
sklearn.decomposition.PCA — scikit-learn 0.20.1 documentation