수달이네 기술 블로그

4. 차원 축소 시각화(t-SNE, UMAP, initialization: random, PCA) 본문

AI공부/멀티모달

4. 차원 축소 시각화(t-SNE, UMAP, initialization: random, PCA)

슬픈 수달이 2026. 3. 16. 13:31

구현(차원축소)

  1. MNIST와 CIFAR10데이터셋 다운로드
  2. (이미지, 라벨)형태의 데이터셋을 순회하며 이미지를 0~1로 정규화
  3. 2D/3D이미지를 1D벡터로 펼침
  4. 각 데이터셋에서 1000개씩 랜덤 샘플링
  5. t-SNE로 2차원 임베딩 생성
  6. 라벨별로 점을 찍고 범례 표시

모듈, 데이터셋 로드

import numpy as np
from umap import UMAP # pip install umap-learn
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
from torchvision.datasets import MNIST, CIFAR10

mnist = MNIST(root='.', train=True, download=True) 
cifar10 = CIFAR10(root='.', train=True, download=True)
  • MNIST 데이터셋: 28×28×1(흑백) = 784 크기, train 60000장, test 10000장
  • CIFAR-10 데이터셋: 32×32×3(rgb) = 3072 크기, train 50000장, test 10000장

사이킷런 데이터셋을 convert해주는 함수

def convert_sklearn_dataset(pytorch_dataset):
  X, y = [], []
  for image, label in pytorch_dataset:
    x = np.array(image) 
    x = x / 255 
    X.append(x)
    y.append(label)
  X = np.array(X)
  X = X.reshape(len(X), -1) # 이미지를 1차원 벡터로 평탄화(MAP, t-SNE 같은 함수에 넣을 수 있도록)
  y = np.array(y)
  return X, y
  • 이미지 로드 → 0~1로 정규화 → 반복
  • X를 1차원의 벡터로 평탄화(x.reshape: (N, HWC))
    • MNIST: (60000, 784)
    • CIFAR-10: (50000, 3072)

데이터셋을 불러온 후

mnist_X, mnist_y = convert_sklearn_dataset(mnist)
cifar10_X, cifar10_y = convert_sklearn_dataset(cifar10)
mnist_X
# array([[0., 0., 0., ..., 0., 0., 0.],
#        [0., 0., 0., ..., 0., 0., 0.],
#        [0., 0., 0., ..., 0., 0., 0.],
#        ...,
#        [0., 0., 0., ..., 0., 0., 0.],
#        [0., 0., 0., ..., 0., 0., 0.],
#        [0., 0., 0., ..., 0., 0., 0.]], shape=(60000, 784))
  • convert함수 적용

t-SNE적용

tsne_random = TSNE(n_components=2, perplexity=30, init="random", random_state=2026)
tsne_pca = TSNE(n_components=2, perplexity=30, init="pca", random_state=2026)

TSNE메서드(t-SNE 객체를 생성해줌)

  • n_component=2: 2차원으로 줄여서 화면에 그리기 좋게 만듦.(시각화)
  • perplexity = 200: 근처에 몇개의 이웃을 고려할지 설정
    • 그 분포의 엔트로피가 log(perplexity)가 되도록 설정한다.
    • 5~50 일반적, 데이터가 많으면 더 커짐(클수록 전역, 작을수록 국소에 집중)
  • init: 초기값 설정(initialization)을 random값으로 할지 PCA(주성분 분석)로 초기화 할지 설정

minst, cifar10 데이터셋 전체에서 1000개의 인덱스를 중복없이 뽑아낸다.

np.random.seed(2025)
mnist_idx = np.random.choice(len(mnist_X), 1000, replace=False)
cifar10_idx = np.random.choice(len(cifar10_X), 1000, replace=False)
  • mnist_idx = (1000, 784)
  • cifar-10_idx: (1000, 3072)

임베딩

def plot_embedding(model, X, y, idx):
    X_set = X[idx] 
    y_set = y[idx]

    X_set = model.fit_transform(X_set)
    class_names = set(y_set)

    for i, class_name in enumerate(class_names): # class_names의 개수 = 10개
        plt.scatter(
            X_set[y_set == class_name, 0],
            X_set[y_set == class_name, 1],
            color=plt.cm.tab10(i),
            label=class_name,
        )
    plt.xlabel('component 0')
    plt.ylabel('component 1')
    plt.legend()
    plt.show()

고차원 데이터를 저차원 좌표변환하는 과정

  • X_set: (1000, 784)
  • y_set: (1000)
  • model.fit_transform: 모델 학습과 차원 축소를 한다. (1000, 2) → 2차원으로 압축하기 때문
    • 학습: 데이터 포인트 간의 이웃 관계, 거리 분포, 확률 분포를 계산 학습
    • 차원 축소: 학습된 표현을 바탕으로 실제 데이터를 저차원(2) 공간에 매핑

t-SNE

t-SNE, MNIST 데이터, 랜덤 초기화

plot_embedding(tsne_random, mnist_X, mnist_y, mnist_idx)

고차원의 데이터 벡터를 2차원으로 축소한 것을 확인할 수 있다.

  • 가까운 점은 더 가깝게 배치했고, 먼 점은 더 멀리 배치한 t-SNE의 구조를 확인 가능하다.

t-SNE, MNIST데이터, PCA초기화

plot_embedding(tsne_pca, mnist_X, mnist_y, mnist_idx)

미세하고 명확히 보이진 않지만, 좀더 안정적으로 나눠짐.

t-SNE, CIFAR-10데이터, 랜덤 초기화

plot_embedding(tsne_random, cifar10_X, cifar10_y, cifar10_idx)

CIFAR데이터셋이 훨씬 크고, 차원이 많으므로, 분리가 힘듦을 알 수 있따.

t-SNE, CIFAR-10데이터, PCA 초기화

plot_embedding(tsne_pca, cifar10_X, cifar10_y, cifar10_idx)

마찬가지로 큰 차이는 없다.

UMAP

umap = UMAP(n_components=2, min_dist=.05, n_neighbors=8, random_state=2025)
  • n_components = 2: 2차원으로 줄임
  • min_dist: 점들 사이의 최소 거리
    • 그래프 기반으로 공간을 구성하므로
    • 저차원의 공간에 임베딩할 때 점 사이의 거리를 제어하는 파라미터가 필요하다.
  • n_neighbors: 데이터의 지역 구조를 파악할 때 몇 개의 이웃을 참고할지 결정(t_SNE의 perplexity와 비슷)
    • 그래프를 만들 때 각 점이 연결할 이웃의 수(KNN기반)
  • init이 없으므로 기본인 spectral 값으로 초기화된다.

UMAP, MNIST 데이터셋, spectral 초기화(default)

plot_embedding(umap, mnist_X, mnist_y, mnist_idx)

UMAP, CIFAR-10 데이터셋, spectral 초기화

plot_embedding(umap, cifar10_X, cifar10_y, cifar10_idx)

  • t-SNE와 같이 역시 마찬가지로 명확하게 분리되진 않았으나, 그래도 같은 색끼리 비슷한 구역에 뭉쳐짐을 확인 할 수 있다.