UFLDL Tutorial 17 Unsupervised Learning – PCA Whitening
PCA Whitening
Introduction
주 성분 분석(Principal Components Analysis, PCA)는 차원을 축소하는 알고리즘으로 특징을 학습하는 비지도학습(unsupervised feature learning) 알고리즘의 속도를 높이는데 사용됩니다. 더욱 중요한 점은, PCA를 이해하게 되면 whitening을 구현할 수 있게 된다는 점입니다. 이것은 아주 중요한 많은 알고리즘들의 전처리 과정으로 사용되는 것입니다.
만약 이미지를 이용하여 알고리즘을 훈련시키고 있다고 하여봅시다. 그렇다면 입력되는 데이터는 어느정도 redundant를 가질 것입니다. 왜냐하면 이미지에서 인접한 픽셀들은 서로 높게 관련되어있을 것이기 때문입니다. 자세히 말하자면, 16 * 16 크기의 흑백 이미지 패치를 이용하여 훈련시킨다고 한다면, 입력은 $x \in \Re^{256}$의 256 차원의 벡터가 될 것이고, 각 특징 $x_j$는 각 픽셀의 픽셀 값이 될 것입니다. 인접한 픽셀들간의 관련성(correlation)이 있기 때문에 PCA는 입력 데이터를 더 낮은 차원의 것으로 아주 적은 에러로 근사(approximate)할 수 있도록 해 줍니다.
Example and Mathematical Background
실제로 예제를 돌려보기 위해서 $n=2$차원 입력을 갖는 데이터셋 $ \{ x^{(1)}, x^{(2)}, \cdots, x^{(m)} \}$을 사용할 것입니다. 따라서 $x^{(i)} \in \mathfrak{R}^2$입니다. 이제 이 2차원 데이터를 1차원으로 줄이려 한다고 가정해봅시다. 실제로는 256차원을 50차원 정도로 줄이는 것 같은 수준으로 하게 될 것이지만 여기서는 시각적으로 알아보기 쉽도록 가정한 것입니다. 데이터셋을 표시하면 다음과 같습니다.
이 데이터는 특징 $x_1$와 $x_2$가 같은 평균값 0과 분산 값을 가지도록 전처리 작업이 되어있습니다.
그림으로 표시하기 위해서 각 데이터 점들은 $x_1$ 값에 따라서 3개의 색깔 중 하나로 표시하였으며, 그 색들은 알고리즘에는 영향이 없습니다.
PCA는 원래보다 적은 차원의 부분 공간(subspace)으로 데이터를 사영(proect)합니다. 앞에서 그림으로 표시한 데이터를 보면, 데이터 분산의 주축(principal direction) $u_1$과 두번째 축(secondary direction) $u_2$을 볼 수 있습니다.
다시 말하면, 데이터는 $u_1$과 $u_2$ 방향으로 더 많이 퍼져 있다는 것입니다. 이러한 두 축을 찾으려면 먼저 우리는 행렬 $\Sigma$를 계산하여야 합니다.
$$ \Sigma = \frac{1}{m} \sum_{i=1}^m (x^{(i)})(x^{(i)})^T $$
만약 $x$가 평균 0을 22 $\Sigma$는 $x$의 공분산(covariance) 행렬과 같게 됩니다. 실은 여기서의 $\Sigma$는 시그마(sigma)라고 부르며, 공분산 행렬을 나타내는 표준 기호입니다. 아쉽게도 수열의 합을 타나내는 기호 $\Sigma_{i=1}^n i$와 동일하지만 두가지 다른 점이 있습니다.
$\Sigma$의 첫번째 고유 벡터(eigenvector)가 데이터가 퍼져있는 주 축인 $u_1$이고 $u_2$은 두번째 고유 벡터입니다.
수학적으로 이를 유도하고 증명하는 것에 관심이 있는 사람은 CS229(Machine Learning)의 PCA 강의를 보면 됩니다. 하지만 이 강의에서는 그것을 볼 필요는 없습니다.
선형 대수 프로그램들을 통해서 고유 벡터를 구할 수 있습니다. 좀더 자세히 살펴보면, $\Sigma$의 고유벡터를 구한다고 하였을 때, 고유 벡터를 열 방향으로 쌓아 다음과 같은 $U$ 행렬을 만들 수 있습니다.
$$ U = \begin{bmatrix} | & | & & | \\ u_1 & u_2 & \cdots & u_n \\ | & | & & | \end{bmatrix} $$
여기서 $u_1$은 가장 큰 고유값을 갖는 고유벡터(principal eigenvector)이고, $u_2$는 두번째 고유벡터로 이어지는 순서입니다. 또한 $ \textstyle \lambda_1, \lambda_2, \ldots, \lambda_n $는 그에 해당하는 고유값입니다.
벡터 $u_1$과 $u_2$는 우리 데이터를 표현하는 새로운 기저입니다. 다시 말하면 $x \in \mathfrac{R}^2$가 트레이닝 샘플이라고 하였을 때, $u_1^T x$는 $x$를 $u_1$에 사영하였을 때, 그 사영의 길이(length, magnitude)입니다.
비슷하게 $u_2^T x$는 $x$를 $u_2$에 사용했을 때의 길이입니다.
Rotating the Data
이제 우리는 데이터 $x$를 새로운 기저 $(u_1, u_2$를 사용해서 표현할 수 있습니다.
$$ x_{\text rot} = U^T x = \begin{bmatrix} u^T_1 x \\ u^T_2 x \end{bmatrix} $$
여기서 "rot"는 원래의 데이터를 회전(rotation)했다는 것에서 따온 것입니다. 이것을 전체 트레이닝 셋에 적용해보면, 즉, $x_{\text rot}^{(i)} = U^T x^{(i)}$을 모든 $i$에 대해서 계산합니다. 이렇게 변환된 $x_{\text rot}$를 출력해보면 다음과 같습니다.
이것이 트레이닝 셋을 $u_1, u_2$ 기저에 대해서 회전 시킨 것입니다. 일반적으로 $U^T x$는 트레이닝 셋을 기저들 $u_1, u_2, \cdots, u_n$에 대해서 회전시킵니다.
행렬 $U$의 한 성질은 그것이 직교(orthogonal) 행렬이라는 점입니다. 이는 이 행렬이 $U^T U = U U^T = I$를 만족한다는 뜻입니다. 따라서 $x_{\text rot}$를 원래의 데이터 $x$로 돌려놓을 필요가 있을 경우, 여러분은 단지 $x = U x_{\text rot}$를 계산하면 된다는 뜻입니다. $ U x_{\text rot} = U U^T x = x$이기 때문입니다.
Reducing the Data Dimension
데이터 분포의 주축은 회전 시킨 데이터의 $x_{\text{rot, 1}}$의 첫번째 차원이라는 것을 보았습니다. 따라서 데이터를 1차원으로 축소시키고자 한다면 다음과 같이 사용하면 됩니다.
$$ \tilde{x}^{(i)} = x_{\rm rot,1}^{(i)} = u_1^Tx^{(i)} \in \Re $$
다시 말하면, $x \in \Re^n$이 있고, 이를 $k \lt n$차원의 표현 $\tilde{x} \in \Re^k$로 축소시키고자 한다면, $x_{\text rot}$의 첫번째부터 $k$개의 요소들을 취해서 사용하면 됩니다. 이는 분포가 큰 $k$개의 방향에 해당합니다.
PCA를 설명하는 다른 방법은 $r_{\text{rot}}$가 n차원의 벡터라고 하였을 때, 처음 몇개의 컴포넌트는 매우 큰 값을 갖고 이후의 컴포넌트들은 작은 값을 갖도록 하는 것이라고 할 수 있습니다. 지금 예제에서도 $\textstyle x_{\rm rot,1}^{(i)} = u_1^Tx^{(i)}$는 대부분의 샘플에서 큰 값을 갖고, $\textstyle x_{\rm rot,2}^{(i)} = u_2^Tx^{(i)}$는 그보다 작은 값을 갖습니다. 여기서 PCA가 하는 일은 $r_{\text{rot}}$의 나중에 오는 컴포넌트들을 제거하여 그 값들을 0으로 취급하는 것입니다. 자세히 말하면 $\tilde{x}$는 처음 $k$개를 제외한 나머지 부분의 컴포넌트를 0으로 만들어 $x_{\text{rot}}$의 근사값을 찾는 것이라고 할 수 있습니다.
$$ \begin{align} \tilde{x} = \begin{bmatrix} x_{\rm rot,1} \\ \vdots \\ x_{\rm rot,k} \\ 0 \\ \vdots \\ 0 \\ \end{bmatrix} \approx \begin{bmatrix} x_{\rm rot,1} \\ \vdots \\ x_{\rm rot,k} \\ x_{\rm rot,k+1} \\ \vdots \\ x_{\rm rot,n} \end{bmatrix} = x_{\rm rot} \end{align} $$
우리 예제에서의 $\tilde{x}$를 표시해보면 다음과 같습니다. ($n=2, k=1$)
그렇지만 $\tilde{x}$의 뒤쪽 $n-k$컴포넌트는 항상 0으로 정의되기 때문에 사실은 이것들을 0으로 계속 유지하고 있을 필요가 없습니다. 따라서 앞쪽의 $k$개 컴포넌트만을 이용하여 $k$차원의 벡터로 $\tilde{x}$를 정의하고자 합니다.
이 설명은 왜 우리의 데이터를 $\textstyle u_1, u_2, \ldots, u_n$의 기저로 이루어진 공간에서 표현하려는지의 이유도 내포하고 있습니다. 어떤 컴포넌트를 남길 것인지를 결정하는 것은 상위 $k$개의 컴포넌트를 결정하는 것과 같습니다. 결국 "상위 $k$개의 PCA (혹은 주성분) 컴포넌트를 유지시킨다."라고 말하는 것과 동일한 것입니다.
Recovering an Approximation of the Data
이제 $ \textstyle \tilde{x} \in \Re^k $은 원래의 $\textstyle x \in \Re^k$를 낮은 차원으로 "압축(compressed)된" 표현이라고 이야기할 수 있습니다. 그렇다면 $\textstyle \tilde{x}$가 주어질 경우 어떻게 원래의 $\textstyle x$ 값의 근사하는 $\textstyle \hat{x}$로 복원할 수 있을까요? 앞에서 배운대로 $\textstyle x = u x_{\text{rot}}$임을 알고 있습니다. 또한 $\textstyle \tilde{x}$는 마지막 $n-k$개의 컴포넌트를 0으로 바꾸어서 만든 $\textstyle x_{\text{rot}}$의 추정치임을 알고 있습니다. 따라서 $\textstyle \tilde{x}$가 주어진다면, $\textstyle x_{\text{rot}} \in \Re^n$를 얻기위해서는 그것에 $n-k$개의 0을 붙여야 합니다. 마지막으로 $x$를 얻기 위해서 $U$를 앞에다 곱하여 $x$의 근사값을 얻을 수 있습니다. 식으로 표현하면 아래와 같습니다.
$$ \hat{x} = U \begin{bmatrix} \tilde{x}_1 \\ \vdots \\ \tilde{x}_k \\ 0 \\ \vdots \\ 0 \end{bmatrix} = \sum_{i=1}^k u_i \tilde{x}_i $$
마지막 등호는 앞에서의 $U$의 정의에서 온 것입니다. 실제 구현할 때에는, 0을 벡터에 덧붙인 후 $U$를 곱하는 과정을 진행하지는 않습니다. 벡터의 상당한 부분이 모두 0으로 채워져 있기 때문입니다. 대신, $U$의 앞 $k$개의 컬럼만을 곱하도록 합니다. 이제 이것을 우리 데이터셋에 적용하면, 아래와 같은 $\hat{x}$을 얻게 됩니다.
따라서 여기서 우리는 원래의 데이터셋을 표현하기 위해서 1차원 추정치를 사용하였습니다.
만약 오토엔코더를 훈련시키고자 하거나 비지도 특징 학습 알고리즘(unsupervised feature learning algorithm)을 하고 있다면, 알고리즘의 실행 속도는 입력 값의 차원에 달려 있을 것입니다. 만약 $\tilde{x} \in \Re^k$를 $x$ 대신 알고리즘에 넣으면 트레이닝은 저차원 입력에서 이루어 지기 때문에 알고리즘이 상당히 빨라질 것입니다. 많은 데이터셋에서 저차원의 $\tilde{x}$ 표현은 원래의 데이터셋을 정말 잘 추정할 수 있습니다. 따라서 PCA를 사용하면 아주 적은 추정 에러를 일으키긴 하지만 알고리즘의 속도를 높일 수 있습니다.
Number of components to retain
어떻게 $k$를 정할까요? 다시 말하자면 얼마만큼의 PCA 컴포넌트를 남겨두어야 할까요? 위의 2차원 예제에서는 2개의 컴포넌트 중 하나만을 남기는 것이 자연스럽습니다. 하지만 더 높은 차원의 데이터에서는 이런식으로는 안됩니다. 만약 $k$가 너무 크다면 데이터를 많이 압축하지 못할 것입니다. $k=n$의 한계치에서는 단지 또다른 기저(basis)로 회전되었을 뿐 원래의 데이터를 사용하는 것 다름 없게 됩니다. 하지만 $k$가 너무 작다면, 아주 나쁜 추정치를 얻게 될 것입니다.
$k$를 잘 정하기 위해서는 여러 $k$값에 대해서 "유지된 데이터의 분포 비율(percentage of variance retained)"을 살펴보게 됩니다. 자세히 말하자면, $k=n$에서는 데이터를 정확히 추정하는 추정 값을 가지게 되고 100%의 분포를 유지하게 됩니다. 다시 말하면 원래 데이터의 모든 분포는 유지될 수 있습니다. 하지만 반대로 $k=0$이 되면 모든 데이터의 추정치는 0벡터로 유지되는 분포는 0%입니다.
다시 말해보자면, $\Sigma$의 고유값을 $\textstyle \lambda_1, \lambda_2, \ldots, \lambda_n$라고 하였을 때, $\lambda_j$의 고유벡터가 $u_j$라고 한다면, $k$개의 주성분 콤포넌트를 유지시켰다면 남겨진 분포의 비율은 다음과 같이 계산할 수 있습니다.
$$ \frac{\sum_{j=1}^k \lambda_j}{\sum_{j=1}^n \lambda_j} $$
앞의 2차원 예제에서는 $\lambda_1 = 7.29, \lambda_2 = 0.69$이므로 $k=1$개의 주성분 컴포넌트를 사용하면 $7.29/(7.29+0.69)=0.913$을 얻을 수 있습니다. 이는 곧 91.3%의 분포를 의미합니다.
남겨진 분포의 비율을 정확한 정의는 이 강의의 범주에서 벗어납니다. 하지만 $\lambda_j = \sum_{i=1}^m x^2_{\text{rot}_j}$라는 것은 보일 수 있습니다. 따라서 어떤 $\lambda_j \approx0$이라는 것은 $x_{\text{rot}_j}$가 거의 0에 가깝다는 것을 의미하며, 따라서 값을 추정할때 상대적으로 0에 가까운 값들을 잃게 될 것임을 의미합니다. 또한 이는 우리가 왜 $\lambda_j$가 큰 첫부분의 주요 컴포넌트를 유지해야하는지도 설명해줍니다. 첫부분의 주요 컴포넌트 $x_{\text{rot_j}}$들은 더 산포되어있고, 더 큰 값을 가지게 되며 그것들을 0으로 설정해버리면 더 큰 추정 오차가 발생할 것입니다.
이미지의 경우, 99%의 분포를 유지하도록 하는 $k$를 정하기 위한 한가지 휴리스틱한 방법이 있습니다. 그것은 다음 식을 만족하는 가장 작은 $k$를 고르는 것입니다.
$$ \frac{\sum_{j=1}^k \lambda_j}{\sum_{j=1}^n \lambda_j} \geq 0.99 $$
응용 분야에 따라, 추가적인 에러가 발생하여도 괜찮다면 90-98% 사이의 값을 사용할 때도 있습니다. 다른 사람들에게 PCA를 어떻게 적용하는지 설명할 때에는, $k$를 95%의 분포를 유지하도록 정하였다고 말하는 것이 단순히 120개의 컴포넌트를 유지했다고 하는 것보다 더 이해하기 쉬운 설명이 될 것입니다.
PCA on Images
PCA를 이용하고자 할 때, 보통 우리는 각 특징들 $x_1, x_2, \cdots, x_n$가 다른 것들과 비슷한 범위내의 값들을 가지기, 그리고 평균이 0에 가깝기를 원합니다. 만약 PCA를 다른 응용에 사용해본 적이 있다면 각 특징들을 평균 0과 분산 1을 가지도록 전처리 과정을 별도로 거쳤을지도 모르겠습니다. 원래의 각 특징 $x_j$의 평균과 분산을 계산하여서 말이죠. 하지만 이것은 이미지 유형의 데이터에서 우리가 하고자 하는 전처리는 아닙니다. 정확히 말하면, "보통의 이미지들"을 이용하여 알고리즘을 학습하고자 한다면, 특징 $x_j$는 픽셀$j$의 값이 될것입니다. 여기서 "보통 이미지"라는 것은 동물이나 사람이 살아가는 동안 보게되는 평범한 종류의 이미지를 뜻합니다.
노트: 우리는 보통 잔디, 나무 등과 같을 것들을 가지고 있는 외부 환경의 이미지를 사용합니다. 이들로부터 알고리즘을 훈련시키기 위헤서 그 이미지를 16 * 16 정도의 작은 패치로 잘라내어 사용합니다. 하지만 실제로는 대부분의 특징 학습 알고리즘은 훈련에 사용하는 이미지와 같은 종류의 이미지에 대해서는 강인하므로, 따라서 보통의 카메라에서 얻어지는 대부분의 이미지들에서는, 흐리거나 아니팩트가 없는한 제대로 작동해야 합니다.
보통 이미지에서 훈련을 시킬 때, 각 픽셀에 대해서 별도의 평균과 분산을 추정하는 것은 그다지 올바르지 않아 보입니다. 왜냐하면 이미지의 일부분에서의 통계량은 이론상 다른 부분과 동일할 것이기 때문입니다. 이미지의 이 특징은 "stationarity"라고 부릅니다.
자세히 살펴보면, PCA가 잘 동작하기 위해서는, 흔히 다음의 2가지가 만족되어야 한다고 이야기 합니다. 첫째로 특징은 0에 가까운 평균을 가져야 하고, 다음으로는 여러 다른 특징들은 서로 비슷한 분포를 가져야 합니다. 보통 이미지에서는 두번째 조건은 분산의 정규화(normalization)과정이 없어도 이미 충족하고 있습니다. 따라서 분산 정규화 과정은 하지 않아도 됩니다.
만약 스펙트로그램이나 Bag of word 벡터와 같이 텍스트 데이터 같은 오디오 데이터에서 훈련을 하고자 할 때에도 분산의 정규화는 필요하지 않습니다.
사실은 PCA는 데이터의 스케일링에는 영향을 받지 않습니다. 또한 입력 데이터의 스케일에 상관없이 같은 고유 벡터를 계산하게 됩니다. 더 형식을 갖추어 말하면, 특징 벡터들 $x$에 어떤 양수값을 곱해 모든 특징을 스케일링하여도 PCA가 계산하는 고유벡터는 변하지 않습니다.
따라서 분산 정규화는 사용하지 않을 것입니다. 우리가 해야하는 정규화는 평균 정규화로 특징들의 평균을 0 가까이로 만드는 것입니다. 응용 분야에 따라서 전체 이미지가 얼마나 밝은지는 별 관심이 없을 때가 많습니다. 예를 들면, 물체 인식의 경우 이미지의 전체 밝기는 어떤 물체가 있는지에 대해서 영향을 미치지 않습니다. 더 정확히 말하면 이미지 패치의 픽셀 값 평균에는 별 관심이 없습니다. 따라서 평균 정휴과를 위해서 어떤 값을 뺄 수 있게 됩니다.
자세히 말하면, 16 * 16 패치 $n=256$의 $x^{(i)} \in \Re^n$인 픽셀 값이 있다면, 각 이미지 패치 $x^{(i)}$를 정휵화 하기 위해서 모든 $j$에 대해 다음과 같이 할 수 있습니다.
$$ \mu^{(i)} := \frac{1}{n} \sum_{j=1}^n x^{(i)}_j $$
$$ x^{(i)}_j := x^{(i)}_j - \mu^{(i)} $$
위의 두 단계는 각 이미지 패치 $x^{(i)}$에 대해서 별도로 이루어지는 것입니다. 여기서 $\mu^{(i)}$는 이미지 패치 $x^{(i)}$의 평균 픽셀 값입니다. 특별히 이것은 각 픽셀 $x_j$의 평균 값을 추정하는 것과는 다른 행위입니다.
만약 보통 이미지가 아닌 손글씨나, 배경이 희고 물체가 중앙에 오도록 분리작업이 된 이미지를 이용하고 있다면 다른 형태의 정규화가 고려되어야 합니다. 가장 좋은 방법은 응용분야에 맞추어서 결정하여야 합니다. 하지만 보통 이미지를 훈련할 경우, 위에서 설명한 이미지마다의 평균 정규화를 수행하는 것은 기본적으로 사용되는 것입니다.
Whitening
앞에서 우리는 데이터의 차원을 줄이기 위해서 PCA를 사용하였습니다. 이것은 어떤 알고리즘에서 쓰이는 whitening 혹은 sphering이라고 불리는 전처리 과정과 밀접한 관계가 있습니다. 우리가 이미지에서 훈련을 시킬 때, 이미지를 입력으로 그대로 사용하는 것은 dedundant를 가집니다. 인접한 픽셀들을 높은 관련성이 있기 때문입니다. Whitening의 목표는 입력의 redundant를 줄이도록 하는 것입니다. 다시 말하자면 학습 알고리즘이 트레이닝 입력을 보았을 때, 특징들이 다른 특징들과 서로 덜 관련되(correlated)도록 하고, 또한 서로 같은 분산 값을 가지도록 하는 것입니다.
2D example
먼저 앞에서 했던 2D 예제에서 whitening을 이야기해보고자 합니다. 그 다음 이것을 스무딩(smoothing)과 어떻게 통합할 수 있는지 알아보고 마지막으로 PCA와도 통합해볼 것입니다.
우리가 가진 입력 특징들을 서로 관련성을 적도록 하려면 어떻게 해야할까요? 이미 우리는 $\textstyle x_{\rm rot}^{(i)} = U^Tx^{(i)}$을 계산하면서 이 작업을 하였습니다.
이전의 $x_{\rm rot}$을 표시한 그림을 다시 살펴봅시다.
이 때, 이 데이터의 covariance 행렬은 다음과 같습니다.
$$ \begin{bmatrix} 7.29 & 0 \\ 0 & 0.69 \end{bmatrix} $$
기술적으로 보면, 이 장에서 언급된 "covariance"는 데이터들이 평균이 0을 가질 때만 성립합니다. 남은 내용에서도 따로 언급하지 않는한 이런 가정을 가지고 설명하도록 하겠습니다. 하지만 데이터의 평균이 정확하게 0이 아니더라도, 근본적으로 설명하고자 하는 것은 여전히 성립할 수 있습니다. 따라서 이 부분에 대해서는 걱정하지 앟ㄴ아도 됩니다.
여기서 대각 성분이 $\lambda_1, \lambda_2$인 것은 우연한 일이 압니다. 더군다나 나머지 성분들은 0입니다. 따라서 $ \textstyle x_{\rm rot,1} $와 $\textstyle x_{\rm rot,2}$는 서로 상관관계가 없기 때문에, 우리가 원하는 whitened data로써의 원하는 성질을 만족합니다.
각 입력 특징의 분산을 1로 만들기 위해서, 각 특징 $ \textstyle x_{\rm rot,i}$를 $1 / \sqrt{\lambda_i}$로 리스케일해줍니다. 다시말하면 우리가 원하는 whitened data $ \textstyle x_{\rm PCAwhite} \in \Re^n $ 를 다음과 같이 정의할 수 있습니다.
$$ x_{\rm PCAwhite,i} = \frac{x_{\rm rot,i} }{\sqrt{\lambda_i}} $$
$ x_{\rm PCA_{white}}$을 출력해보면 다음과 같습니다.
이 데이터는 이제 covariance 행렬이 identity matrix $I$가 되었습니다. 이 $ x_{\rm PCA_{white}}$를 이제부터 PCA whitened된 버전의 데이터라고 부르고자 합니다. $ x_{\rm PCA_{white}}$의 각 컴포넌트는 서로 상관성이 없고 고정된 분산값 1을 갖습니다.
Whintening combined with dimensionality reduction
Whitened된 데이터를 구하고 싶고, 이것이 원래 입력보다 낮은 차원의 데이터였으면 한다면, $ x_{\rm PCA_{white}}$의 컴포넌트 중 상위 $k$개의 것만 취하면 됩니다. PCA whintening과 regularization을 서로 통합할 때를 살펴보면 $ x_{\rm PCA_{white}}$의 마지막 몇 컴포넌트는 0에 가깝게 되기 때문에, 이 때에도 그 컴포넌트들을 안전하게 제거해버릴 수 있습니다.
ZCA Whitening
마지막입니다. 사실 데이터가 covariance를 identity $I$로 가지게 하는 방법은 하나가 아닙니다. $R$이 어떤 orthogonal matrix라고 한다면, 그러니까 $RR^T = R^T R = I$라고 한다면, $\textstyle R \,x_{\rm PCAwhite}$을 계산하면 이는 idenity covariance를 갖습니다.
ZCA whitening에서는, 다음과 같은 $R=U$로 사용합니다.
$$ x_{\rm ZCAwhite} = U x_{\rm PCAwhite} $$
$ \textstyle x_{\rm ZCAwhite}$을 그래프로 출력해보면 다음과 같습니다.
가능한 모든 $R$ 중에서 이렇게 선택된 것을 사용한 $\textstyle x_{\rm ZCAwhite}$가 원래의 입력 데이터 $x$와 가장 가까운 것을 볼 수 있습니다.
ZCA whitening을 할 때에는, PCA whintening과는 달리 데이터의 $n$ 차원을 모두 유지합니다. 따라서 차원 축호는 하지 않습니다.
Regularization
실제로 PCA whintening이나 ZCA whintening을 구현할 때에는, 때로 고유값 $\lambda_i$가 0에 가깝게 될 때가 있습니다. 따라서 $\sqrt{\lambda_i}$로 나눠주는 스케일링 단계에서 0에 가까운 값으로 나눠지게 될 것입니다. 이는 데이터를 매우 큰 값으로 커지게 만들거나 불안정한 값으로 만들어버림을 의미합니다. 따라서 이런 경우, 약간의 regularization을 이용한 스케일링을 수행합니다. 제곱근을 구해 나누기를 하기 전에 고유값에 작은 상수 $\textstyle \epsilon$를 추가합니다.
$$ x_{\rm PCAwhite,i} = \frac{x_{\rm rot,i} }{\sqrt{\lambda_i + \epsilon}} $$
$x$가 $[-1, 1]$사이의 값을 가질 때 $\textstyle \epsilon \approx 10^{-5}$정도의 값을 사용하는 것이 일반적입니다.
이미지의 경우, $\epsilon$을 추가하는 것은 입력 이미지에서 약간의 스무딩 혹은 저주파 필터링의 효과를 갖습니다. 또한 이미지 픽셀에서의 계단 현상 아티팩트를 제거하는 효과도 있으며 특징 학습을 향상시키기도 합니다.
ZCA whitening은 데이터 $x$를 $x_{\textstyle ZCA_{\textstyle whitening}}$으로 매핑하는 전처리 단계의 형태를 띕니다. 이는 생물의 눈, 망막이 이미지를 어떻게 처리하는지에 대한 거친 (rough) 모델이기도 합니다. 자세히 말하면, 눈이 이미지를 받아들일 때, 눈에서 가장 가까운 픽셀들은 비슷한 값들로 인지될 것인데, 이는 이미지에서 인접한 부분들은 그 밝기가 서로 높은 상관성이 있기 때문입니다. 따라서 각 픽셀 값을 모두 신경을 통해 뇌로 전달하는 것은 시간을 낭비하는 꼴입니다. 따라서 그 대신, 망막은 상관성 제거(decorrelation) 연산을 수행합니다. 이는 시신경이 "on center, off surround/off center, on surround" 함수를 불러 계산하게 되는데, 이는 ZCA에서 행해지는 것과 매우 비슷합니다. 이러한 적은 redundant를 갖는 이미지 표현이 뇌로 전달됩니다.
Implementing PCA Whintening
여기서는 PCA, PCA whitnening, ZCA whinteing 알고리즘을 정리하고 선행대수 라이브러리를 이용하여 어떻게 구현할지를 알아보겠습니다.
먼저 데이터가 평균 0을 갖는지 확인해야 합니다. Natural image는 이를 각 이미지 패치의 평균 값으로 빼주는 것으로 할 수 있습니다.
각 패치의 평균을 구하고 이를 패치에서 빼주려면 MATLAB에서는 다음과 같이 합니다.
1 2 3 4 5 |
avg = mean(x, 1); % Compute the mean pixel intensity value separately for each patch. x = x - repmat(avg, size(x, 1), 1); |
다음으로 $\textstyle \Sigma = \frac{1}{m} \sum_{i=1}^m (x^{(i)})(x^{(i)})^T$를 계산하여야 합니다. MATLAB을 사용하고 있거나, C++, Java 등에서 선형대수 라이브러리를 사용할 수 있다면, 비효율적으로 덧셈을 일일이 계산하는 대신 한번에 이를 계산하고 있습니다.
1 2 3 |
sigma = x * x' / size(x, 2) |
여기서 $x$는 데이터 구조체로 하나의 샘플을 하나의 컬럼으로 가집니다. 따라서 $x$는 $n$행 $m$열의 행렬입니다.
다음 $\Sigma$의 고유벡터를 계산하여 PCA를 계산합니다. 어떤 사람은 MATLAB의 eig
함수를 사용하고자 할 것입니다. 하지만 $\Sigma$는 symmetric positive semi-difinite 행렬입니다. 따라서 svd
함수를 사용하는 것이 더 믿을 만 합니다.
1 2 3 |
[U, S, V] = svd(sigma) |
이는 $\Sigma$의 고유벡터를 포함하는 행렬 $U$과 그에 대한 고유값을 대각 성분으로 가지는 $S$, 그리고 $V$는 $U$와 같은 값으로 무시하여도 상관없습니다. 여기서 $S$는 큰 순서대로 정렬되어있습니다.
svd
함수는 행렬의 sigular vector와 singular value를 계산하는 것으로, symmetric positive semi-difinite 행렬의 특수한 예입니다. 이것이 고유벡터와 고유값를 구하는 것과 같은 이유는 깊이 이야기하지 않겠습니다.
마지막으로 $x_\text{rot}$와 $\tilde{x}$를 계산합니다.
1 2 3 4 5 |
xRot = U' * x; % rotated version of the data. xTilde = U(:,1:k)' * x; % reduced dimension representation of the data, % where k is the number of eigenvectors to keep |
이것은 데이터의 $\tilde{x} \in \Re^k$인 PCA 표현을 계산해줍니다. 그런데 $x$가 트레이닝 데이터를 담고 있는 $n$행 $m$열 행렬일경우, 이것은 vetorized된 구현입니다. 따라서 위에 써진 코드는 $x_{\textstyle{rot}}$와 $\tilde{x}$를 전체 트레이닝 셋에 대해서 한번에 계산할 것입니다. 결 $x_{\textstyle{rot}}$와 $\tilde{x}$는 각 트레이닝 샘플에 대해 한 열이 대응되게 됩니다.
PCA whitened 데이터인 $x_{\textstyle PCA_{\text{white}}}$는 다음과 같이 계산합니다.
1 2 3 |
xPCAwhite = diag(1./sqrt(diag(S) + epsilon)) * U' * x; |
$S$의 대각 성분들은 고유값 $\lambda_i$를 포함하고 이는 모든 $i$에 대해서 $\textstyle x_{\rm PCAwhite,i} = \frac{x_{\rm rot,i} }{\sqrt{\lambda_i}}$을 동시에 계산할 수 있는 방법입니다.
마지막으로 ZCA whintened 데이터 $\textstyle x_{\rm ZCAwhite}$는 다음과 같이 계산합니다.
$$