[ Python ] UMAP (Uniform Manifold Approximation and Projection)

2019. 5. 22. 00:32분석 Python/구현 및 자료

이것의 관심을 가진 이유는 원래 기본적인 T-SNE은 Visualization 용으로만 쓰는데,

실제로 이 패키지에서는 그 Embedding 한 것을 변수로 사용할 수 있다고 합니다. 

그래서 train을 학습시켜서 그걸 다시 test에 transform 하는 식으로 변형도 가능하다고 해서,

일반적으로 우리가 알고 있는 T-SNE와는 달리, 저차원으로 잘 축소해서 사용할 수 있을 것 같아서 포스팅합니다..

 

https://arxiv.org/abs/1802.03426  https://github.com/lmcinnes/umap https://umap-learn.readthedocs.io/en/latest/parameters.html

제가 한번 해본건데요!

지금 이게 결국 feature로 쓸 수 있다면 KNN Clustering 만으로도 충분히 데이터를 분류할 수 있게 되는 것 같습니다.

이전에 별의별 짓을 해도 성능이 안 올라갔는데 말이죠!

예제로 잇는데 LinearSVC를 사용하는데 확률 값을 뽑으려면 먼가 다른 방법이 필요하더라고요

그래서 참고 자료 올립니다.

http://dev-aux.com/python/how-to-predict_proba-with-linearsvc

 

How to predict_proba with LinearSVC - Developer's hints and tips

Once I had a problem where I have to give the best solution according to Area under the curve (AUC or AUROC) score. I had hundreds of features and my training set was about 100.000 of objects. It was a classification problem. I had tried gradient boosting,

dev-aux.com

CalibratedClassifierCV라는 것을 쓰면 확률 값을 뽑을 수 있더라고요

그리고 GridSearchCV 도 되는데 또 CV라 껄껄... 암튼 돌리니 됩니다.

그래서 같이 올려드립니다.

from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.svm import LinearSVC
X_train, X_test, y_train, y_test = train_test_split(
    embedding ,  labelcode , test_size=0.2, random_state=42)
svc = LinearSVC(dual=False, random_state=123)
params_grid = {"C": [10**k for k in range(-3, 4)]}
from sklearn.calibration import CalibratedClassifierCV
clf = GridSearchCV(svc, params_grid)
cclf = CalibratedClassifierCV(base_estimator=clf , cv=5)
cclf.fit(X_train, y_train)
prob = cclf.predict_proba(X_test)[:,1]
print("Accuracy on the test set with raw data: {:.3f}".format(
    cclf.score(X_test, y_test)))
    
    ## Accuracy on the test set with raw data: 0.919 !!!!!!!!!!!!!!!!!!!!

 

0.919....??? amazing 합니다.

으음 사실 근데 전체 데이터에 대해서 umap을 하고 거기서 train test를 나눴기 때문에 이 부분에서 물론 문제가 있을 수 있지만, 암튼 LinearSVC만으로도 충분히 성능이 나오네요 거기다 2차원인데 말이죠...

 확률 분포도 되게 Cutoff를 보는 데 있어서 여유롭게 잘라도 되는 것이 보이네요

UMAP에 대해 자세히 알아봐야겠습니다

 

 

 

 

 

 

 

밑에 좀 더 보니 pipeline을 이용해서 umap parameter들도 설정해서 embedding 시킬 수가 있네요.

물론 한번 돌릴 때 장난 아니게 오래 걸리더라고요

cuml에도 umap이 있지만 이런 기능은 아직 제공하지 않더라고요.

앞으로 많이 사용해볼 것 같네요 ㄷㄷㄷ

umap = UMAP(random_state=456)
pipeline = Pipeline([("umap", umap),
                     ("svc", svc)])
params_grid_pipeline = {"umap__n_neighbors": [5, 20],
                        "umap__n_components": [15, 25, 50],
                        "svc__C": [10**k for k in range(-3, 4)]}

clf_pipeline = GridSearchCV(pipeline, params_grid_pipeline)
clf_pipeline.fit(X_train, y_train)
print("Accuracy on the test set with UMAP transformation: {:.3f}".format(
    clf_pipeline.score(X_test, y_test)))

 

Location 변수를 2차원으로 투영시키고 싶어서 UMAP을 이용해서 투영시키면 다음과 같이 나온다.

음...........................음?

만든 사람한테 물어보니 변수 1개를 가지고하면은 동등한 거리에 있는 구조로 만들기 때문에 어려울 것 같다고 한다. 

그래서 여러개를 돌리고 metric = "dice"를 쓰라고 했더니 오른쪽 그림과 같이 나왔다.

으음 이렇게 되면 기대할 수 있는게 Feature combination 같은 효과가 일어나서 파생변수를 쓸수 있느 것일까?

오른쪽 그림은 152차원으로 된 여러개의 onehot으로 된 것을 2차원으로 만든 그림입니다.

저번에 tensorflow로 categorical도 embedding해서 word2vec loss로 최소화한다음에 embedding 된 것을 쓰려고 했는데, Loss가 어떠한 상수로 유지가 됬었습니다.

그래서 먼가 그것도 다른 변수랑 같이 학습했으면 더 효과가 좋았을까?라는 생각이 드네요.

한개의 변수했던 것과 여러개의 Categorical 변수를 합쳐서 만들었을 때 그림

모델 저장 방식

import numpy as np
from sklearn.datasets import load_digits
digits = load_digits()
X = digits.data
y = digits.target
import umap
reducer = umap.UMAP()
embedding = reducer.fit_transform(X, y)
print(embedding.shape)
# (1797, 2)
import joblib
filename = 'this_is_a_test.sav'
joblib.dump(reducer, filename)
#time passes 
loaded_reducer = joblib.load(filename)
print(type(loaded_reducer))
# <class 'umap.umap_.UMAP'>
# with pickle
import pickle
f_name = 'saving_example.sav'
pickle.dump(reducer, open(f_name, 'wb'))
# time passes
loaded_model = pickle.load((open(f_name, 'rb')))
print(type(loaded_model))
# <class 'umap.umap_.UMAP'>
728x90