t-SNE

|

이론적 배경

Stochastic Neighbor Embedding(SNE)

고차원 원공간에 존재하는 데이터 x의 이웃간의 거리를 최대한 보존하는 저차원의 y를 학습하는 방법론

  • 원래의 고차원 공간에 존재하는 i번째 object가 주어졌을 때, j번째 object가 선택될 확률
  • 저차원의 공간에서 i번째 object가 주어졌을 때, j번째 object가 선택될 확률

SNE는 위 두 확률이 비슷해지면 저차원이 잘 모델링된다고 가정을 한다. 확률의 비슷함은 당연히 KL divergence!

그래서 다음 식을 최소화시키도록 학습을 한다.

t-SNE

  • SNE에서 $\sigma_i$는 원래 dense한 곳에서는 작고, sparse한 곳에서는 크게 하려고 했는데, 상수로 고정하여도 성능에 큰 차이가 없었음.
  • $p_{i\vert j}$와 $p_{j\vert i}$를 같이 놓고 풀어도 성능이 그리 나쁘지 않았음.
    • 그래서 요렇게 변경
  • 그래서 다시 계산하면
    • 요리 나온다. 이거는 유도해보지 않았고… 어차피 gradient descent로 풀어버리니까…
  • gaussian은 꼬리가 얇아서 적당히 떨어진 것과 멀리 떨어진 것의 확률이 모두 작다.(crowding problem) 그래서 $q_{ij}$에 대해서 t-분포를 사용했음.

실제 쓸 때 필요한 정보

요거 쓰면 빠른데 dimension이 2일때만 된다…ㅠㅠ

multicore-TSNE 이 코드를 받아서 써야한다. scikit-learn의 t-sne와 여러 다른 t-sne 구현체에 대해서 [40164 x 512]로 실험했는데 다들 잘 안나온다. 심지어 segfault까지 나옴.. 요놈을 가져다 쓰자!

10분안에 끝남 (다른 녀석들은 몇시간 기다려도 안됨 ㅠ)

from MulticoreTSNE import MulticoreTSNE as TSNE
import numpy as np

def normalize_data(d):
    row_sums = d.sum(axis=1)
    return (d.T / row_sums).T

tsne = TSNE(n_jobs=16, metric="cosine")  # 16코어, cosine metric
emb = np.load("testKrEn/en_pair.npy")
emb2 = emb.astype(np.double)
Y = tsne.fit_transform(emb2)
np.save("out_2.npy", Y)
Y_norm = normalize_data(Y)
np.save("out_norm_2.npy", Y_norm)

http://techfly.top/2017/03/09/machine_learning_tensorflow_tsne_data_nonlinear_dimensionality_reduction/ 요거 보고 구현해봐야하나…ㅠㅠ

https://github.com/maestrojeong/t-SNE/blob/master/t-SNE.ipynb