열렬히.뛰기

11. 차원축소와 패턴

수학 & 통계 > 탐색적 자료분석 > 탐색적 자료분석 : 목차 > 11. 차원축소와 패턴

의미1. observation을 줄이는 것. X_1, \cdots, X_n\overline{X}

의미2. variable을 줄이는 것.

우리가 가지고 있는 데이터 ⇒ 모두 matrix

관심 있는 데이터 = 수치형 데이터. binary면 좀 애매하긴 하다.

이때 가장 많이 쓰이는 통계적 차원축소 기법은 다음과 같다.

  • 주성분분석(PCA), 특이값분해(SVD)
  • 고차원 행렬을 근사하는 선형적인 방법.

행렬 데이터와 패턴

데이터 생성 & 패턴 추가

40개의 row와 10개의 column을 가진 데이터 생성.

데이터를 시각화하고, 히트맵을 이용해 클러스터링을 한다.

해답
r
# 데이터 생성
set.seed(12345)
dataMat = matrix(rnorm(400), nrow = 40)

# 데이터 시각화 및 히트맵 그리기
image(1:10, 1:40, t(dataMat)[, nrow(dataMat):1])
heatmap(dataMat)

특정한 패턴이 없으므로, 행렬 데이터에 임의로 패턴을 추가해보자.

  1. 시드넘버를 678910으로 고정한다.
  2. 행에 패턴을 넣는 것이므로 for()문을 쓰되, 그 길이를 40으로 한다.
  3. coinflip 변수를 만들고, 해당 변수가 T일 때 패턴을 넣는다.
  4. 패턴은 rep(c(0, 3), each=5) 로 만들고 각 열에 더한다.
해답
r
set.seed(678910)
for(i in 1:40){
    coinflip = rbinom(1, size=1, prob=0.5)
    
    ## coin이 앞면일 경우, 패턴 추가
    if (coinflip){
       dataMatrix[i, ] = dataMatrix[i, ] + rep(c(0, 3), each=5) 
    }
}

인제 패턴이 들어간 상태에서의 행렬을 시각화해보자.

히트맵을 그리고(image() 사용), 클러스터링도 해본다. (heatmap() 사용)

해답
r
# 히트맵 그리기
image(1:10, 1:40, t(dataMat)[, nrow(dataMatrix):1])

# 클러스터링 해보기
heatmap(dataMat)

⇒ 첫번째 히트맵을 볼 때, 오른쪽에 있는 몇몇 행들이 나머지 열보다 더 높은 값을 가지고 있는 것을 볼 수 있다.

⇒ 두번째 덴드로그램(히트맵)으로부터 열(column)이 정확히 둘로 나눠지는 것을 볼 수 있다.

행과 열의 패턴

행과 열의 평균을 확인해서 패턴이 잘 들어갔는지를 자세히 살펴보자.

해답
r
## 패턴 찾기
hh = hclust(dist(dataMat))
ordered = dataMat[hh$order, ]

par(mfrow=c(1, 3))
image(t(ordered)[, nrow(ordered):1])

plot(rowMeans(ordered), 40:1,
     xlab="Row Mean", ylab="Row", pch=19)

plot(colMeans(ordered), xlab="Column",
     ylab="Column Mean", pch=19)

  • 행과 열로 각각 2개씩 나눠지게 된다.
  • 행(row) 기준: 아래 vs 위. 모양 자체는 정규분포
    • 아래 : 평균 0
    • 위 : 평균 3
  • 열(column) 기준 : 아래 vs 위. 모양 자체는 이항분포
    • 처음 5개 = 평균 0
    • 나머지 다섯 개 = 평균 약 1.8

데이터를 만들 때를 생각해보자.

  • 기본적으로 정규분포를 사용: rnorm()
  • 패턴을 넣을 때(데이터의 절반) 이항분포를 사용: rbinom()
  • 저런 모양이 나온 이유라고 할 수 있다.

실제 데이터는 이것보다 더 다양한 패턴이 나타날 수 있기 때문에

패턴들을 구분짓는 방법이 필요함!

가장 좋은 방법은 패턴을 나타내는 데이터만 뽑아내는 것이라고 할 수 있다!

이는 원 데이터에서 차원을 축소해서 저차원 데이터를 얻는 것과 같다.

  • 하나의 방법은 변수들 중 어떤 것은 버리고, 다른 것은 살린다.
    • 상관관계를 분석하는 방법. 그런데 모든 변수들을 다 하긴 어렵다.
  • 다른 방법은 새로운 변수(feature)를 만드는 것이다.
    • 새 변수는 서로 uncorrelated 되어야 한다.
    • 또한 최대한 많은 분산을 표현해야 한다.
  • 이때 사용하는 것이 PCA와 FA라고 할 수 있다.

PCA: 주성분분석

PCA란? 데이터 특성을 나타내는 공분산행렬을 분해해 일부를 얻어내는 것!

사영(projection)을 통해 데이터의 위치 변환 후 변하지 않는 축만 뽑는다.

이러한 과정은 SVD (특이값 분해)를 통해 데이터를 압축하는 것과 같다.

y_i = P^TX_i

PCA의 원리

  1. 각각의 벡터를 가지고 표본 공분산행렬 S를 만든다.
\underline{X}_c = \mathbf{X} - \mathbf{1} \cdot \underline{\bar{X}} \\[10pt] S =
  1. S의 고유값을 찾는다. 이때 tr(S) = 고유값의 합 = 표본 분산들의 합
|S - \lambda I| = 0
  1. 직교인 고유벡터를 찾는다.
  2. S를 분해해보면 다음과 같다.
S = ALA^T

만약 A^T에 다변량 정규분포 X를 곱하면 그 값 Y 역시 다변량 정규분포를 따름.

\begin{align*} Y &\sim MN(A^T\mu,~A^T \textstyle\sum A) \\[5pt] Y &= A^T(X_p-\overline{X}) \sim MN(0, A^TS\cdot A) \end{align*}
  1. 여기서 차원을 줄인다.
  • A = p \times p 행렬
  • p 개 중 일부 = d개를 뽑아내기.
    • 이때의 d만 뽑았을 때의 합이 tr(S)와 비슷하면 그냥 쓰면 된다.
    • 이 행렬을 주성분이라고 한다.
\begin{align*} \hat var(Z) = \hat var(X\cdot A) &= A^T\cdot \hat var(X_c) \cdot A \\ &=A^T\cdot S\cdot A \\ &= L \end{align*}

(정리)

  1. 표본 공분산행렬 A를 만든다.

  2. A를 대각행렬 L로 만든다.

  3. A의 대각원소 중 일부를 뽑아서 A_d를 만든다.

  4. 원래 데이터인 X_cA_d를 곱해서 Z_d를 만든다.

    고유벡터를 모은 A_dX_c에 곱해서 선형 변환을 수행한다.

(특징)

  • 변수들 간의 선형관계가 강해야 PCA는 잘 작동한다.
  • X들이 correlation이 강하지 않으면 의미가 없다.
  • 설문조사처럼 모든 변수들이 같은 수준으로 점수화가 된 경우에는 공분산 행렬을 사용
  • 그러나 변수들의 scale이 서로 많이 다른 경우에는 값이 큰 특정 변수가 전체적인 경향을 좌우
    • 따라서 이때는 상관계수 행렬을 사용하여 추출해야 한다.
    • R에서는 prcomp(scale=T) 로 만들면 됨.
    • 대부분의 예시에서 상관계수 행렬과 공분산 행렬을 동시에 놓고 비교!
  • 축소한 만큼의 손실(표현하지 못하는 분산)은 당연히 발생한다.

만약 X_c = \begin{pmatrix} X_1 & X_2 & X_3 \end{pmatrix} 인 경우

A = \begin{pmatrix} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \\ a_{31} & a_{32} & a_{33} \end{pmatrix}

만약 X가 행렬일 경우, SVD는 다음으로 표현되는 행렬 분해이다.

X = UDV^T
  • UXX^T에서 고유벡터를 뽑아 모은 것
  • VX^TX에서 고유벡터를 뽑아 모은 것 = 주성분
  • D의 대각원소는 X^TXXX^T의 각 고유값의 제곱근로 이뤄진 값.
  • X의 랭크는 행의 갯수와 열의 갯수 중 최솟값.

예시 1: 패턴 1개

svd를 해 근사 데이터를 만들고, 원래 데이터와 근사 데이터를 비교해보자.

svd를 통한 근사 데이터를 만들 떄, U와 V의 1st 성분만 뽑아낸다.

해답
r
# pca 실행
svd1 = svd(scale(ordered))

# 1st 특이값벡터 => 근사행렬
approx = with(svd1, outer(u[, 1], v[, 1]))

# 기존데이터 vs 특이값분해 
par(mfrow=c(1, 2))
image(t(ordered)[, nrow(ordered):1], main="Original Matrix")
image(t(approx)[, nrow(approx):1], main = "Approximated Matrix")

완전히 같지는 않아도, 왠만한 중요한 정보를 다 가지고 있다.

X \approx U_1 V_1^\prime

주성분행렬에서 특이값(=분산)들은 오름차순으로 정렬된다.

따라서 첫 번쨰 특이값은 모든 데이터의 분산 중 가장 크다.

설명된 분산

이때, 데이터의 첫 번째 분산이 전체 분산을 얼마나 반영하는지 살펴보자.

  1. 기존 데이터를 0과 1로만 이뤄진 데이터로 바꾼다.
  2. “특이값(전체 분산)” vs “설명된 분산의 비율” 비교
  3. 시각화
해답
r
# 0, 1로만 이뤄진 데이터 만들기
const = Ordered * 0
for (i in 1:dim(ordered)[1]) {
     const[i, ] <- rep(c(0, 1), each = 5)

svd2 <- svd(const)

# 데이터 비교!
windows()
par(mfrow=c(1, 3))
image(t(const)[, nrow(const):1], 
      main="original data")
plot(svd2$d, xlab = "열", ylab = "특이값", 
     pch = 19)
plot(svd2$d^2/sum(svd2$d^2), xlab = "열", 
     ylab = "설명된 분산비율", pch = 19)

  • 생각보다 잘 나타내며, 좋은 결과가 나온다.
  • 첫 번째 그림 : 원래 데이터의 모습
  • 두 번째 그림 : 원래 분산
  • 세 번째 그림 : 설명된 분산의 비율
    • 설명된 분산의 비율이 클 수록 정보 손실이 작다고 할 수 있다.

    • 설명된 분산의 비율 = (선택된 고유값) / (전체 고유값의 합)

      따라서 그 비율이 높을수록 원래 분산과 비슷해짐!

비교: PCA vs SVD

이렇게 만들어진 SVD의 특이값 = PCA의 주성분!

plot()으로 확인해보자.

해답
r
# pca와 svd 만들기
svd1 = svd(scale(ordered))
pca1 = prcomp(ordered, scale=TRUE)

# 그래프로 비교해보기
par(mfrow=c(1,1))
plot(pca1$rotation[, 1], svd1$v[, 1], pch=19,
     xlab="Principal Component 1", ylab="Right singular vector")
abline(c(0,1))

예시 2: 패턴 2개

패턴이 2개 이상인 데이터 역시 svd를 통해 패턴을 발견할 수 있다.

먼저 패턴 2개를 넣은 새 데이터를 만들어보자.

해답
r
# 데이터 만들기
set.seed(678910)
dataMat2 = matrix(rnorm(400), nrow = 40)

# 패턴 만들기
for(i in 1:40){
    coinflip1 = rbinom(1, size=1, prob=0.5)
    coinflip2 = rbinom(1, size=1, prob=0.5)
    if(coinflip1){
        dataMat2[i, ] = dataMat2[i, ] + rep(c(0, 5), each=5)
    }
    if(coinflip2){
        dataMat2[i, ] = dataMat2[i, ] + rep(c(0, 5), 5)
    } 
}

# 순서 정렬
hh2 = hclust(dist(dataMat2))
ordered2 = dataMat2[hh2$order, ]

데이터와 각 패턴의 모습은 다음과 같다.

해답
r
# 시각화
windows()
par(mfrow=c(1,3))
image(t(ordered2)[, nrow(ordered2):1])
plot(rep(c(0, 1), each=5), pch=19, 
     xlab="column", ylab="pattern 1", 
     main="pattern 1")
plot(rep(c(0, 1), 5), pch=19, 
     xlab="column", ylab="pattern 2", 
     main="pattern 2")

새 데이터 → scale()svd() 해서 svd3를 만들고, 시각화해보자.

첫 번째 오른쪽 특이값벡터, 두 번째 특이값벡터의 plot을 그리면 된다.

해답
r
svd3 = svd(scale(ordered2))
windows()
par(mfrow=c(1, 2))
plot(svd3$v[, 1], pch=19, xlab="column",
     ylab="1st right singular vector")
plot(svd3$v[, 2], pch=19, xlab="column",
     ylab="2nd right singular vector")

첫번째 오른쪽 특이값벡터가 좀 더 상단의 두 패턴을 많이 반영했다고 할 수 있다.

설명된 분산

여기서도 설명된 분산의 비율을 확인해보자.

해답
r
par(mfrow=c(1, 2))
plot(svd3$d, pch=19,
     xlab="column", ylab="Singular value")
plot(svd3$d^2/sum(svd3$d^2), pch=19,
     xlab="column", ylab="percent of var. explained")

예시 3: 얼굴 데이터

얼굴 데이터를 SVD해서 원래 결과와 비슷한지 확인해보자.

이는 통계 데이터를 PCA하는 것 같은 과정이다.

  • 얼굴데이터 : 일부만 시각화 → 전체 데이터와 비슷
  • 통계데이터 : 일부만 뽑아내기 → 전체 데이터와 비슷.

얼굴 데이터를 살펴보고, scree plot을 그려보자.

해답
r
load("face.rda")
par(mfrow=c(1,1))

# 얼굴 보기
image(t(faceData)[, nrow(faceData):1])

# 설명된 분산의 비율
svd_face = svd(scale(faceData))
u = svd_face$u
d = svd_face$d
v = svd_face$v

svd_faceplot(d^2/sum(d^2), pch=19, 
     xlab="Singular Vector", 
     ylab="Var. explained")

특이값의 갯수를 다르게 해보며 얼굴이 원래와 비슷해지는지 보자.

해답
r
# 다양한 근사행렬
approx1 = u[, 1] %*% t(v[, 1]) * d[1]
approx5 = u[, 1:5] %*% diag(d[1:5]) %*% t(v[, 1:5])
approx10 = u[, 1:10] %*% diag(d[1:10]) %*% t(v[, 1:10])

# 얼굴 시각화
windows()
par(mfrow=c(1, 4))
image(t(approx1)[, nrow(approx1):1], main="1 vector")
image(t(approx5)[, nrow(approx5):1], main="5 vector")
image(t(approx10)[, nrow(approx10):1], main="10 vector")
image(t(faceData)[, nrow(faceData):1], main="origin")

FA: 요인분석

  • 목적은 차원축소이고, outcome이 여러개.
  • 기존 변수 m개의 정보를 담을 수 있는 새 변수 n개를 만든다.
    • 기존 변수에 무언가를 더하고 곱해서 새 변수를 만든다.
    • ex. 국, 수, 사, 과, 영 ⇒ 암기력, 학습능력 측정.

FA의 원리

X_{i1} - \mu_{i1} = \lambda_{11}f_{i1} + \cdots + \lambda_{11}f_{id} + \epsilon_{i1} \\ \vdots \\ X_{ip} - \mu_{ip} = \lambda_{p1}f_{i1} + \cdots + \lambda_{p1}f_{id} + \epsilon_{ip}
\mathbf{X - \mu = \Lambda f + e}

요인분석 식을 만들어보면, 다음과 같은 변수 4개가 존재한다.

  • X_{ij} : 관찰변수 = 줄여야 하는 기존 변수.
  • f_{in} : 잠재변수 (common factors), 요인, 인자 = 만들어야 하는 새 변수
    • 아직 무슨 값을 가졌는지 모르니까 분포를 가진다.
  • \lambda_{ij} : 요인적재량 (factor loadings) = 잠재변수가 관찰변수에 미치는 가중치.
    • 보통 0 아니면 1 이라고 가정한다.
  • \epsilon_{ij} : 특정변수 (specific factors)
    • 서로 상관관계가 없고, 잠재변수하고도 상관관계가 없다.

이때, 새 변수(관찰변수)의 분산 Var(X_{i})은 얼마일까?

\begin{align*} Var(X_{i}) &= {\lambda_1}^2~var(f_1) + \cdots {\lambda_n}^2~var(f_n) + {\sigma_j}^2 \\[10pt] &= {\lambda_1}^2 + \cdots {\lambda_n}^2 + {\sigma_j}^2 \end{align*}

모든 변수를 다 담는 행렬 형태로 다시 써보면 다음과 같다.

\begin{align*} E(\mathbf{x}) &= \mathbf{\mu + \Lambda}E(\mathbf{f}) + E(\mathbf{\epsilon}) \\ &= \mathbf{\mu} \\[10pt] Var(\mathbf{x}) &= \mathbf{\Lambda \cdot v(f_i) \cdot \Lambda^t} + var(\mathbf{\epsilon_i}) \\ &= \mathbf{\Lambda \cdot \Lambda^t + \psi} \\[10pt] S &= \mathbf{\hat\Lambda \cdot \hat\Lambda^t + \hat\psi} \end{align*}

공분산행렬 S에서 우리가 모르는 변수 2개를 보자.

  1. 오차변수의 공분산행렬 \hat \psi
    • \hat \psi을 대각행렬(diagonal matrix)라고 가정.
    • 왜? 그래야 \mathbf{x}들끼리의 분산을 \mathbf{\Lambda}로 설명 가능.
  2. 요인행렬 \mathbf{\hat\Lambda}
    • 요인적재량을 모은 것으로, 변수 간의 상관관계를 설명한다.
    • 문제는 \mathbf{f_i}도 일종의 확률변수. 만약 \lambda \cdot R \cdot R^{-1} \cdot \mathbf{f_i}를 하면, 값이 달라짐. 따라서 값이 한개가 아님. 이 상태에서는 관찰변수들과 잠재변수들 사이의 관계가 명확하지 않음.
    • 따라서 이를 회전시켜야 함. (= 분산 재분배)

요인행렬의 회전

  1. Varimax (직교회전)
    • 요인 간 상관성이 없다고 가정
    • 좌표축의 각도를 정확히 90도로 유지하여 회전
    • 요인행렬 각 열의 분산을 최대화하는 기법
    • 큰 값은 더 크게, 작은 값은 더 작게
  2. Promax (사각회전)
    • 요인 간 상관성이 있다고 가정
    • 좌표축의 각도가 90도가 되지 않도록 회전
    • 추출한 요인들 간 상관관계를 다시 설명해야 함.
    • 요인 간 군집관계를 잘 설명.

예제 4: 주식 데이터

데이터 불러오기 & 편집

  1. 데이터를 불러온다.

  2. 상관계수 행렬을 만들어준다. prcomp(~~, scale = T) 로 해줘도 된다.

    \text{matrix} - \text{avg. mat} \over \text{sigma. mat}
해답
r
# 데이터 불러오기
load("stockreturns.RData")

# 표준화된 행렬 만들기
mu = matrix(apply(stocks, 2, mean), dim(stocks)[1], dim(stocks)[2], byrow=T)
sig = matrix(apply(stocks, 2,sd), dim(stocks)[1], dim(stocks)[2], byrow=T)

stocks_new = (stocks - mu) / sig

PCA로 분석하기

PCA 작업을 해주고, 시각화를 시켜보자.

screeplot()biplot() 을 이용한다.

Scree Plot 이란?

  • PCA 분석 후 주성분 수를 선정하기 위해 쓰는 차트
  • 고유값-주성분의 분산 변화를 보여준다.
  • 고유값 변화율이 완만해지는 부분이 필요한 주성분의 수이다.
해답
r
# pca 작업 실행
stock_pca1 = prcomp(stocks)
stock_pca2 = prcomp(stocks_new)

# screeplot
windows()
par(mfrow=c(1, 2))
screeplot(stock_pca1)
screeplot(stock_pca2)

# biplot()
windows()
par(mfrow=c(1, 2))
biplot(stock_pca1, 1:2)
abline(h=0, lty=3, col='red')
abline(v=0, lty=3, col='red')

biplot(stock_pca2, 1:2)
abline(h=0, lty=3, col='red')
abline(v=0, lty=3, col='red')

여기서는 필요한 주성분이 대충 5개 정도임을 알 수 있다.

각 축이 고유벡터라고 생각하면 된다.

biplot과 두 PCA

biplot이란? 각 개체들의 첫번째 주성분(=행), 두번째 주성분(=열) 값을 나타내는 행렬도를 시각화 한것

  1. 숫자는 데이터 그 자체를 의미
  2. Biplot 그림에서 화살표는 원변수와 PC의 상관계수를 뜻하며, PC와 평행할수록 해당 PC에 큰 영향.
  3. 화살표 벡터의 길이가 원변수의 분산을 표현하며, 길수록 분산이 크다.
해답
r
windows()
with(stock_pca1, plot(rotation[, 1], rotation[, 2], type='n', xlab='PC1', ylab='PC2'))
with(stock_pca1, text(rotation[, 1], rotation[, 2], 1:10))
abline(h=0, lty=3, col='red')
abline(v=0, lty=3, col='red')

결과 해석

  • PC1에 가장 많은 영향을 미치는 요인은 comp1이다.
  • PC2에 가장 많은 영향을 미치는 요인은 comp10이다.
  • 가장 분산이 큰 애는 comp4이다.

생각해봐야 할 것

  • 주성분분석의 대상인 변수의 선정
  • 제1주성분의 정의

FA로 분석하기

데이터 : 주식 주가지수

첫번째 4개 회사는 기술기업, 3개는 투자은행, 3개는 리테일.

데이터를 준비해보자.

해답
r
kval = 3
stock_fa = factanal(stocks_new, kval, rotation="none", score="reg")

str(stock_fa)
stock_fa
stock_fa$loadings

stock_fa2 = factanal(stocks_new, kval, rotation="none")

요인분석의 상관관계와 원 데이터의 상관관계를 보자.

해답
r
# 비교1 : 요인분석의 상관관계 vs 원 상관관계
all.equal(stock_fa$correlation, cor(stocks))

# 비교2
x1 = apply(stocks_new, 2, var)
x2 = apply(stock_fa$loadings^2, 1, sum)
all.equal(x1-x2, stock_fa$uniquenesses)

회전행렬을 만들어보자.

해답
r
# 회전행렬 만들기
stock_fa_R1 = factanal(stocks_new, kval, rotation="varimax")
stock_fa_R2 = factanal(stocks_new, kval, rotation="promax")

이후 시각화를 해보자.

해답
r
## 텍스트
text = "Stocks (No rotation)"
text2 = "Stocks (Varimax)"
text3 = "Stocks (Promax)"

## 새 창 만들기 
windows()
par(mfcol=c(2,3))

# 회전없이 갈 때
with(stock_fa, plot(loadings[, 1], loadings[, 2], xlim=c(-1, 1), 
ylim=c(-1, 1), main=text, xlab='Factor 1', ylab="Factor 2"))
with(stock_fa, text(loadings[, 1], loadings[, 2], labels = 1:10, pos=4))
abline(v=0)
abline(h=0)

with(stock_fa, plot(loadings[, 1], loadings[, 3], xlim=c(-1, 1), 
ylim=c(-1, 1), main=text, xlab='Factor 1', ylab="Factor 3"))
abline(v=0)
abline(h=0)

# varimax 일 때
with(stock_fa_R1, plot(loadings[, 1], loadings[, 2], xlim=c(-1, 1), 
ylim=c(-1, 1), main=text2, xlab='Factor 1', ylab="Factor 2"))
with(stock_fa_R1, text(loadings[, 1], loadings[, 2], labels = 1:10, pos=4))
abline(v=0)
abline(h=0)

with(stock_fa_R1, plot(loadings[, 1], loadings[, 3], xlim=c(-1, 1), 
ylim=c(-1, 1), main=text2, xlab='Factor 1', ylab="Factor 3"))
with(stock_fa_R1, text(loadings[, 1], loadings[, 3], labels = 1:10, pos=4))
abline(v=0)
abline(h=0)

# promax로 갈 때
with(stock_fa_R2, plot(loadings[, 1], loadings[, 2], xlim=c(-1, 1), 
ylim=c(-1, 1), main=text3, 
xlab='Factor 1', ylab="Factor 2"))
with(stock_fa_R2, text(loadings[, 1], loadings[, 2], labels = 1:10, pos=4))
abline(v=0)
abline(h=0)

with(stock_fa_R2, plot(loadings[, 1], loadings[, 3], xlim=c(-1, 1), 
ylim=c(-1, 1), main=text3, 
xlab='Factor 1', ylab="Factor 3"))
with(stock_fa_R2, text(loadings[, 1], loadings[, 3], labels = 1:10, pos=4))
abline(v=0)
abline(h=0)

결과 해석

  1. factor 2의 관점에서 보자. rotation을 해보면 리테일이 두드러져 보인다.

    factor 2가 리테일에 관련된 잠재요인임을 알 수 있다.

  2. factor 3의 관점에서 보자. rotation을 해보면, 투자은행이 두드러져 보인다.

    factor 3가 투자은행에 관련된 잠재요인임을 알 수 있다.

이러한 factor를 찾아냄으로써 연관된 (=같이 움직이는) 변수들을 찾을 수 있다.

  • 추정된 람다를 바탕으로 factor score을 찾아냄.
r
cor(stock_fa$scores)
r
> as.matrix(cor(stock_fa$scores))
              Factor1      Factor2       Factor3
Factor1  1.000000e+00 6.663222e-16 -4.337095e-16
Factor2  6.663222e-16 1.000000e+00  1.263550e-15
Factor3 -4.337095e-16 1.263550e-15  1.000000e+00
  • factor가 많으면 많을수록, 설명은 잘 되나 해석하기 힘듬
  • factor가 너무 적으면, 관계 설명이 너무 어려워짐.

정리 : PCA vs FA

  • 주성분분석 : hclustering과 비슷.

  • 요인분석 : d를 지정한다. k-means와 비슷

  • FA: 모델링 베이스. 안되는 걸 전부 error term으로

    • \mu, \Lambda를 estimation

    • 결과를 하나 잡고, 제일 좋은 것을 선택.

      차원은 2개야! ⇒ 확인!

    • 따라서 답이 달라질 수 있음.

  • PCA: 분해 베이스. 수학적 방법을 사용

    • 행렬의 trace와 eigenvalue 사용

    • 결과는 나와있고, 이중에서 고르기

      차원 중 3개를 잡자! ⇒ 확인!

    • 따라서 답이 항상 1개

  • SVD, PCA, FA 모두 변수들을 줄이는 것이 목표.

    변수를 줄인다 = 연관성이 높은 변수를 찾아서 지울 것을 지운다.

  • 따라서, 먼저 표본공분산을 보면서 상관관계가 있는지를 봐야 함!

    상관관계가 없으면 차원축소를 하는 의미가 없다.

    상관관계가 있다 = 정보가 중복되어 있다. (시험문제!!!)