for textmining

주성분분석(Principal Component Analysis)

|

이번 글에서는 차원축소(dimensionality reduction)변수추출(feature extraction) 기법으로 널리 쓰이고 있는 주성분분석(Principal Component Analysis)에 대해 살펴보도록 하겠습니다. 이번 글은 고려대 강필성 교수님과 역시 같은 대학의 김성범 교수님 강의를 정리했음을 먼저 밝힙니다. 그럼 시작하겠습니다.

기법 개요

PCA는 데이터의 분산(variance)을 최대한 보존하면서 서로 직교하는 새 기저(축)를 찾아, 고차원 공간의 표본들을 선형 연관성이 없는 저차원 공간으로 변환하는 기법입니다. 이를 그림(출처)으로 나타내면 아래와 같습니다. 2차원 공간에 있는 데이터들이 하나의 주성분(PC1)을 새로운 기저로 선형변환된 걸 확인할 수 있습니다. 여기에서 핑크색 표시가 돼 있는 사선축이 원 데이터의 분산을 최대한 보존하는(=데이터가 가장 많이 흩뿌려져 있는) 새 기저입니다. PCA의 목적은 바로 이런 축을 찾는 데 있습니다.

Feature Extraction

변수추출(Feature Extraction)은 기존 변수를 조합해 새로운 변수를 만드는 기법으로, 단순히 일부 중요 변수만을 빼내는 변수선택(Feature Selection)과는 대비됩니다. 변수추출에는 기존 변수 가운데 일부만 활용하는 방식이 있고, 모두 쓰는 방식이 있는데 PCA는 후자에 해당합니다. 아울러 PCA는 기존 변수를 선형결합(linear combination)해 새로운 변수를 만들어 냅니다.

예컨대 PCA는 변수가 $p$개, 관측치가 $n$개 있는 데이터 $X$(p x n)로 새로운 변수 $z$를 아래와 같이 만드는 과정으로 이해하면 좋을 것 같습니다. 여기에서 벡터 $x_i$는 데이터 행렬 $X$의 $i$번째 변수에 해당하는 행벡터(1 x n)인데요, 이들을 적절히 조합해 새로운 벡터 $z_i$ (1 x n)들을 만들어내는 것입니다.

\[\begin{align*} \overrightarrow { { z }_{ 1 } } &={ \alpha }_{ 11 }\overrightarrow { { x }_{ 1 } } +{ \alpha }_{ 12 }\overrightarrow { { x }_{ 2 } } +...+{ \alpha }_{ 1p }\overrightarrow { { x }_{ p } } ={ \overrightarrow { { \alpha }_{ 1 } } }^{ T }X\\ \overrightarrow { { z }_{ 2 } } &={ \alpha }_{ 21 }\overrightarrow { { x }_{ 1 } } +{ \alpha }_{ 22 }\overrightarrow { { x }_{ 2 } } +...+{ \alpha }_{ 2p }\overrightarrow { { x }_{ p } } ={ \overrightarrow { { \alpha }_{ 2 } } }^{ T }X\\ &...\\ \overrightarrow { { z }_{ p } } &={ \alpha }_{ p1 }\overrightarrow { { x }_{ 1 } } +{ \alpha }_{ p2 }\overrightarrow { { x }_{ 2 } } +...+{ \alpha }_{ pp }\overrightarrow { { x }_{ p } } ={ \overrightarrow { { \alpha }_{ p } } }^{ T }X \end{align*}\]

사실 위와 같은 식의 선형결합은 선형변환으로도 이해할 수 있습니다. 바꿔 말하면 벡터 $z_i$는 $X$를 $α_i$( p x 1)라는 새로운 축에 사영(projection)시킨 결과물이라는 것이죠. 선형변환에 대해 살펴보시려면 이곳을, 사영에 대해 보시려면 이곳 방문을 권해 드립니다. 어쨌든 변수추출로 새롭게 만들어진 $z_i$로 구성된 행렬 $Z$는 아래와 같이 적을 수 있습니다.

\[Z=\begin{bmatrix} \overrightarrow { { z }_{ 1 } } \\ \overrightarrow { { z }_{ 2 } } \\ ... \\ \overrightarrow { { z }_{ p } } \end{bmatrix}=\begin{bmatrix} { \overrightarrow { { \alpha }_{ 1 } } }^{ T }X \\ { \overrightarrow { { \alpha }_{ 2 } } }^{ T }X \\ ... \\ { \overrightarrow { { \alpha }_{ p } } }^{ T }X \end{bmatrix}=\begin{bmatrix} { \overrightarrow { { \alpha }_{ 1 } } }^{ T } \\ { \overrightarrow { { \alpha }_{ 2 } } }^{ T } \\ ... \\ { \overrightarrow { { \alpha }_{ p } } }^{ T } \end{bmatrix}X={ A }^{ T }X\]

PCA의 목적과 solution

위 식에서 각 변수와 결합하는 계수들만 알면 PCA를 수행할 수 있게 됩니다. 앞서 설명드렸듯이 PCA의 목적은 원데이터 행렬 $X$의 분산을 최대한 보존하는 데 있기 때문에 $Z$의 분산 또한 최대화되어야 합니다. 그럼 우리가 알고 싶은 미지수인 $p$차원 계수벡터를 $α$, $X$의 공분산행렬(covariance matrix)을 $Σ$로 둡시다. 그럼 아래와 같이 식을 쓸 수 있습니다.

\[\begin{align*} \max _{ \alpha }{ \{ Var(Z)\} } &=\max _{ \alpha }{ \{ Var({ \overrightarrow { \alpha } }^{ T }X)\} } \\ &=\max _{ \alpha }{ \{ { \overrightarrow { \alpha } }^{ T }Var(X)\overrightarrow { \alpha } \} } \\ &=\max _{ \alpha }{ \{ { \overrightarrow { \alpha } }^{ T }\Sigma \overrightarrow { \alpha } \} } \end{align*}\]

위 식을 만족하는 $α$는 무수히 많을 수 있습니다. 사실 $α$의 크기를 무작정 키우기만 해도 $Z$의 분산을 높일 수가 있게 되거든요. 이 때문에 아래와 같은 제약식을 둡니다.

\[\left\| \alpha \right\| ={ \overrightarrow { \alpha } }^{ T }\overrightarrow { \alpha } =1\]

이를 종합해 라그랑지안 문제로 변형하겠습니다.

\[L={ \overrightarrow { \alpha } }^{ T }\Sigma \overrightarrow { \alpha } -\lambda ({ \overrightarrow { \alpha } }^{ T }\overrightarrow { \alpha } -1)\]

최대값을 구하기 위해 $L$을 미지수 $α$로 미분한 식을 0으로 두어 정리하면 아래와 같습니다.

\[\begin{align*} \frac { \partial L }{ \partial \overrightarrow { \alpha } } =\Sigma \overrightarrow { \alpha } -\lambda \overrightarrow { \alpha } &=0\\ (\Sigma -\lambda )\overrightarrow { \alpha } &=0 \end{align*}\]

고유벡터(eigenvector)의 정의에 의해 $α$는 데이터의 공분산행렬 $Σ$의 고유벡터, $λ$는 $Σ$의 고유값이 됩니다. 따라서 원데이터 $X$의 분산을 최대화하는 $α$는 $Σ$의 고유벡터라는 사실을 알 수 있습니다. $Σ$의 고유벡터를 주성분(Principal Component)이라고 합니다.

한편 공분산행렬은 비특이행렬(non-singular matrix)로 고유값과 고유벡터의 개수가 차원수($p$)만큼 존재한다고 합니다.

공분산행렬 고유벡터의 성질

데이터가 각 변수별로 평균이 0으로 맞춰져 있을 때(centering 작업 이미 수행되어 있다고 가정) 데이터 $X$의 공분산 행렬 $Σ$는 아래와 같이 구합니다.

\[\Sigma=cov(X)=\frac { 1 }{ n-1 } X{ X }^{ T }\propto X{ X }^{ T }\]

$X​$의 차원수가 p x n이라면, 공분산행렬 $Σ​$은 p x p 크기의 정방행렬(square matrix)이 됩니다. 또한 $Σ^T=Σ​$인 대칭행렬(symetric matrix)입니다.

열벡터가 공분산행렬 $Σ$의 고유벡터인 행렬을 $A$, 대각성분이 $Σ$의 고유값이고 대각성분을 제외한 요소값이 0인 행렬을 $Λ$라고 할 때 다음과 같이 식을 쓸 수 있습니다.

\[\Sigma A=\Lambda A\\ \Sigma =A\Lambda { A }^{ -1 }\]

$Σ$는 대칭행렬이므로 식을 다음과 같이 정리할 수 있습니다.

\[\begin{align*} { \Sigma }^{ T }=&{ \left( { A }^{ -1 } \right) }^{ T }\Lambda { A }^{ T }\\ =&A\Lambda { A }^{ -1 }=\Sigma \\ \\ \therefore &{ A }^{ -1 }={ A }^{ T } \\ &{ A }^{ T }A=I \end{align*}\]

따라서 공분산행렬 $Σ$의 서로 다른 고유벡터끼리는 서로 직교(orthogonal)함을 확인할 수 있습니다. 원데이터를 공분산 행렬의 고유벡터로 사영하기 전에는 변수 간 연관성이 있었더라도 PCA 변환에 의하여 좌표축이 바뀐 데이터들은 서로 무상관(uncorrelated)이게 됩니다.

고유값과 새 변수의 분산

$Σ$는 원데이터 $X$의 공분산행렬이고, $Σ$의 가장 큰 고유값과 고유벡터를 각각 $λ_1$, $α_1$이라고 두겠습니다. 이 둘로 만든 새로운 변수 $z_1$와 그 분산은 아래와 같이 쓸 수 있습니다.

\[\begin{align*} \overrightarrow { { z }_{ 1 } } &={ \overrightarrow { { \alpha }_{ 1 } } }^{ T }X\\ Var(\overrightarrow { { z }_{ 1 } } )&={ \overrightarrow { { \alpha }_{ 1 } } }^{ T }\Sigma \overrightarrow { { \alpha }_{ 1 } } \end{align*}\]

고유벡터의 정의에 의해 아래와 같은 식이 성립합니다.

\[\Sigma \overrightarrow { { \alpha }_{ 1 } } ={ \lambda }_{ 1 }\overrightarrow { { \alpha }_{ 1 } }\]

이를 원식에 대입하고, $α$를 단위벡터로 정한 제약식을 원용해 정리하면 다음과 같습니다.

\[\begin{align*} Var({ z }_{ 1 })&={ \overrightarrow { { \alpha }_{ 1 } } }^{ T }\Sigma \overrightarrow { { \alpha }_{ 1 } } \\ &={ { \overrightarrow { { \alpha }_{ 1 } } }^{ T }\lambda }_{ 1 }\overrightarrow { { \alpha }_{ 1 } } \\ &={ \lambda }_{ 1 }{ \overrightarrow { { \alpha }_{ 1 } } }^{ T }\overrightarrow { { \alpha }_{ 1 } } \\ &={ \lambda }_{ 1 } \end{align*}\]

요컨대 $Σ$의 제1 고유벡터로 만든 새로운 변수 $z_1$의 분산은 그에 해당하는 고유값 $λ_1$이라는 뜻입니다.

이를 확장하여 $Σ$의 $i$번째로 큰 고유값과 고유벡터를 각각 $λ_i$, $α_i$이라고 둡시다. 이들로 만든 새로운 변수 $z_i$의 분산은 그에 해당하는 고유값 $λ_i$가 됩니다. 따라서 $Σ$의 고유값 전체 합과 원데이터 $X$의 분산은 서로 같습니다.

PCA 예제 1

다음과 같은 데이터 $X​$가 주어졌다고 합시다. 변수는 3개, 관측치는 5개로 구성된 데이터입니다.

구분 $n_1$ $n_2$ $n_3$ $n_4$ $n_5$
$p_1$ 0.2 0.45 0.33 0.54 0.77
$p_2$ 5.6 5.89 6.37 7.9 7.87
$p_3$ 3.56 2.4 1.95 1.32 0.98

우선 변수(행)별로 평균을 0으로 centering한 행렬 $X’​$를 만듭니다.

구분 $n_1$ $n_2$ $n_3$ $n_4$ $n_5$
$p_1$ -1.1930 -0.0370 -0.5919 0.3792 1.4427
$p_2$ -1.0300 -0.7647 -0.3257 1.0739 1.0464
$p_3$ 1.5012 0.3540 -0.0910 -0.7140 -1.0502

$X$의 공분산행렬은 다음과 같이 구할 수 있습니다.

\[\begin{align*} \Sigma =cov(X)&=\frac { 1 }{ 5-1 } X'{ X' }^{ T }\\\\ &=\begin{bmatrix} 0.0468 & 0.1990 & -0.1993 \\ 0.1990 & 1.1951 & -1.0096 \\ -0.1993 & -1.0096 & 1.0225 \end{bmatrix} \end{align*}\]

$Σ$를 고유분해한 결과는 아래와 같습니다. 행렬 $A$는 각각의 열벡터가 $Σ$의 고유벡터로 구성돼 있습니다. 대각행렬 $Λ$는 각각의 대각원소가 $Σ$의 고유값입니다. $λ_1(2.7596)$에 대응하는 고유벡터는 $α_1$($[0.5699,0.5765,-0.5855]^T$)입니다.

\[\begin{align*} \Sigma A&=A\Lambda \\\\ A&=\begin{bmatrix} \overrightarrow { { \alpha }_{ 1 } } & \overrightarrow { { \alpha }_{ 2 } } & \overrightarrow { { \alpha }_{ 3 } } \end{bmatrix}\\ &=\begin{bmatrix} 0.5699 & 0.7798 & 0.2590 \\ 0.5765 & -0.6041 & 0.5502 \\ -0.5855 & 0.1643 & 0.7938 \end{bmatrix}\\\\ \Lambda &=\begin{bmatrix} { \lambda }_{ 1 } & 0 & 0 \\ 0 & { \lambda }_{ 2 } & 0 \\ 0 & 0 & { \lambda }_{ 3 } \end{bmatrix}\\ &=\begin{bmatrix} 2.7596 & 0 & 0 \\ 0 & 0.1618 & 0 \\ 0 & 0 & 0.0786 \end{bmatrix} \end{align*}\]

그렇다면 우리는 여기에서 가장 큰 고유값에 해당하는 고유벡터로 새로운 변수 $z_1$을 만들 수 있습니다. 아래 식에서 $x_1, x_2, x_3$은 각각 $X’$의 행벡터이고, 이 벡터들 앞에 붙는 계수는 해당하는 고유벡터의 요소값입니다.

\[\begin{align*} \overrightarrow { { z }_{ 1 } } &={ \overrightarrow { { \alpha }_{ 1 } } }^{ T }X\\ \\ &=\begin{bmatrix} 0.5699 & 0.5765 & -0.5855 \end{bmatrix}\begin{bmatrix} \overrightarrow { { x }_{ 1 } } \\ \overrightarrow { { x }_{ 2 } } \\ \overrightarrow { { x }_{ 3 } } \end{bmatrix}\\ \\ &=0.5699\overrightarrow { { x }_{ 1 } } +0.5765\overrightarrow { { x }_{ 2 } } -0.5855\overrightarrow { { x }_{ 3 } } \\ &=0.5699\begin{bmatrix} -1.1930 & -0.0370 & -0.5919 & 0.3792 & 1.4427 \end{bmatrix}\\ &\quad+0.5765\begin{bmatrix} -1.0300 & -0.7647 & -0.3257 & 1.0739 & 1.0464 \end{bmatrix}\\ &\quad-0.5855\begin{bmatrix} 1.5012 & 0.3540 & -0.0910 & -0.7140 & -1.0502 \end{bmatrix}\\ &=\begin{bmatrix} -2.1527 & -0.6692 & -0.4718 & 1.2533 & 2.0404 \end{bmatrix} \end{align*}\]

여기에서 $z_1$의 첫번째 요소(스칼라) -2.1527의 의미를 곱씹어봅시다. 원데이터의 첫번째 데이터($n_1$)는 [-1.930, -1.0300, 1.5012]였습니다. 이 $n_1$이 첫번째 고유벡터 $α_1$과 내적된 결과가 바로 -2.1527입니다. 축에 해당하는 벡터가 유닛벡터일 때 벡터의 내적과 사영은 동일한 의미를 지닙니다. 따라서 -2.1527은 $n_1$을 $α_1$라는 축에 사영해 $α_1$에서 어디쯤 위치하는지 나타내주는 스칼라값이라고 보면 좋을 것 같습니다. 이를 그림으로 나타내면 다음과 같습니다.

$z_1$의 두번째 요소 -0.6692는 원데이터의 두번째 데이터 $n_2$를 $α_1$라는 축에 사영한 결과로 볼 수 있습니다. 마찬가지 방식으로 $z_2, z_3$을 만들어 $Z$를 계산할 수 있습니다.

\[Z={ A }^{ T }X\\\\ \begin{bmatrix} \overrightarrow { z_{ 1 } } \\ \overrightarrow { z_{ 2 } } \\ \overrightarrow { z_{ 3 } } \end{bmatrix}=\begin{bmatrix} { \overrightarrow { \alpha _{ 1 } } }^{ T } \\ { \overrightarrow { \alpha _{ 2 } } }^{ T } \\ { \overrightarrow { \alpha _{ 3 } } }^{ T } \end{bmatrix}X=\begin{bmatrix} -2.1527 & -0.6692 & -0.4718 & 1.2533 & 2.0404 \\ -0.0615 & 0.4912 & -0.2798 & -0.4703 & 0.3204 \\ 0.3160 & -0.1493 & -0.4047 & 0.1223 & 0.1157 \end{bmatrix}\]

그러면 $Z$의 공분산행렬을 구해보겠습니다. 아래와 같습니다.

\[cov(Z)=\begin{bmatrix} 2.7596 & 0 & 0 \\ 0 & 0.1618 & 0 \\ 0 & 0 & 0.0786 \end{bmatrix}\]

보시다시피 새 변수 $z_1, z_2, z_3$ 사이에 공분산이 0이어서 무상관(uncorrelated) 관계가 된 것을 확인할 수 있습니다. 이는 $Σ$의 고유벡터는 서로 직교하는데, $X$가 이 고유벡터를 새로운 축, 즉 주성분으로 하여 선형변환되었기 때문입니다.

아울러 앞선 증명에서 살펴보았든 $z_1$의 분산은 $λ_1$이라는 사실 또한 확인할 수 있습니다. 만약 새 변수로 $z_1$만 남기고 나머지를 생략하게 된다면 아래 식과 같이 원데이터 $X$ 분산의 92%를 보존하면서도 원데이터를 3차원에서 1차원으로 줄일 수 있게 됩니다. 다시 말해 3개 주성분 가운데 첫번째 주성분(PC1)을 선택해도 원데이터의 설명력을 어느 정도 보존할 수 있다는 이야기입니다.

\[\frac { { \lambda }_{ 1 } }{ { \lambda }_{ 1 }+{ \lambda }_{ 2 }+{ \lambda }_{ 3 } } =\frac { 2.7596 }{ 2.7596+0.1618+0.0786 } =0.920\]

loading plot

PCA는 기존 변수를 선형결합하는 과정에서 새 변수를 만들게 되는데요, 선형결합의 계수들을 가지고 시각화를 하면 각 변수별로 중요도를 어림짐작할 수 있습니다.

위 그림의 가로축은 가장 큰 고유값에 해당하는 주성분(PC1)의 계수를 뜻합니다. 세로축은 두번째 주성분(PC2)의 계수입니다. 여기에서 기존 변수 $x_2$는 PC1을 만들 때 상대적으로 중요하지만, PC2에는 그렇지 않음을 알 수 있습니다. $x_3$는 반대로 PC1에는 덜 중요하고, PC2에는 중요함을 알 수 있습니다.

PCA 예제 2

이번엔 R로 분석하는 예제를 소개합니다. 내장 데이터인 iris를 대상으로 PCA를 적용해 보기로 했습니다. PCA를 수행한 뒤 summary 함수를 쓰면 아래와 같은 표를 얻을 수 있습니다. iris의 독립변수는 네 개이므로 PCA를 수행하면 네 개의 주성분을 얻을 수 있고, 각 축이 전체 데이터의 분산에서 차지하는 비율을 의미합니다.

구분 PC1 PC2 PC3 PC4
변수 비율 0.7296245 0.2285076 0.03668922 0.005178709

2D Score Plot을 그리면 아래 그림과 같습니다. PC1, PC2 두 개만으로도 전체 데이터 분산의 95.8%를 보존하고 있기 때문에 2차원으로 시각화해도 원 데이터의 모양을 파악하는 데 문제가 없습니다.

loading plot은 아래 그림과 같습니다. PC1 기준으로는 ‘Petal.Length’, ‘Petal.Width’, ‘Sepal.Length’가 비교적 중요한 변수임을 확인할 수 있습니다. PC2 입장에서는 ‘Sepal.Width’가 중요한 변수입니다.

위 분석에 사용한 R 코드는 아래와 같습니다.

library(rgl)
library(devtools)
install_github("vqv/ggbiplot")
library(ggbiplot)

# PCA
# cor = whether the calculation should use the correlation matrix or the covariance matrix
# score = whether the score on each principal component should be calculated
pcadata < princomp(iris[,1:4], cor=T, scores=T)
# summary
plot(pcadata, type='l')
summary(pcadata)

# 2d score plot
ggbiplot(pcadata,groups = iris$Species)

# loading plot
plot(pcadata$loadings[,1:2], col=c('black','blue','red','green'), pch=16)
legend('topleft',
	 c('Sepal.Length','Sepal.Width','Petal.Length','Petal.Width'),
     text.col=c('black','blue','red','green'))

PCA의 절차

지금까지 논의한 내용을 바탕으로 PCA 수행절차를 정리하면 다음과 같습니다.

  1. 기존 데이터 $X$의 공분산행렬 계산
  2. 공분산행렬의 고유값과 고유벡터 계산
  3. 고유값의 크기 순서대로 고유벡터를 나열
  4. 정렬된 고유벡터 가운데 일부 선택
  5. 해당 고유벡터와 $X$ 내적

PCA는 서로 직교하는 새 기저로 데이터를 변환하기 때문에 변수 간 상관관계가 높은 데이터에 효과가 좋다고 합니다. 데이터 차원축소, 압축에 널리 쓰이고 있습니다.



Comments