본문 바로가기
머신러닝 with Python

[머신러닝 with Python] UMAP과 t-SNE 비교 (차원 축소 비교 및 구현)

by CodeCrafter 2025. 3. 11.
반응형

 

고차원 데이터를 시각화하고 이해하는 것은 머신러닝 및 데이터 분석에서 중요한 일입니다.

 

선형 차원 축소 기법인 PCA는 굉장히 유명하지만, 데이터의 복잡한 비선형을 선형으로 가정하여 축소한다는 점에서 정보의 손실이 많은데요.

[머신러닝 with 파이썬] PCA / 주성분 분석 / 차원축소 /iris 데이터 활용

 

[머신러닝 with 파이썬] PCA / 주성분 분석 / 차원축소 /iris 데이터 활용

이번에 알아볼 것은 차원축소 알고리즘의 대표적인 PCA(주성분 분석)에 대해서 알아보겠습니다.  Tabular type의 데이터에서 차원을 축소한다는 것은 곧, 변수의 개수(또는 피처의 개수)를 줄인다

jaylala.tistory.com

 

 

대표적인 비선형 차원 축소 기법으로는 UMAP(Unifor Manifold Approximation and Projection) 과 t-SNE(t-distributed Stochastic Neighbor Embedding)이 있습니다. 

 

이번 포스팅에서는 이 두 방법에 대한 핵심 원리, 차이점, 그리고 파이썬 구현을 다뤄보고자 합니다.

 

1.  t-SNE와 UMAP 비교

1.1 t-SNE

- t-SNE는 고차원 데이터의 확률 분포를 저차원에서 보존하는 비선형 차원 축소 기법입니다. 핵심 개념은 다음과 같습니다:

 

 a)확률 분포 변환: 고차원 공간에서 유사한 데이터 포인트는 낮은 Kullback-Leibler(KL) 발산을 가지도록 저차원 공간에 배치됩니다.

 b) 비슷한 데이터 유지: 지역적 구조(local structure)를 보존하는 데 중점을 둡니다.

 c) 단계적 접근: 고차원 데이터에서 유사도를 측정하고, 저차원 공간에서 새로운 확률 분포를 찾습니다.

저차원에서는 qij로 표현되며, Kullback-Leibler(KL) divergence를 최소화하는 방식으로 최적화됩니다.

 

1.2 UMAP

- UMAP은 Riemannian Geometry와 Graph Theory를 기반으로 한 차원 축소 기법으로, t-SNE보다 빠르고 글로벌 구조를 더 잘 보존하는 특징이 있습니다. 핵심 개념은 다음과 같습니다:

 

 a) 토폴로지 학습: 고차원 공간에서 최근접 이웃 그래프를 구축하고, 이를 저차원 공간에서 최적으로 유지합니다.

 b) 확률 분포 기반 최적화: 거리 기반의 그래프를 생성하고 이를 Embedding으로 변환합니다.

 c) 빠른 계산 속도: t-SNE보다 계산 비용이 낮아 대규모 데이터에서도 유리합니다.

 

 UMAP에서 거리 함수는 다음과 같습니다.

 

이때, a와 b는 거리 분포를 최적화하는 상수를 말합니다.

 

비교 항목 t-SNE UMAP
주목하는 부분 지역적 구조 지역적 및 전역적 구조
구현 속도 느림 빠름(병렬 연산 가능)
해석 가능성 상대적으로 낮음 상대적으로 높음
보존 구조 근접 이웃 보존 근접 이웃 + 글로벌 구조 보존
초기화 임의 초기화 k-NN 그래프 기반 초기화

 

 

2. 파이썬 코드를 통해 알아보는 t-SNE와 UMAP

 

이번에는 sciket learn에 있는 mnist_784 데이터를 활용해서 t-SNE와 UMAP을 구현해보겠습니다.

 

mnist_784 데이터는 0부터 9까지의 손글씨 숫자 클래스로 구성되어 있으며 28x28(=784)의 픽셀로 구성된 이미지 입니다.

 

 

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import fetch_openml
from sklearn.manifold import TSNE
import umap
from sklearn.preprocessing import StandardScaler

# 데이터 로드
mnist = fetch_openml('mnist_784', version=1)
X, y = mnist.data, mnist.target.astype(int)

# 데이터 정규화
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# t-SNE 적용
tsne = TSNE(n_components=2, perplexity=30, random_state=42)
X_tsne = tsne.fit_transform(X_scaled[:5000])

# UMAP 적용
umap_model = umap.UMAP(n_components=2, n_neighbors=30, min_dist=0.3, metric='euclidean')
X_umap = umap_model.fit_transform(X_scaled[:5000])

# 시각화
fig, ax = plt.subplots(1, 2, figsize=(12, 6))

sns.scatterplot(x=X_tsne[:, 0], y=X_tsne[:, 1], hue=y[:5000], palette='tab10', ax=ax[0])
ax[0].set_title('t-SNE Visualization')

sns.scatterplot(x=X_umap[:, 0], y=X_umap[:, 1], hue=y[:5000], palette='tab10', ax=ax[1])
ax[1].set_title('UMAP Visualization')

plt.show()

 

 

 

 a) t-SNE 결과

 - 동일한 색상의 점들이 군집(cluster)을 형성하는 경향이 있지만, 몇몇 데이터 포인트는 잘못 배치된 것처럼 보입니다.

- 특히 일부 숫자들(예: 4와 9, 3과 5)은 서로 겹쳐 있어 분리하기 어렵습니다.

 

b) UMAP 결과

 - 숫자 클래스들이 t-SNE보다 더 명확하게 구분되어 있습니다.
- 일부 숫자들(0, 1, 4, 9)은 t-SNE보다 더 뚜렷하게 클러스터링되어 있음.
- 데이터 분포가 조금 더 구조적으로 배치된 느낌이 강하며, 숫자 간의 관계성이 잘 반영됨.

 

 

3. 결론

- 두 방법 모두 데이터의 구조를 유지하며 차원을 축소하는데 강력한 도구입니다. 

- 그렇지만, 이론적인 특징을 통해 알아본 것과 코드 구현을 통해서 알아본 것을 바탕으로 종합해보면

 

 데이터의 전역적인 구조를 구분하는 면에서는 UMAP이 더 좋은 것을 알 수 있고

 데이터의 지역적인 구조에 집중한다면 t-SNE가 더 좋다는 것을 알 수 있습니다.

반응형

댓글