#!/usr/bin/env python3


t-SNE를 이용한 매니폴드 학습


데이터를 산점도로 시각화할 수 있다는 이점 때문에 PCA가 데이터 변환에 가장 먼저 시도해볼 만한 방법이지만,

LFW(Labeled Faces in the Wild) 데이터셋의 산점도에서 본 것처럼 알고리즘의(회전하고 방향을 제거하는) 유용성이 떨어짐

maniford learning매니폴드 학습 알고리즘이라고 하는 시각화 알고리즘들은 훨씬 복잡한 매핑을 만들어 더 나은 시각화를 제공

t-SNE(t-Distributed Stochastic Neighbor Embedding) 알고리즘을 아주 많이 사용함


maniford learnning 알고리즘은 그 모적이 시각화라 3개이상의 특성을 뽑는 경우는 거의 없음

t-SNE를 포함해서 일부 maniford learnning 알고리즘들은 훈련 데이터를 새로운 표현으로 변환시키지만 새로운 데이터에는 변활할 수 없음

즉 테스트세트에는 적용할 수 없고, 단지 훈련데이터에만 변환할 수 있음


따라서 maniford learnning은 탐색적 데이터 분석에 유용하지만 지도학습용으로는 거의 사용하지 않음


t-SNE의 아이디어는 데이터 포인트 사이의 거리를 가장 잘 보존하는 2차원 표현을 찾는 것

먼저 t-SNE는 각 데이터 포인트를 2차원에 무작위로 표현한 후 원본 특성 공간에서 가까운 포인트는 가깝게, 멀리 떨어진 포인트는 멀어지게 만듬

t-SNE는 가까이 있는 포인트에 더 많은 비중을 둠 ==> 이웃 데이터 포인트에 대한 정보를 보존하려함



1. 손글씨 숫자 데이터셋에 t-SNE maniford learnning을 적용

# load library

from sklearn.datasets import load_digits

import matplotlib

import matplotlib.pyplot as plt


# matplotlib 설정

matplotlib.rc('font', family='AppleGothic'# 한글 출력

plt.rcParams['axes.unicode_minus'] = False # 축 - 설정


# data load

digits = load_digits()


# subplot 객체 생성

fig, axes = plt.subplots(2, 5, #  subplot객체(2x5)를 axes에 할당

                         subplot_kw={'xticks':(), 'yticks':()}) # subplot 축 눈금 해제


for ax, img in zip(axes.ravel(), digits.images): # axes.ravel()과 digits.images를 하나씩 할당

    ax.imshow(img)

plt.gray() # 그래프 흑백

plt.show() # 그래프 출력

숫자 데이터셋의 샘플 이미지



2. PCA를 사용하여 데이터를 2차원으로 축소해 시각화

### 처음 두 개의 주성분을 이용해 그래프를 그리고 각 샘플을 해당하는 클래스의 숫자로


from sklearn.decomposition import PCA


# PCA 모델을 생성

pca = PCA(n_components=2) # 주성분 갯수

pca.fit(digits.data) # PCA 적용


# 처음 두 개의 주성분으로 숫자 데이터를 변환

digits_pca = pca.transform(digits.data) # PCA를 데이터에 적용

colors = ['#476A2A', '#7851B8', '#BD3430', '#4A2D4E', '#875525',

               '#A83683', '#4E655E', '#853541', '#3A3120', '#535D8E']


for i in range(len(digits.data)): # digits.data의 길이까지 정수 갯수

    # 숫자 텍스트를 이용해 산점도 그리기

    plt.text(digits_pca[i, 0], digits_pca[i, 1], str(digits.target[i]), # x, y, 그룹; str은 문자로 변환

             color=colors[digits.target[i]], # 산점도 색상

             fontdict={'weight':'bold', 'size':9}) # font 설정

plt.xlim(digits_pca[:, 0].min(), digits_pca[:,1].max()) # 최소, 최대

plt.ylim(digits_pca[:, 1].min(), digits_pca[:,1].max()) # 최소, 최대

plt.xlabel('first principle component'# x 축 이름

plt.ylabel('second principle componet'# y 축 이름

plt.show()

처음 두 개의 주성분을 사용한 숫자 데이터셋의 산점도


각 클래스가 어디 있는지 보기 위해 실제 숫자를 사용해 산점도를 출력

숫자 0, 6, 4는 두 개의 주성분만으로 잘 분리 됨

다른 숫자들은 대부분 많은 부분이 겹쳐 있음


3. 같은 데이터셋에 t-SNE를 적용해 결과를 비교

### TSNE모델에는 transform 메소드가 없고 fit_transform만 있음


# library import

from sklearn.manifold import TSNE


# t-SNE 모델 생성 및 학습

tsne = TSNE(random_state=0)

digits_tsne = tsne.fit_transform(digits.data)


# 시각화

for i in range(len(digits.data)): # 0부터  digits.data까지 정수

    plt.text(digits_tsne[i, 0], digits_tsne[i, 1], str(digits.target[i]), # x, y , 그룹

             color=colors[digits.target[i]], # 색상

             fontdict={'weight': 'bold', 'size':9}) # font

plt.xlim(digits_tsne[:, 0].min(), digits_tsne[:, 0].max()) # 최소, 최대

plt.ylim(digits_tsne[:, 1].min(), digits_tsne[:, 1].max()) # 최소, 최대

plt.xlabel('t-SNE 특성0'# x축 이름

plt.ylabel('t-SNE 특성1'# y축 이름

plt.show() # 그래프 출력

t-SNE로 찾은 두 개의 성분을 사용한 숫자 데이터셋의 산점도


모든 클래스가 확실히 잘 구분 되었음

이 알고리즘은 클래스 레이블 정보를 사용하지 않으므로 완전한 비지도 학습

그럼에도 원본 데이터 공간에서 포인트들이 얼마나 가가이 있는지에 대한 정보로 클래스가 잘 구분되는 2차원 표현을 찾음


t-SNE의 매개변수perplexity, early_exaggeration


perplexity: 값이 크면 더 많은 이웃을 포함하여 작은 그룹은 무시

                       기본값 = 30

                       보통 5~50사이의 값을 가짐


early_exaggeration: 원본 공간의 클러스터들이 얼마나 멀게 2차원에 나타낼지를 정함, 기본값은 4

                                         최소한 1보다 커야하고 값이 클수록 간격이 커짐

+ Recent posts