본문 바로가기
RESEARCH

[읽을거리 링크] t-Stochastic Neighbor Embedding (t-SNE) + 예제코드(Python)

by BLADEBONE 2019. 8. 12.

 

t-Stochastic Neighbor Embedding(t-SNE, "티스니"라 읽음)은 2008년 Journal of Machine Learning Research에 실린 Laurens van der Maaten과 Geoffrey Hinton의 Visualizing Data using t-SNE 논문에서 제안되었으며, 해당 논문은 9000회 이상 인용된 인기 논문이다. t-SNE의 주요 목적은 Data Visualization으로 고차원 데이터(high-dimensional data)를 2차원 또는 3차원의 저차원 데이터로 시각화하여 데이터 분석 과정에서 활용하기 위한 방법이다. 

 

데이터 분석 시 가장 먼저 하는 일이 데이터의 시각화인데 가장 기초적인 방법으로 주성분분석법(principal component analysis, PCA)이 있다. 이는 데이터의 공분산(covariance)을 분석하여 선형변환 행렬(linear transformation matriix)을 얻어 차원을 축소하는 방법이다. PCA는 선형변환을 이용하기 때문에 비선형 특성을 가진 데이터에 대해서는 데이터의 특성을 잘 추출하지 못하는 한계가 있다. 

 

데이터에 내재된 비선형적 특성을 고려하기 위해 다양한 비선형 차원 축소 기법들 - Stochastic Neighbor Embedding(SNE, Hinton and Roweis, 2002), Isomap (Tenenbaum et al, 2000), Locally Linear Embedding (LLE, Roweis ans Saul, 2000), etc - 이 제안되었는데, t-SNE도 그 중 하나이다. 

 

t-SNE는 인기있는 내용이다 보니 관련글들이 상당히 많았는데 t-SNE를 이해하고 활용하는데 있어 참고할만한 자료들을 아래에 정리하였다.

 

 

 

1) t-SNE 이론 정리

 

■ t-SNE를 이용한 차원 감소 (Dimension reduction), 조대협의 블로그
https://bcho.tistory.com/1210

 

t-SNE를 이용한 차원 감소 (Dimension reduction)

t-SNE를 이용한 차원 감소 조대협 (http://bcho.tistory.com) PCA 기반 차원 감소의 문제점 앞의 글에서 차원 감소에 대한 개념과, 차원 감소 알고리즘의 하나인 PCA 알고리즘에 대해서 살펴보았다. PCA의 경우 선..

bcho.tistory.com

 

■ t-SNE, ratsgo's blog

https://ratsgo.github.io/machine%20learning/2017/04/28/tSNE/

 

t-SNE · ratsgo's blog

이번 글에서는 데이터 차원축소(dimesionality reduction)와 시각화(visualization) 방법론으로 널리 쓰이는 t-SNE(Stochastic Neighbor Embedding)에 대해 살펴보도록 하겠습니다. 단어 벡터와 같이 고차원 데이터를 시각화하는 데 가장 인기있는 알고리즘이기도 합니다. 이번 글 역시 고려대 강필성 교수님 강의를 정리했음을 먼저 밝힙니다. 그럼 시작하겠습니다. Stochastic Neighbor Embeddin

ratsgo.github.io

 

 

■ t-SNE 정리, 홍게

https://ml-dnn.tistory.com/10

 

T-SNE 정리(1/2) Stochastic neighborhood embedding SNE 요약 정리

T-sne Visualizing data using t-SNE¶ T-SNE를 사용한 데이터 차원 축소 시각화¶ T-SNE 를 본격적으로 다루기 전에 SNE에 대해서 설명합니다.¶ 1. Introduction¶ 1-1 높은 차원의 데이터시각화¶ 높은 차원의..

ml-dnn.tistory.com

 

 

2) t-SNE 예제 (python - scikit-learn 활용, PCA와 함께)

 

■ Visualising high-dimensional datasets using PCA and t-SNE in Python, Luuk Derksen(Towards Data Science)

https://towardsdatascience.com/visualising-high-dimensional-datasets-using-pca-and-t-sne-in-python-8ef87e7915b

 

Visualising high-dimensional datasets using PCA and t-SNE in Python

Update: April 29, 2019. Updated some of the code to not use ggplot but instead use seaborn and matplotlib. I also added an example for a…

towardsdatascience.com

 

■ 고차원 데이터의 차원 축소와 시각화 방법 (PCA vs. t-SNE)  ※ 바로 위 사이트 번역 + 추가 정리

https://skyeong.net/186

 

고차원 데이터의 차원 축소와 시각화 방법 (PCA vs. t-SNE)

데이터분석과 관련하여 가장 중요한 것은 데이터가 어떻게 생겼는지 탐색하는 과정입니다. 이 과정에 데이터의 특정 변수의 분포를 관찰할 수도 있고, 서로 상관관계가 있는 변수들이 어떻것이 있는지 살표보는 과..

skyeong.net

 

 

3) t-SNE 코드 실행시 오류 해결 (scikit-learn fetch_mldata 오류)

 

■ scikit-learn의 fetch-mldata('MNIST original') 에러, TAEWAN.KIM 블로그

http://taewan.kim/post/sklearn_mnist_fetch_error/

 

scikit-learn의 fetch_mldata('MNIST original') 에러

Sklearn의 mnist 데이터 패치 오류를 해결하는 방법입니다.

taewan.kim

 

※ 초보자의 경우, 라이브러리 코드에서 오류가 발생하면 손도 되지 못하고 어찌할 수 없는 경우가 많은 위 블로그와 같이 몸소 나서서 해결하시는 훌륭한 분들이 있어 고마울 따름

 

 

4) t-SNE 활용 (perplexity의 역할)

 

■ t-Stochatic Neighbor Embeddding (t-SNE)와 perplexity, LOVIT x DATA SCIENCE

https://lovit.github.io/nlp/representation/2018/09/28/tsne/

 

t-Stochastic Neighbor Embedding (t-SNE) 와 perplexity

t-Stochastic Nearest Neighbor (t-SNE) 는 vector visualization 을 위하여 자주 이용되는 알고리즘입니다. t-SNE 는 고차원의 벡터로 표현되는 데이터 간의 neighbor structure 를 보존하는 2 차원의 embedding vector 를 학습함으로써, 고차원의 데이터를 2 차원의 지도로 표현합니다. t-SNE 는 벡터 시각화를 위한 다른 알고리즘들보다 안정적인 임베딩 학습 결과를 보여줍니다. 이는 t

lovit.github.io

 

 

5) 샘플 코드 (2019.08.12 기준)

 

■ Python Configuration

 

Python 3.6.8 / numpy 1.16.1 / pandas 0.24.1 / scikit-learn 0.20.2 / matplotlib 3.0.2 / seaborn 0.9.0

 

 

■ Code File Download

 

tSNE_MNIST.ipynb
2.51MB
tSNE_MNIST.py
0.01MB

 

■ Plot of sampled MNIST data (N=10000)

 

< PCA vs. t-SNE vs. PCA 50 + t-SNE >

 

 

■ Python Code (tSNE-MNIST.py)

# code by Luuk Derksen
# https://towardsdatascience.com/visualising-high-dimensional-datasets-using-pca-and-t-sne-in-python-8ef87e7915b

from __future__ import print_function
import time

import numpy as np
import pandas as pd

from sklearn.datasets import fetch_mldata
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE

# %matplotlib inline
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

import seaborn as sns

## Download MNIST mat file from GitHub
import os
from sklearn import datasets
import urllib.request

basedir = datasets.get_data_home()
targetdir = os.path.join(basedir, "mldata")
targetfile = os.path.join(targetdir, "mnist-original.mat")

if os.path.isfile(targetfile):
    print("The MNIST data file exists in your directory")
    print(targetdir)
else:    
    print("Download the MNIST data file from github URL")
    fileURL = "https://github.com/amplab/datascience-sp14/raw/master/lab7/mldata/mnist-original.mat"
    urllib.request.urlretrieve(fileURL, targetfile)

## loading data
mnist = fetch_mldata("MNIST original", data_home=basedir)
X = mnist.data / 255.0
y = mnist.target
print(X.shape, y.shape)

## Convert matrix/vector to Pandas DataFrame
feat_cols = [ 'pixel'+str(i) for i in range(X.shape[1]) ]
df = pd.DataFrame(X,columns=feat_cols)
df['y'] = y
df['label'] = df['y'].apply(lambda i: str(i))
X, y = None, None
print('Size of the dataframe: {}'.format(df.shape))

## For Reproducibility  of the results
np.random.seed(42)
rndperm = np.random.permutation(df.shape[0])
    
## Plot image
fig = plt.figure( figsize=(16,7) )
plt.gray()
for i in range(0,15):
    ax = fig.add_subplot(3,5,i+1, title="Digit: {}".format(str(df.loc[rndperm[i],'label'])) )
    ax.matshow(df.loc[rndperm[i],feat_cols].values.reshape((28,28)).astype(float))
plt.show()

## PCA for full data
pca = PCA(n_components=3)
pca_result = pca.fit_transform(df[feat_cols].values)
df['pca-one'] = pca_result[:,0]
df['pca-two'] = pca_result[:,1] 
df['pca-three'] = pca_result[:,2]
print('Explained variation per principal component: {}'.format(pca.explained_variance_ratio_))

# plot PCA features, 1st & 2nd components
plt.figure(figsize=(16,10))
sns.scatterplot(
    x="pca-one", y="pca-two",
    hue="y",
    palette=sns.color_palette("hls", 10),
    data=df.loc[rndperm,:],
    legend="full",
    alpha=0.3
)
plt.show()

# plot PCA features, 1st, 2nd, and 3rd components
ax = plt.figure(figsize=(16,10)).gca(projection='3d')
ax.scatter(
    xs=df.loc[rndperm,:]["pca-one"], 
    ys=df.loc[rndperm,:]["pca-two"], 
    zs=df.loc[rndperm,:]["pca-three"], 
    c=df.loc[rndperm,:]["y"], 
    cmap='tab10'
)
ax.set_xlabel('pca-one')
ax.set_ylabel('pca-two')
ax.set_zlabel('pca-three')
plt.show()

## t-SNE 
# PCA for sampled data (N=10000)
N = 10000
df_subset = df.loc[rndperm[:N],:].copy()
data_subset = df_subset[feat_cols].values
pca = PCA(n_components=3)
pca_result = pca.fit_transform(data_subset)
df_subset['pca-one'] = pca_result[:,0]
df_subset['pca-two'] = pca_result[:,1] 
df_subset['pca-three'] = pca_result[:,2]
print('Explained variation per principal component: {}'.format(pca.explained_variance_ratio_))

# t-SNE
time_start = time.time()
tsne = TSNE(n_components=2, verbose=1, perplexity=40, n_iter=300)
tsne_results = tsne.fit_transform(data_subset)
print('t-SNE done! Time elapsed: {} seconds'.format(time.time()-time_start))

# plot
df_subset['tsne-2d-one'] = tsne_results[:,0]
df_subset['tsne-2d-two'] = tsne_results[:,1]
plt.figure(figsize=(16,10))
sns.scatterplot(
    x="tsne-2d-one", y="tsne-2d-two",
    hue="y",
    palette=sns.color_palette("hls", 10),
    data=df_subset,
    legend="full",
    alpha=0.3
)
plt.show()

## PCA vs. t-SNE
plt.figure(figsize=(16,7))
ax1 = plt.subplot(1, 2, 1)
sns.scatterplot(
    x="pca-one", y="pca-two",
    hue="y",
    palette=sns.color_palette("hls", 10),
    data=df_subset,
    legend="full",
    alpha=0.3,
    ax=ax1
)
ax2 = plt.subplot(1, 2, 2)
sns.scatterplot(
    x="tsne-2d-one", y="tsne-2d-two",
    hue="y",
    palette=sns.color_palette("hls", 10),
    data=df_subset,
    legend="full",
    alpha=0.3,
    ax=ax2
)
plt.show()

## t-SNE after PCA 50
# PCA 50
pca_50 = PCA(n_components=50)
pca_result_50 = pca_50.fit_transform(data_subset)
print('Cumulative explained variation for 50 principal components: {}'.format(np.sum(pca_50.explained_variance_ratio_)))
# t-SNE
time_start = time.time()
tsne = TSNE(n_components=2, verbose=0, perplexity=40, n_iter=300)
tsne_pca_results = tsne.fit_transform(pca_result_50)
print('t-SNE done! Time elapsed: {} seconds'.format(time.time()-time_start))

# plot
df_subset['tsne-pca50-one'] = tsne_pca_results[:,0]
df_subset['tsne-pca50-two'] = tsne_pca_results[:,1]
plt.figure(figsize=(16,4))
ax1 = plt.subplot(1, 3, 1)
sns.scatterplot(
    x="pca-one", y="pca-two",
    hue="y",
    palette=sns.color_palette("hls", 10),
    data=df_subset,
    legend="full",
    alpha=0.3,
    ax=ax1
)
ax2 = plt.subplot(1, 3, 2)
sns.scatterplot(
    x="tsne-2d-one", y="tsne-2d-two",
    hue="y",
    palette=sns.color_palette("hls", 10),
    data=df_subset,
    legend="full",
    alpha=0.3,
    ax=ax2
)
ax3 = plt.subplot(1, 3, 3)
sns.scatterplot(
    x="tsne-pca50-one", y="tsne-pca50-two",
    hue="y",
    palette=sns.color_palette("hls", 10),
    data=df_subset,
    legend="full",
    alpha=0.3,
    ax=ax3
)
plt.show()

 

 

 

반응형

댓글