이론

[알고리즘] 주성분 분석 PCA - 개념 정리

weweGH 2026. 7. 29. 17:00
반응형

 

PCA 주성분 분석
PCA 주성분 분석


주성분 분석 PCA - 개념 정리


들어가며


PCA(Principal Component Analysis, 주성분 분석)는 고차원 데이터를 더 낮은 차원으로 압축하는 차원 축소(Dimensionality Reduction) 기법입니다. 데이터의 핵심 정보는 최대한 보존하면서, 변수의 수를 줄이는 것이 목적입니다.

예를 들어, 학생 100명의 시험 성적 데이터가 수학, 물리, 화학, 영어, 국어 5개 과목으로 구성되어 있다고 가정하겠습니다. 그런데 수학과 물리 성적은 서로 높은 상관관계를 가집니다.PCA는 이처럼 서로 관련 있는 변수들을 묶어 더 적은 수의 새로운 변수(주성분)로 표현합니다.

결과적으로 5개의 과목 점수 대신, "이과 계열 역량"과 "문과 계열 역량" 같은 2개의 주성분으로 데이터를 요약할 수 있습니다.

이 글에서는 PCA의 개념, 동작 원리, 수식, 그리고 파이썬 구현 방법을 설명합니다.


  • PCA가 필요한 이유
  • PCA의 핵심 개념 - 분산과 주성분
  • PCA 동작 과정
  • 주요 수식
  • 파이썬을 활용한 PCA
  • PCA 적용 시 주의사항

PCA가 필요한 이유


데이터의 차원이 늘어날수록 다음과 같은 문제가 발생합니다. PCA는 이 문제들을 완화하기 위해 변수 간 상관관계를 분석하고, 정보 손실을 최소화하면서 차원을 줄입니다.

문제 설명
차원의 저주(Curse of Dimensionality) 차원이 늘어날수록 데이터 간 거리가 커져 모델 성능이 저하됨
다중공선성 (Multicollinearity) 변수 간 상관관계가 높으면 회귀 계수 추정이 불안정해짐
시각화 불가 3차원을 초과하면 데이터를 눈으로 확인하기 어려움
연산 비용 증가 변수가 많을수록 학습 시간과 메모리 사용량이 증가함

PCA의 핵심 개념 - 분산과 주성분


PCA는 "어느 방향으로 데이터를 투영(Projection)했을 때 분산이 가장 커지는가?"를 찾는 알고리즘입니다. 분산이 크다는 것은 데이터가 그 방향으로 넓게 퍼져 있다는 의미입니다. 즉, 데이터의 정보를 가장 많이 담고 있는 방향입니다.

PCA가 찾는 새로운 축을 주성분(Principal Component)이라 부릅니다. 각 주성분은 서로 직교(Orthogonal)합니다. 이는 주성분 간에 상관관계가 없다는 의미이며, 다중공선성 문제를 제거합니다.

용어 설명
제1 주성분 (PC1) 데이터의 분산이 가장 큰 방향
제2 주성분 (PC2) PC1과 직교(수직)하면서, 그 다음으로 분산이 큰 방향
제k 주성분 (PCk) 이전 모든 주성분과 직교하면서, k번째로 분산이 큰 방향

PCA 동작 과정


PCA는 다음 5단계로 수행됩니다.


1단계: 데이터 표준화

변수마다 단위와 스케일이 다르면 분산이 큰 변수가 주성분에 과도하게 영향을 미칩니다. 따라서 평균 0, 표준편차 1이 되도록 표준화합니다.

$$ z = \frac{x - \mu}{\sigma} $$

  • $\mu$: 평균
  • $\sigma$: 표준편차

2단계: 공분산 행렬 계산

표준화된 데이터에서 변수 간 상관관계를 담은 공분산 행렬(Covariance Matrix)을 계산합니다. 수식은 다음과 같습니다.

$$ \Sigma = \frac{1}{n-1} X^T X $$

  • $\Sigma$: 공분산 행렬 ($p \times p$ 크기, $p$는 변수의 수)
  • $X$: 표준화된 데이터 행렬 ($n \times p$)

3단계: 고유값 분해

공분산 행렬을 고유값 분해(Eigendecomposition)하여 고유벡터(Eigenvector)와 고유값(Eigenvalue)을 구합니다. 수식은 다음과 같습니다.

$$ \Sigma v = \lambda v $$

  • $v$: 고유벡터 (주성분의 방향)
  • $\lambda$: 고유값 (해당 주성분이 설명하는 분산의 크기)

4단계: 주성분 선택

고유값이 큰 순서대로 주성분을 정렬합니다. 상위 $k$개의 주성분을 선택하여 차원을 $p$에서 $k$로 줄입니다.


5단계: 데이터 변환

원본 데이터를 선택한 $k$개의 주성분 방향으로 투영하여 새로운 저차원 데이터를 생성합니다.


주요 수식


설명된 분산 비율 (Explained Variance Ratio)

각 주성분이 전체 분산 중 얼마나 많은 비율을 설명하는지를 나타냅니다. 수식은 다음과 같습니다.

$$ EVR_k = \frac{\lambda_k}{\sum_{i=1}^{p} \lambda_i} $$

  • $EVR_k$: $k$번째 주성분의 설명된 분산 비율
  • $\lambda_k$: $k$번째 주성분의 고유값
  • $\sum \lambda_i$: 전체 고유값의 합

예를 들어, PC1의 $EVR = 0.72$라면, 제1 주성분 하나가 원본 데이터 분산의 72%를 설명한다는 의미입니다.


누적 설명된 분산 (Cumulative Explained Variance)

몇 개의 주성분을 선택할지 결정할 때는 누적 설명된 분산을 기준으로 삼습니다. 일반적으로 누적 비율이 80~95% 가 되는 시점에서 주성분 수를 결정합니다.

$$ \text{Cumulative EVR}(k) = \sum_{i=1}^{k} EVR_i $$

반응형

파이썬을 활용한 PCA


파이썬에서는 sklearn의 PCA를 사용합니다. 붓꽃(Iris) 데이터셋을 활용한 예제는 다음과 같습니다.

from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

# 데이터 로드
iris = load_iris()
X = iris.data          # (150, 4) - 꽃받침 길이/너비, 꽃잎 길이/너비
y = iris.target
feature_names = iris.feature_names

# 1. 표준화 (PCA 전 필수)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 2. PCA 적용 (전체 주성분 수 = 원본 변수 수)
pca = PCA()
pca.fit(X_scaled)

# 3. 설명된 분산 비율 확인
evr = pca.explained_variance_ratio_
print("설명된 분산 비율:", np.round(evr, 4))
print("누적 설명된 분산 비율:", np.round(np.cumsum(evr), 4))

출력 결과는 다음과 같습니다. PC1과 PC2 두 개만으로 전체 분산의 95.8%를 설명합니다. 따라서 4차원 데이터를 2차원으로 압축해도 정보 손실이 크지 않습니다.

분산 비율 출력 결과
분산 비율 출력 결과


스크리 플롯 (Scree Plot) - 주성분 수 결정

스크리 플롯은 주성분 수에 따른 설명된 분산 비율을 시각화하여 최적의 주성분 수를 결정하는 데 사용합니다.

# 스크리 플롯 시각화
plt.figure(figsize=(8, 4))
plt.bar(range(1, len(evr) + 1), evr, alpha=0.7, label='개별 분산 비율')
plt.step(range(1, len(evr) + 1), np.cumsum(evr), where='mid', color='red', label='누적 분산 비율')
plt.axhline(y=0.95, color='gray', linestyle='--', label='95% 기준선')
plt.xlabel('주성분 번호')
plt.ylabel('설명된 분산 비율')
plt.title('Scree Plot')
plt.legend()
plt.tight_layout()
plt.show()

scree plot
scree plot


2차원으로 차원 축소 및 시각화

4개의 특성을 2개의 주성분으로 축소한 결과, 3종류의 붓꽃 품종이 2차원 평면에서 비교적 뚜렷하게 분리되는 것을 확인할 수 있습니다.

# 2개의 주성분으로 축소
pca_2d = PCA(n_components=2)
X_pca = pca_2d.fit_transform(X_scaled)

# 결과 시각화
target_names = iris.target_names
colors = ['#e74c3c', '#2ecc71', '#3498db']

plt.figure(figsize=(8, 6))
for i, (color, name) in enumerate(zip(colors, target_names)):
    plt.scatter(
        X_pca[y == i, 0], X_pca[y == i, 1],
        color=color, label=name, alpha=0.8, edgecolors='white', s=80
    )

plt.xlabel(f'PC1 ({evr[0]*100:.1f}%)')
plt.ylabel(f'PC2 ({evr[1]*100:.1f}%)')
plt.title('PCA - Iris 데이터 2차원 시각화')
plt.legend()
plt.tight_layout()
plt.show()

차원 축소 시각화 결과
차원 축소 시각화 결과


주성분 로딩(Component Loading) 확인

각 주성분이 원본 특성과 어떤 관계인지를 로딩 행렬로 확인합니다. 로딩값의 절댓값이 클수록 해당 특성이 주성분에 크게 기여합니다.

# 주성분 로딩 (각 주성분에 대한 원본 특성의 기여도)
loading_df = pd.DataFrame(
    pca_2d.components_.T,
    index=feature_names,
    columns=['PC1', 'PC2']
)
print(loading_df.round(3))

출력 결과는 다음과 같습니다.

PC1은 꽃잎 길이(petal length)와 꽃잎 너비(petal width)의 기여도가 높습니다. 이 주성분은 "꽃잎 크기"에 대한 정보를 주로 담고 있다고 해석할 수 있습니다. PC2는 꽃받침 너비(sepal width)의 기여도가 가장 높습니다.

기여도 출력 결과
기여도 출력 결과


주요 파라미터

n_components=0.95로 지정하면 누적 설명 분산이 95% 이상이 되는 최소 주성분 수를 자동으로 선택합니다.

파라미터 설명 기본값
n_components 축소할 차원 수
정수(개수) 또는 0~1 사이 실수(분산 비율) 지정 가능
None (전체 유지)
svd_solver SVD 분해 방식 (auto, full, randomized) auto
whiten 주성분의 분산을 1로 정규화할지 여부 False

PCA 적용 시 주의사항


표준화는 필수
PCA는 분산을 기반으로 주성분을 찾습니다. 변수 간 스케일이 다르면 단위가 큰 변수가 주성분에 과도하게 기여합니다. StandardScaler로 표준화한 뒤 PCA를 적용합니다.

해석의 어려움
원본 특성을 조합한 새로운 축(주성분)이므로, PC1이 "어떤 의미인지"를 직관적으로 설명하기 어렵습니다. 예측 성능은 높아질 수 있지만, 모델 해석이 필요한 경우에는 신중히 사용합니다.

선형 관계만 포착
PCA는 선형 상관관계를 기반으로 작동합니다. 변수 간 비선형 관계가 존재하는 경우에는 커널 PCA(Kernel PCA) 또는 t-SNE, UMAP 등의 비선형 차원 축소 기법을 고려합니다.

기법 특징 주요 용도
PCA 선형, 빠름, 역변환 가능 전처리, 시각화
Kernel PCA 비선형, PCA 확장 비선형 구조 데이터
t-SNE 비선형, 군집 구조 보존 고차원 데이터 시각화
UMAP 비선형, t-SNE보다 빠름 대규모 데이터 시각화

마무리하며

PCA는 데이터의 분산이 최대인 방향을 순서대로 찾아 고차원 데이터를 저차원으로 압축하는 기법입니다. 공분산 행렬의 고유벡터가 주성분의 방향, 고유값이 각 주성분이 설명하는 분산의 크기를 나타냅니다. PCA 전 반드시 표준화를 적용해야 하며, 누적 설명된 분산 비율을 기준으로 적절한 주성분 수를 결정합니다.


반응형