t-SNE
13 Oct 2017 | ml dimension reduction이론적 배경
Stochastic Neighbor Embedding(SNE)
고차원 원공간에 존재하는 데이터 x의 이웃간의 거리를 최대한 보존하는 저차원의 y를 학습하는 방법론
- 원래의 고차원 공간에 존재하는 i번째 object가 주어졌을 때, j번째 object가 선택될 확률
- pj|i=e−|xi−xj|22σ2i∑ke−|xi−xk|22σ2i
- 저차원의 공간에서 i번째 object가 주어졌을 때, j번째 object가 선택될 확률
- qj|i=e−|yi−yj|2∑ke−|yi−yk|2
SNE는 위 두 확률이 비슷해지면 저차원이 잘 모델링된다고 가정을 한다. 확률의 비슷함은 당연히 KL divergence!
그래서 다음 식을 최소화시키도록 학습을 한다. Cost=∑iKL(Pi||Qi)=∑i∑jpj|ilogpj|iqj|i
t-SNE
- SNE에서 σi는 원래 dense한 곳에서는 작고, sparse한 곳에서는 크게 하려고 했는데, 상수로 고정하여도 성능에 큰 차이가 없었음.
- pi|j와 pj|i를 같이 놓고 풀어도 성능이 그리 나쁘지 않았음.
- 그래서 요렇게 변경
- pij=pj|i+pi|j2,qij=qj|i+qi|j2
- 그래서 요렇게 변경
- 그래서 다시 계산하면
- Cost=∑iKL(Pi||Qi)=∑i∑jpijlogpijqij∂C∂yi=4∑j(yj−yi)(pij−qij)
- 요리 나온다. 이거는 유도해보지 않았고… 어차피 gradient descent로 풀어버리니까…
- gaussian은 꼬리가 얇아서 적당히 떨어진 것과 멀리 떨어진 것의 확률이 모두 작다.(crowding problem) 그래서 qij에 대해서 t-분포를 사용했음.
- qij=(1+|yi−yj|2)−1∑k≠l(1+|yk−yl|2)−1
실제 쓸 때 필요한 정보
요거 쓰면 빠른데 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