PCA
Kernel PCAの説明に入る前にPCAとは何か、ざっとおさらいしたいと思います。
PCAとは?
PCA(Principle Component Analysis)/主成分分析は、機械学習で主にデータの次元を減らすのに使われるテクニックです。「次元の呪い」としても知られるよう、特徴量が多すぎると学習に支障をきたします。なので、「不必要な特徴量はなるべく取り除きたい。本当に必要な特徴量だけを使いたい」のです。
PCAのメカニズム
各$x_i$がD次元(D個の特徴量)ベクトルのデータセットがあるとします。これをM次元に写すのに、y = Ax となる $A = [u_1^{T}, ... u_M^{T}]$、$u_k^{T}u_k = 1, k = 1,2... M$ があるとします。この時、PCAでは$y_i$の分散が最大になるAをみつけます。
A^* = argmax tr(S_y)
S_y=\dfrac {1}{N}\sum ^{N}_{i=1}\left( y_{i}-\overline {y}\right) \left( y_{i}-\overline {y}\right) ^{T}
\overline {y} = \dfrac {1}{N}\sum ^{N}_{i=1}x_i
$S_x$をSの分散共分散行列とした時、$tr(S_y) = tr(AS_xA^T)$により、ラグランジ定数を使い微分すると、下のような固有値ベクトル $u_k$による式になります。
S_xu_k = \lambda_ku_k
このように、PCAではxの分散が最大になるような固有値をとることで、特徴量を絞り出すことができます。
この固有値ベクトルによる写像は、下のような回転写像になります。
縦と横の広がりである、それぞれの特徴量の分散だけが残ったことがわかります。
Kernel PCA
上記のPCAでは、線形分離できるデータに対して次元削除を行いましたが、データが線形分離できない時に Kernel PCAを使います。
D次元の特徴量をもつデータをM次元に写す$\phi (x)$があるとします。この時、スタンダードなPCAを新たな次元空間で行うこともできますが、大変なので、カーネルトリックを使います。
まず、写像後の特徴量は平均0をとると仮定します。
\dfrac {1}{N}\sum ^{N}_{i=1} \phi(x_i) = 0
この時、分散共分散は
C = \dfrac {1}{N}\sum ^{N}_{i=1} \phi(x_i)\phi(x_i)^T
となります。
固有値ベクトル$v_i$は、下の式から求めることができます。
Cv_k = \lambda_k v_k
例えば、下のように、左のデータでは線形分離できませんが、カーネルを使うことで、線形分離可能になります。
scikit learn Kernel PCA
パラメター | 概要 | 選択肢 | デフォルト |
---|---|---|---|
n_components | ターゲットの次元数 | int | None(そのまま) |
kernel | カーネルタイプ | “linear” ,“poly” , “rbf” ,“sigmoid” ,“cosine” | "linear" |
gamma | rbfとpolyのカーネル係数 | float | 1/n_features |
degree | polyの係数 | int | 3 |
coef0 | polyとsigmoidの独立係数 | float | 1 |
kernel_params | カーネルのパラメターの名前 | Stringからのmapping | None |
alpha | リッジ回帰 | 1.0 | |
eigen_solver | 固有値の選択 | "auto", "dense", "arpack" | "auto" |
tol | arpackの収束 | float | 0 |
max_iter | arpackの最大反復回数 | int | None |
remove_zeros | 固有値0の削除 | bool | False |
random_state | arpackでのrandom_state | RandomState Instance or None | None |
n_jobs | 並列作業 | int/None | None |
使用例
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA, KernelPCA
from sklearn.datasets import make_circles
np.random.seed(0)
X, y = make_circles(n_samples=400, factor=.3, noise=.05)
plt.figure(figsize=(10,10))
plt.subplot(2, 2, 1, aspect='equal')
plt.title("Original space")
reds = y == 0
blues = y == 1
plt.scatter(X[reds, 0], X[reds, 1], c="red",s=20, edgecolor='k')
plt.scatter(X[blues, 0], X[blues, 1], c="blue",s=20, edgecolor='k')
plt.xlabel("$x_1$")
plt.ylabel("$x_2$")
-> 線形分裂できない。。。
RBFカーネル!
kpca = KernelPCA(kernel="rbf", fit_inverse_transform=True, gamma=10)
X_kpca = kpca.fit_transform(X)
pca = PCA()
X_pca = pca.fit_transform(X)
plt.scatter(X_kpca[reds, 0], X_kpca[reds, 1], c="red",s=20, edgecolor="k")
plt.scatter(X_kpca[blues, 0], X_kpca[blues, 1], c="blue",s=20, edgecolor="k")
x = np.linspace(-1, 1, 1000)
plt.plot(x, -0.1*x, linestyle="solid")
plt.title("Projection by KPCA")
plt.xlabel(r"1st PC induced by $\phi$")
plt.ylabel("2nd component")
分割後:
PCAの利点と欠点
利点
- 特徴量間の関係を無視できる。
- 学習がシンプルで速くなる。
- 過学習を防ぐ。
- より理解しやすい可視化。
欠点
- 元々の特徴量の解釈が難しくなる。
- 正規化が必要。
引用
Quan Wang, "Kernel Principal Component Analysis and its Applications in Face Recognition and Active Shape Models", 2014
https://arxiv.org/pdf/1207.3538.pdf