Programming

차원 축소(Dimension Reduction) 이해와 PCA 실습

Lucas.Kim 2026. 1. 11. 05:51
반응형

1. 개요

머신러닝에서 피처(feature)의 개수, 즉 차원이 증가할수록 모델의 성능이 반드시 좋아지는 것은 아닙니다.
오히려 차원이 커질수록 데이터 분석과 모델 학습이 어려워지는 여러 문제가 발생합니다.

이 글에서는

  • 차원 축소가 왜 필요한지
  • 차원 축소의 두 가지 방식
  • PCA(주성분 분석)의 원리
  • 붓꽃(Iris) 데이터를 이용한 PCA 실습
  • PCA 전후의 분류 성능 비교

입문자도 이해할 수 있도록 단계별로 설명합니다.

2. 차원이 커질 때 발생하는 문제

차원이 증가하면 다음과 같은 문제가 발생합니다.

(1) 차원의 저주(Curse of Dimensionality)

  • 피처 수가 많아질수록 데이터 포인트 간 거리가 급격히 멀어집니다.
  • 데이터 공간이 희소해지면서 **거리 기반 알고리즘(KNN 등)**의 성능이 급격히 저하됩니다.

(2) 다중 공선성 문제

  • 피처 수가 많을수록 피처 간 상관관계가 높아질 가능성이 커집니다.
  • 선형 회귀 모델에서는 다중 공선성으로 인해 회귀 계수가 불안정해지고 예측 성능이 저하됩니다.

3. 차원 축소를 하는 이유

수십~수백 개의 피처를 소수의 핵심 피처로 축소하면 다음과 같은 이점이 있습니다.

  • 학습 데이터 크기 감소 → 학습 시간 절약
  • 불필요한 피처 제거 → 모델 성능 개선
  • 2~3차원으로 축소하여 데이터 시각화 가능
  • 데이터의 잠재적 구조(Latent Structure) 파악 가능

4. 차원 축소의 두 가지 방식

(1) 피처 선택(Feature Selection)

  • 기존 피처 중 중요한 피처만 선택
  • 불필요하거나 중복된 피처는 제거
  • 예: Lasso 회귀, 트리 기반 피처 중요도

(2) 피처 추출(Feature Extraction)

  • 기존 피처들을 새로운 저차원의 피처로 압축
  • 원본 피처를 단순히 줄이는 것이 아니라 새로운 공간으로 매핑
  • 우리가 직접 정의하지 않은 잠재적(Latent) 특성을 추출

👉 PCA는 대표적인 피처 추출 기법입니다.

5. PCA(Principal Component Analysis) 개념 이해

PCA의 핵심 아이디어

  • 데이터의 **변동성(분산)**이 가장 큰 방향을 가장 중요한 정보로 간주
  • 변동성이 큰 방향부터 새로운 축(주성분)을 생성
  • 해당 축으로 데이터를 투영하여 차원 축소 수행

PCA 수행 절차 요약

  1. 입력 데이터의 공분산 행렬 계산
  2. 공분산 행렬을 고유값, 고유벡터로 분해
  3. 고유값이 큰 순서대로 주성분 선택
  4. 선택된 고유벡터로 원본 데이터 선형 변환

📌 고유벡터 = PCA 축,
📌 고유값 = 해당 축이 설명하는 데이터 분산의 크기

6. 붓꽃(Iris) 데이터로 PCA 실습

(1) 데이터 로딩 및 시각화

from sklearn.datasets import load_iris
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

# 사이킷런에서 제공하는 붓꽃 데이터셋 로딩
iris = load_iris()

# 피처 컬럼명 정의
columns = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width']

# NumPy 배열을 pandas DataFrame으로 변환
irisDF = pd.DataFrame(iris.data, columns=columns)

# 타깃 변수(품종) 추가
irisDF['target'] = iris.target

# 데이터 확인
irisDF.head(3)

(2) 원본 데이터 산점도 시각화

# 클래스별 마커 설정
markers = ['^', 's', 'o']

# 클래스별 산점도 시각화
for i, marker in enumerate(markers):
    x_axis_data = irisDF[irisDF['target']==i]['sepal_length']
    y_axis_data = irisDF[irisDF['target']==i]['sepal_width']
    plt.scatter(
        x_axis_data,
        y_axis_data,
        marker=marker,
        label=iris.target_names[i]
    )

plt.legend()
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.show()

📌 versicolor와 virginica 클래스가 서로 섞여 있음을 확인할 수 있습니다.

(3) PCA를 위한 데이터 표준화

from sklearn.preprocessing import StandardScaler

# PCA는 분산 기반 기법이므로 반드시 표준화 수행
iris_scaled = StandardScaler().fit_transform(
    irisDF.iloc[:, :-1]
)

iris_scaled.shape

✔ 평균 0, 분산 1인 정규 분포로 변환합니다.

(4) PCA 변환 수행

from sklearn.decomposition import PCA

# 2개의 주성분으로 차원 축소
pca = PCA(n_components=2)

# PCA 학습
pca.fit(iris_scaled)

# PCA 변환 수행
iris_pca = pca.transform(iris_scaled)
print(iris_pca.shape)

(5) PCA 변환 데이터 시각화

# PCA 변환 결과를 DataFrame으로 변환
pca_columns = ['pca_component_1', 'pca_component_2']
irisDF_pca = pd.DataFrame(iris_pca, columns=pca_columns)

# 타깃 값 추가
irisDF_pca['target'] = iris.target

# PCA 결과 산점도 시각화
markers = ['^', 's', 'o']

for i, marker in enumerate(markers):
    x_axis_data = irisDF_pca[irisDF_pca['target']==i]['pca_component_1']
    y_axis_data = irisDF_pca[irisDF_pca['target']==i]['pca_component_2']
    plt.scatter(
        x_axis_data,
        y_axis_data,
        marker=marker,
        label=iris.target_names[i]
    )

plt.legend()
plt.xlabel('pca_component_1')
plt.ylabel('pca_component_2')
plt.show()

📌 PCA 변환 후 클래스 분리가 더 명확해진 것을 확인할 수 있습니다.

(6) explained_variance_ratio_ 해석

print(pca.explained_variance_ratio_)

[0.72962445 0.22850762]

 

  • 첫 번째 주성분이 전체 데이터 분산의 약 72.9% 설명
  • 두 번째 주성분이 약 22.8% 설명
    👉 두 개의 주성분만으로 전체 정보의 약 95% 이상을 유지

7. PCA 전후 분류 성능 비교

(1) 원본 데이터 성능

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
import numpy as np

# 랜덤 포레스트 분류기 생성
rcf = RandomForestClassifier(random_state=156)

# 원본 데이터로 교차 검증 수행
scores = cross_val_score(
    rcf,
    iris.data,
    iris.target,
    scoring='accuracy',
    cv=3
)

print(f'원본 데이터 교차 검증 개별 정확도 : {scores}')
print(f'원본 데이터 평균 정확도 : {np.mean(scores)}')

 

(2) PCA 변환 데이터 성능

# PCA 변환된 데이터 사용
pca_X = irisDF_pca[['pca_component_1', 'pca_component_2']]

scores_pca = cross_val_score(
    rcf,
    pca_X,
    iris.target,
    scoring='accuracy',
    cv=3
)

print(f'PCA 변환 데이터 교차 검증 개별 정확도 : {scores_pca}')
print(f'PCA 변환 데이터 평균 정확도 : {np.mean(scores_pca)}')

✔ 결과 해석:

  • PCA 적용 후 정확도는 다소 감소
  • 하지만 차원 수를 4 → 2로 줄인 상태에서 이 정도 성능 유지
  • 고차원 데이터에서는 오히려 과적합 방지 효과 기대 가능

8. 결론

  • 차원 축소는 단순한 데이터 압축이 아닙니다.
  • 핵심 목적은 데이터를 더 잘 설명하는 잠재적 요소(Latent Feature)를 추출하는 데 있습니다.
  • PCA는 분산 기반 차원 축소 기법으로 가장 널리 사용됩니다.
  • 시각화, 학습 속도 개선, 과적합 완화에 매우 효과적입니다.
반응형