u++の備忘録

『画像認識』における統計的特徴抽出手法の可視化 Pythonでの実装

 『画像認識』(機械学習プロフェッショナルシリーズ)の第3章「統計的特徴抽出」に登場した手法について、Pythonで実装しようと思います。

www.kspub.co.jp

 この章で紹介されている手法は、以下の5つです。

  1. 主成分分析
  2. 白色化
  3. フィッシャー線形判別分析
  4. 正準相関分析
  5. 偏最小2乗法

 データセットとしては、iris datasetを使います。

import matplotlib.pyplot as plt
from sklearn import datasets

iris = datasets.load_iris()

Y = iris.target
X = iris.data[:,2:]
length = X[:,0]
breadth = X[:,1]

plt.plot(length[0:50],breadth[0:50],'o',label='setosa')
plt.plot(length[50:100],breadth[50:100],'o',label='versicolor')
plt.plot(length[100:150],breadth[100:150],'o',label='virginica')
plt.xlim([0,8])
plt.ylim([-1,3])
plt.xlabel('length')
plt.ylabel('breadth')
plt.legend(loc='lower right')
plt.show()

f:id:upura:20170722154250p:plain

1. 主成分分析

主成分分析(principle component analysis, PCA)は,線型空間におけるデータの分布をある基準で最もよく近似する,低次元の部分空間を求める次元削減法です

 この章では、分散最大化を基準とした主成分分析を紹介しています。
 詳細は割愛しますが、ざっくりと説明すると分散(データの散らばり)の大きい方向で新しい評価軸を見つけ、データを再構成する手法です。

# PCA
from sklearn.decomposition import PCA
pca = PCA(n_components = 2)
pca.fit(X)
X_pca = pca.transform(X)

plt.plot(X_pca[0:50,0],X_pca[0:50,1],'o',label='setosa')
plt.plot(X_pca[50:100,0],X_pca[50:100,1],'o',label='versicolor')
plt.plot(X_pca[100:150,0],X_pca[100:150,1],'o',label='virginica')
plt.xlim([-4,4])
plt.ylim([-2,2])
plt.xlabel('PC1')
plt.ylabel('PC2')
plt.title('PCA')
plt.legend(loc='lower right')
plt.show()

f:id:upura:20170722154421p:plain

2. 白色化

主成分分析の応用例として白色化(whitening)があげられます.白色化とは,異なる変数を無相関化しスケールをそろえる手法で,データの前処理として頻繁に活用されます

# whitening
import numpy as np

mean = np.mean(X,0)
cov = np.cov(X, rowvar=0)
v, S = np.linalg.eig(cov)
Lambda = np.dot(np.dot(np.linalg.inv(S), cov), S)
xmu =  X - mean
Lambda_invhalf = np.linalg.inv(np.sqrt( np.diag (Lambda) ) * np.identity(2))
X_whiten =xmu.dot(S).dot(Lambda_invhalf.transpose())

plt.plot(X_whiten[0:50,0],X_whiten[0:50,1],'o',label='setosa')
plt.plot(X_whiten[50:100,0],X_whiten[50:100,1],'o',label='versicolor')
plt.plot(X_whiten[100:150,0],X_whiten[100:150,1],'o',label='virginica')
plt.xlim([-3,3])
plt.ylim([-4,4])
plt.title('whiten')
plt.legend(loc='lower right')
plt.show()

f:id:upura:20170722161331p:plain

3. フィッシャー線形判別分析

フィッシャー線形判別分析(Fisher linear discriminant analysis, Fisher LDA)は,教師情報が得られたときに,クラスの分離を強調するような射影を求める次元削減法です

 主成分分析はデータ全体の散らばりを最大化するような空間への変換を行いますが、これは必ずしも分類に適した変換とは限りません。
 フィッシャー線形判別分析は各クラス内分散を最大化する手法です。

 次の記事の説明が、イメージをつかみやかったです。
s0sem0y.hatenablog.com

# Fisher LDA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
lda = LinearDiscriminantAnalysis(n_components=2)
lda.fit(X, Y)
X_lda = lda.transform(X)

plt.plot(X_lda[0:50,0],X_lda[0:50,1],'o',label='setosa')
plt.plot(X_lda[50:100,0],X_lda[50:100,1],'o',label='versicolor')
plt.plot(X_lda[100:150,0],X_lda[100:150,1],'o',label='virginica')
plt.title('Fisher LDA')
plt.legend(loc='lower right')
plt.show()

f:id:upura:20170722170414p:plain

[追記 170726]
ちなみにn=1のときは、次のような結果を得ました。

# Fisher LDA n=1
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
lda = LinearDiscriminantAnalysis(n_components=1)
lda.fit(X, Y)
X_lda = lda.transform(X)

plt.plot(X_lda[0:50,0],'o',label='setosa')
plt.plot(X_lda[50:100,0],'o',label='versicolor')
plt.plot(X_lda[100:150,0],'o',label='virginica')
plt.title('Fisher LDA (n=1)')
plt.legend(loc='lower right')
plt.show()

f:id:upura:20170726081516p:plain

[追記終]

4. 正準相関分析

正準相関分析(canonical correlation analysis, CCA)は,複数の情報源に共通して含まれる情報を抽出する次元削減方法です.射影された2つの変量の相関が高くなるような線形部分空間を求めます

# CCA
from sklearn.cross_decomposition import CCA
cca = CCA(n_components=2)
cca.fit(X, Y)
X_cca = lda.transform(X)

plt.plot(X_cca[0:50,0],X_cca[0:50,1],'o',label='setosa')
plt.plot(X_cca[50:100,0],X_cca[50:100,1],'o',label='versicolor')
plt.plot(X_cca[100:150,0],X_cca[100:150,1],'o',label='virginica')
plt.xlim([-8,9])
plt.ylim([-4,4])
plt.title('CCA')
plt.legend(loc='lower right')
plt.show()

f:id:upura:20170722171446p:plain

5. 偏最小2乗法

偏最小2乗法(partial least squares, PLS)は正準相関分析と同様に,複数情報源に共通して含まれる情報を抽出する方法です.ただし,正準相関分析は2変量の相関最大化で定式化されますが,偏最小2乗法は2変量の共分散最大化で定式化されます

# PLS
from sklearn.cross_decomposition import PLSRegression
pls2 = PLSRegression(n_components=2)
pls2.fit(X, Y)
X_pls = pls2.transform(X)

plt.plot(X_pls[0:50,0],X_pls[0:50,1],'o',label='setosa')
plt.plot(X_pls[50:100,0],X_pls[50:100,1],'o',label='versicolor')
plt.plot(X_pls[100:150,0],X_pls[100:150,1],'o',label='virginica')
plt.xlim([-3,3])
plt.ylim([-1,1])
plt.title('PLS')
plt.legend(loc='lower right')
plt.show()

f:id:upura:20170722172059p:plain

おわりに

 正直なところ、各手法の特徴が可視化された結果のどこに現れているかは、まだ十分に読み取れていません。その辺りを今後分析し、追記していく予定です。