logo

매니폴드 학습

비슷한 것끼리 가깝게 표현하기

  • 새 변수를 만드는 것보다, 비슷한 관측치끼리 가까이 모이도록 하는 것이 목적인 방법
  • 고차원 데이터를 시각화할 때 주로 사용
  • 예시: 손글씨 숫자 이미지가 8×8 = 64개 픽셀로 이루어진 경우
    • 픽셀 하나가 변수 하나이므로 64차원 데이터 → 시각화가 불가능
    • 64차원에서 가까운 이미지를 2차원에서 가까운 점으로 표현하여 시각화

t-SNE

  • t-SNE(t-Distributed Stochastic Neighbor Embedding): 모든 거리를 살리려 하지 않고, 가까운 이웃 관계를 살리는 데 집중하는 방법
    • 원래 공간에서 이웃이던 점들은 그림에서도 꼭 이웃으로 놓음
    • 멀리 있던 점들은 멀리 떨어뜨려 놓기만 하고, 얼마나 먼지는 정확히 맞추지 않음
  • 그림을 해석할 때 주의할 점
    • 무리가 보이는 것은 의미 있음: 비슷한 관측치끼리 모여 있다는 뜻
    • 무리의 크기와 무리 사이의 거리는 그대로 해석하면 안 됨: t-SNE는 가까운 이웃 관계만 신경 쓰기 때문
    • 실행할 때마다 그림 모양이 달라질 수 있음
    • 데이터가 많으면 계산이 오래 걸림

t-SNE는 어떻게 계산하나

  • 원래 공간에서 점마다 "다른 점이 내 이웃일 확률"을 계산. 가까울수록 확률이 높음(정규분포 사용)
  • 2D 그림에서도 같은 방식으로 이웃 확률을 계산(t분포 사용)
  • 두 확률이 최대한 비슷해지도록 그림 속 점의 위치를 조금씩 옮김. 두 확률의 차이는 KL 발산이라는 값으로 측정
  • 2D 쪽에 꼬리가 두꺼운 t분포를 쓰기 때문에, 먼 점들은 더 멀리 밀려나고 서로 다른 무리가 더 뚜렷하게 떨어져 보임

실습 프롬프트

🤖 AI 프롬프트
scikit-learn의 손글씨 숫자 데이터(load_digits)를 PCA와 t-SNE로 각각 2차원으로 줄여
숫자별로 색을 다르게 한 산점도를 그려 비교해줘.
Python 코드를 작성하고, 초보자를 위한 한글 주석을 달아줘.

실습: 데이터 불러오기

  • scikit-learn에 포함된 손글씨 숫자 데이터 사용
  • 이미지 1,797개, 각 이미지는 8×8 = 64개 픽셀
  • y는 이미지가 나타내는 숫자(0-9)
from sklearn.datasets import load_digits

X, y = load_digits(return_X_y=True)
X.shape
실행 결과
(1797, 64)

첫 번째 이미지를 8×8로 되돌려 그려보면 숫자 0이다.

import matplotlib.pyplot as plt

# 첫 번째 이미지(64개 값)를 8×8로 되돌려 흑백으로 그림 (gray_r: 값이 클수록 검게)
plt.imshow(X[0].reshape(8, 8), cmap="gray_r")

손글씨 숫자 데이터의 첫 번째 이미지

PCA로 2차원 그리기

from sklearn.decomposition import PCA
import seaborn as sns

X_pca = PCA(n_components=2).fit_transform(X)  # 64차원을 PCA로 2차원으로 축소
sns.scatterplot(
  x=X_pca[:, 0],     # 가로축: 첫 번째 주성분
  y=X_pca[:, 1],     # 세로축: 두 번째 주성분
  hue=y,             # 실제 숫자(0-9)에 따라 색을 다르게
  palette="tab10",   # 10가지 색을 구분하기 쉬운 색 조합
  legend="full",     # 범례에 숫자 10개를 모두 표시
  s=10)              # 점 크기

손글씨 숫자 데이터를 PCA로 2차원에 그린 산점도

  • 0, 4, 6처럼 바깥쪽에 따로 모이는 숫자도 있음
  • 하지만 1, 5, 7, 8 등은 가운데에 뒤섞여 구분하기 어려움

t-SNE로 2차원 그리기

from sklearn.manifold import TSNE

# 64차원을 t-SNE로 2차원으로 축소 (random_state: 실행할 때마다 같은 그림이 나오도록 고정)
X_tsne = TSNE(n_components=2, random_state=0).fit_transform(X)
sns.scatterplot(
  x=X_tsne[:, 0],    # 가로축: t-SNE 첫 번째 좌표
  y=X_tsne[:, 1],    # 세로축: t-SNE 두 번째 좌표
  hue=y,             # 실제 숫자(0-9)에 따라 색을 다르게
  palette="tab10",   # 10가지 색을 구분하기 쉬운 색 조합
  legend="full",     # 범례에 숫자 10개를 모두 표시
  s=10)              # 점 크기

손글씨 숫자 데이터를 t-SNE로 2차원에 그린 산점도

  • 숫자별로 무리가 뚜렷하게 나뉨
  • 같은 숫자가 두세 개의 작은 무리로 나뉘기도 함: 같은 숫자라도 쓰는 방식이 여러 가지이기 때문
  • random_state를 바꾸면 무리의 위치와 모양이 달라지지만, 숫자별로 나뉜다는 결과는 비슷함

퀴즈

문제 1 / 4맞음: 0힌트: 0틀림: 0채점중: 0남음: 4

매니폴드 학습의 주된 목적으로 가장 적절한 것은?

  • ○비슷한 관측치끼리 가까이 모이도록 저차원에 표현한다
  • ○다른 모형의 입력으로 쓸 새 변수를 만든다
  • ○결측값을 채워 데이터를 정리한다
  • ○정답이 있는 데이터로 새 사례의 클래스를 예측한다

퀴즈를 풀려면 대화형 기능을 불러와야 합니다.

Previous
요인 분석과 주성분 분석