🔥

主成分分析(PCA)と主成分回帰(PCR)、関係の深い前処理の一覧を添えて

2021/07/05に公開

はじめに

使うだけなら以下のコードを実行すればいいです。

import numpy as np

# 行列の縦・横・ランク
m = 200
n = 100
p = 20

# ランダムな直交行列生成のテクニック
U = np.linalg.qr(np.random.normal(m, p))[0]
V = np.linalg.qr(np.random.normal(n, p))[0]
s = np.logspace(4, -2, p)

# 疑似データの生成
X = U.dot(np.diag(s)).dot(V.T)
# PCA
from sklearn.decomposition import PCA

# 主成分分析
model = PCA(n_components=10)
model.fit(X)

# 主成分
print(model.components_)

# 寄与率
print(model.explained_variance_ratio_)
# PCR
from sklearn.decomposition import PCA
from sklearn.linear_model import Ridge

# 次元削減
pca = PCA(n_components=10)
X_pca = pca.fit_transform(X)

# 回帰
model = Ridge()
model.fit(X_pca, y)

主成分分析(PCA: Principal Component Analysis)

主成分分析はデータを表す行列Aの共分散行列Sの固有値分解です。データを表す行列Am \times nの行列で、ここでは Python に合わせて各行にn次元のデータがひとつ記録されている形式、つまり

A = \left( \begin{matrix} a _ {1} ^ {(1)} & a _ {2} ^ {(1)} & \cdots & a _ {n} ^ {(1)} \\ a _ {1} ^ {(2)} & a _ {2} ^ {(2)} & \cdots & a _ {n} ^ {(2)} \\ \vdots & \vdots & \ddots & \vdots \\ a _ {1} ^ {(m)} & a _ {2} ^ {(m)} & \cdots & a _ {n} ^ {(m)} \end{matrix} \right)

の状況を考えます。このときデータの共分散行列S \in \mathbb{R} ^ {n \times n}

S = \frac{(A - \mu) ^ {\mathrm{T}} (A - \mu)}{m}

で定義されます。ただし\muはデータの平均

\mu = \frac{1}{m} \sum _ {i=1} ^ m a ^ {(i)}

を表し、A - \muAの各データから\muを引いたもの、つまり

A - \mu = \left( \begin{matrix} a _ {1} ^ {(1)} - \mu _ 1 & a _ {2} ^ {(1)} - \mu _ 2 & \cdots & a _ {n} ^ {(1)} - \mu _ n \\ a _ {1} ^ {(2)} - \mu _ 1 & a _ {2} ^ {(2)} - \mu _ 2 & \cdots & a _ {n} ^ {(2)} - \mu _ n \\ \vdots & \vdots & \ddots & \vdots \\ a _ {1} ^ {(m)} - \mu _ 1 & a _ {2} ^ {(m)} - \mu _ 2 & \cdots & a _ {n} ^ {(m)} - \mu _ n \end{matrix} \right)

を意味します。一般に、正方行列が与えられたとき、その行列が固有値分解できるとは限りませんが、共分散行列は必ず固有値分解することが可能で、その固有値は\lambda _ r \geq 0を満たすことが保証されています(共分散行列の半正定値性)。

共分散行列Sを固有値分解すると、直交行列X \in \mathbb{R} ^ {n \times n}と対角行列\Lambda \in \mathbb{R} ^ {n \times n}を用いて

S = X ^ \mathrm{T} \Lambda X = \left( \begin{matrix} x _ {1} ^ {(1)} & x _ {1} ^ {(2)} & \cdots & x _ {1} ^ {(n)} \\ x _ {2} ^ {(1)} & x _ {2} ^ {(2)} & \cdots & x _ {2} ^ {(n)} \\ \vdots & \vdots & \ddots & \vdots \\ x _ {n} ^ {(1)} & x _ {n} ^ {(2)} & \cdots & x _ {n} ^ {(n)} \end{matrix} \right)\left( \begin{matrix} \lambda _ 1 & 0 & \cdots & 0 \\ 0 & \lambda _ 2 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & \lambda _ n \end{matrix} \right)\left( \begin{matrix} x _ {1} ^ {(1)} & x _ {2} ^ {(1)} & \cdots & x _ {n} ^ {(1)} \\ x _ {1} ^ {(2)} & x _ {2} ^ {(2)} & \cdots & x _ {n} ^ {(2)} \\ \vdots & \vdots & \ddots & \vdots \\ x _ {1} ^ {(n)} & x _ {2} ^ {(n)} & \cdots & x _ {n} ^ {(n)} \end{matrix} \right)

と表すことができます。ただし\lambda _ 1 \geq \lambda _ 2 \geq \cdots \geq \lambda _ n \geq 0とします。このXを行列Aの主成分といい、x ^ {(r)}を第r主成分といいます。

また、固有値\lambda _ rの 2 乗である\lambda _ r ^ 2を、第r主成分の寄与度といいます。共分散行列Sの Frobenius ノルム\| S \| _ Fと寄与度の間には、以下の関係が成り立ちます。

\| S \| _ F = \sqrt{ \sum _ {r = 1} ^ n \lambda _ r ^ 2}

ただし行列の Frobenius ノルム\| \cdot \| _ Fは、行列A \in \mathbb{R} ^ {m \times n}について以下で定義されます。

\| A \| _ F = \sqrt{ \sum _ {i = 1} ^ m \sum _ {j = 1} ^ n a _ {ij} ^ 2 }

いま、第p主成分までを用いて共分散行列S

S _ {(p)} = X _ {(p)} ^ \mathrm{T} \Lambda _ {(p)} X _ {(p)} = \left( \begin{matrix} x _ {1} ^ {(1)} & x _ {1} ^ {(2)} & \cdots & x _ {1} ^ {(p)} \\ x _ {2} ^ {(1)} & x _ {2} ^ {(2)} & \cdots & x _ {2} ^ {(p)} \\ \vdots & \vdots & \ddots & \vdots \\ x _ {n} ^ {(1)} & x _ {n} ^ {(2)} & \cdots & x _ {n} ^ {(p)} \end{matrix} \right)\left( \begin{matrix} \lambda _ 1 & 0 & \cdots & 0 \\ 0 & \lambda _ 2 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & \lambda _ p \end{matrix} \right)\left( \begin{matrix} x _ {1} ^ {(1)} & x _ {2} ^ {(1)} & \cdots & x _ {n} ^ {(1)} \\ x _ {1} ^ {(2)} & x _ {2} ^ {(2)} & \cdots & x _ {n} ^ {(2)} \\ \vdots & \vdots & \ddots & \vdots \\ x _ {1} ^ {(p)} & x _ {2} ^ {(p)} & \cdots & x _ {n} ^ {(p)} \end{matrix} \right)

で近似することを考えます。このときやはり

\| S _ {(p)} \| _ F = \sqrt{ \sum _ {r = 1} ^ p \lambda _ r ^ 2}

が成り立ちます。これらの事実から、\| S \| _ F\| S _ {(p)} \| _ Fを用いて、第r主成分まででどれくらいSの情報を復元できているかを表す尺度を、たとえば

C = \frac{\| S _ {(p)} \| _ F}{\| S \| _ F} = \sqrt{\frac{ \sum _ {r = 1} ^ p \lambda _ r ^ 2}{ \sum _ {r = 1} ^ n \lambda _ r ^ 2}}

のように定義することができます。主成分分析では、これを 2 乗した

C ^ 2 = \frac{ \sum _ {r = 1} ^ p \lambda _ r ^ 2}{ \sum _ {r = 1} ^ n \lambda _ r ^ 2}

を累積寄与率と呼び、よく用います。

白色化

標準化のパワーアップ版が、主成分分析を用いた白色化です。PCR は白色化の一歩手前くらいの無相関化(した変数を一部だけ取り出す次元削減)という前処理を行ってから線形回帰にかけるモデルです。

次元削減は多重共線性のあるデータに対して有効なことがあります。SVR などのカーネル法に基づく回帰にも用いたいと思うかもしれませんが、その場合は無相関化だけでは不十分で、白色化までやらないと意味がありません。

この機会にいろいろな前処理を紹介しておきましょう。

平均化(averaging)

平均化はデータからそのデータの平均を引く操作です。データをA \in \mathbb{R} ^ {m \times n}として、その平均を\muと置くと、行列Aを平均化した行列A _ {\rm ave}

A _ {\rm ave} = A - \mu

で表すことができます。正直スカラー倍はどうでもいいのですが、共分散行列を

S = A _ {\rm ave} ^ \mathrm{T} A _ {\rm ave}

で定義したいので、

A _ {\rm ave} = \frac{1}{\sqrt{m}}(A - \mu)

としておきます。

標準化(standardization)

標準化はデータを平均化した上で、各変数をその標準偏差で割る操作です。各変数の標準偏差が対角行列に入った行列を

\Sigma = \left( \begin{matrix} \sigma _ 1 & 0 & \cdots & 0 \\ 0 & \sigma _ 2 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & \sigma _ n \end{matrix} \right)

とすると、行列Aを標準化した行列A _ {\rm std}

A _ {\rm std} = A _ {\rm ave} \Sigma ^ {-1}

と書くことができます。標準化済みの行列は、その共分散行列の対角成分が1になり、相関行列に一致します。

S _ {\rm std} = A _ {\rm std} ^ \mathrm{T} A _ {\rm std} = \left( \begin{matrix} 1 & s _ {12} & \cdots & s _ {1n} \\ s _ {21} & 1 & \cdots & s _ {2n} \\ \vdots & \vdots & \ddots & \vdots \\ s _ {n1} & s _ {n2} & \cdots & 1 \end{matrix} \right)

s _ {ij}i番目の変数とj番目の変数の相関係数です。

無相関化(uncorrelation)

無相関化はデータを平均化した上で、右から主成分Xの逆行列X ^ {-1} = X ^ \mathrm{T}をかける操作です。

A _ {\rm unc} = A _ {\rm ave} X ^ {-1} = A _ {\rm ave} X ^ \mathrm{T}

無相関化は標準化の\SigmaXに替わったものとみなすことができます。無相関化された変数の共分散行列は対角行列になり、その対角成分は共分散行列S = A_ {\rm ave} ^ \mathrm{T} A _ {\rm ave}の固有値になります。

証明は難しくありません。主成分分析は共分散行列Sの固有値分解に等しいので

S = X ^ {\mathrm{T}} \Lambda X

が成り立ちます。両辺の左からX、右からX ^ \mathrm{T}をかければ、

\Lambda = X S X ^ \mathrm{T}

となります。いまS = A_ {\rm ave} ^ \mathrm{T} A _ {\rm ave}であったことを思い出せば、

\Lambda = X A _ {\rm ave} ^ \mathrm{T} A _ {\rm ave} X ^ \mathrm{T} = (A _ {\rm ave} X ^ \mathrm{T}) ^ \mathrm{T} (A _ {\rm ave} X ^ \mathrm{T}) = A _ {\rm unc} ^ \mathrm{T} A _ {\rm unc}

です。A _ {\rm unc} ^ \mathrm{T} A _ {\rm unc}は行列A _ {\rm unc}の共分散行列を表しているので、無相関化したデータの共分散行列は対角行列となり、その対角成分は共分散行列S = A_ {\rm ave} ^ \mathrm{T} A _ {\rm ave}の固有値となることが示されました。

次元削減(dimensionality reduction)

次元削減の方法はたくさんありますが、その中でも主成分分析よる次元削減は、いくつかの主成分を削ったX _ {(p)}を用いて無相関化を行います。

A _ {{\rm dim}(p)} = A _ {\rm ave} X _ {(p)} ^ \mathrm{T}

白色化(whitening)

白色化はデータを無相関化した上で、その共分散行列の対角成分が1になるように右から\Lambda ^ {- \frac{1}{2}}をかける操作です。

A _ {\rm wht} = A _ {\rm unc} \Lambda ^ {- \frac{1}{2}}

ここで\Lambdaは共分散行列Sの固有値を対角成分に持つ行列であり、\lambda _ rを第r固有値とすると、\Lambda ^ {- \frac{1}{2}}

\Lambda ^ {- \frac{1}{2}} = \left( \begin{matrix} \frac{1}{\sqrt{\lambda _ 1}} & 0 & \cdots & 0 \\ 0 & \frac{1}{\sqrt{\lambda _ 2}} & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & \frac{1}{\sqrt{\lambda _ n}} \end{matrix} \right)

で定義されます。白色化した行列の共分散行列は単位行列になります。これも証明は簡単で、

S _ {\rm wht} = A _ {\rm wht} ^ \mathrm{T} A _ {\rm wht} = \Lambda ^ {- \frac{1}{2}} A _ {\rm unc} ^ \mathrm{T} A _ {\rm unc}\Lambda ^ {- \frac{1}{2}} = \Lambda ^ {- \frac{1}{2}} \Lambda \Lambda ^ {- \frac{1}{2}} = I _ n

です。共分散行列が単位行列になるのはデータがホワイトノイズから生成しているときの特徴であり、データをホワイトノイズと同じ性質を持つ信号に変えてしまうことから「白色化(whitening)」という名前がつけられています。

ZCA白色化(Zero-phase Component Analysis Whitening)

ZCA白色化(ゼロ位相白色化)は、白色化したデータの右から主成分Xをかける操作です。

A _ {\rm zca} = A _ {\rm wht} X

行列に直交行列をかける操作はある種の「回転」に相当する操作であり、通常の白色化は元のデータからX ^ \mathrm{T}の分だけ「回転」してしまっています(対角行列は拡大縮小だけで回転はしません)。

A _ {\rm wht} = A _ {\rm mean} X ^ \mathrm{T} \Lambda ^ {- \frac{1}{2}}

そこで回転X ^ \mathrm{T}の反対回転であるXをかけて、元のデータからの「回転」を打ち消してやろう、というのがZCA白色化です。

A _ {\rm zca} = A _ {\rm mean} X ^ \mathrm{T} \Lambda ^ {- \frac{1}{2}} X

元の位置からの回転ズレの度合いのことを「位相(phase)」と呼ぶわけですが、元のデータからの回転ズレの度合いが0になるよう補正したので「ゼロ位相」という名前がついています。

ZCA白色化をしても共分散行列は単位行列のままです。

A _ {\rm zca} ^ \mathrm{T} A _ {\rm zca} = X ^ \mathrm{T} A _ {\rm wht} ^ \mathrm{T} A _ {\rm wht} X = X ^ \mathrm{T} I _ n X = X ^ \mathrm{T} X = I _ n

これはXが主成分の場合だけでなく、任意の直交行列Qの場合についても成り立つ性質です。白色化には直交行列Qの自由度があると考えることもでき、その中から位相が0になるように選んだのがZCA白色化です。

主成分回帰(PCR: Principal Component Regression)

主成分回帰は、入力データXを次元削減したあとで線形回帰にかけるモデルです。出力データyに関しては平均化してあれば十分です。つまり、

y _ {\rm ave} \approx X _ {{\rm dim}(p)} w

の回帰モデルです。

発展: SVR などにかけるなら

SVR など、カーネル法に基づくモデルを用いるならば、無相関化だけでなく白色化までしたほうがいいです。

Discussion