Реалізація t-SNE Python: розбіжність Kullback-Leibler


11

t-SNE, як у [1], працює шляхом поступового зменшення розбіжності Куллбека-Лейблера (KL) до досягнення певної умови. Творці t-SNE пропонують використовувати дивергенцію KL як критерій продуктивності візуалізацій:

ви можете порівняти розбіжності Kullback-Leibler, про які повідомляє t-SNE. Цілком чудово запустити t-SNE десять разів і вибрати рішення з найнижчою різницею KL [2]

Я спробував дві реалізації t-SNE:

  • python : sklearn.manifold.TSNE ().
  • R : цне, з бібліотеки (цне).

Обидві ці реалізації, коли встановлено багатослівність, друкують помилку (розбіжність Kullback-Leibler) для кожної ітерації. Однак вони не дозволяють користувачеві отримувати цю інформацію, що мені здається дещо дивним.

Наприклад, код:

import numpy as np
from sklearn.manifold import TSNE
X = np.array([[0, 0, 0], [0, 1, 1], [1, 0, 1], [1, 1, 1]])
model = TSNE(n_components=2, verbose=2, n_iter=200)
t = model.fit_transform(X)

виробляє:

[t-SNE] Computing pairwise distances...
[t-SNE] Computed conditional probabilities for sample 4 / 4
[t-SNE] Mean sigma: 1125899906842624.000000
[t-SNE] Iteration 10: error = 6.7213750, gradient norm = 0.0012028
[t-SNE] Iteration 20: error = 6.7192064, gradient norm = 0.0012062
[t-SNE] Iteration 30: error = 6.7178683, gradient norm = 0.0012114
...
[t-SNE] Error after 200 iterations: 0.270186

Тепер, наскільки я розумію, 0,270186 має бути дивергенцією KL. Однак я не можу отримати цю інформацію ні від моделі, ні від t (що є простим numpy.ndarray).

Щоб вирішити цю проблему, я міг би: i) Обчислити розбіжність KL самостійно, ii) Зробити щось неприємне в python для захоплення та розбору виходу функції TSNE () [3]. Однак: i) було б досить нерозумно перерахувати розбіжність KL, коли TSNE () вже обчислив його, ii) було б трохи незвично з точки зору коду.

Чи є у вас якісь інші пропозиції? Чи є стандартний спосіб отримати цю інформацію за допомогою цієї бібліотеки?

Я згадував, що спробував бібліотеку tsne R , але я вважаю за краще відповіді зосередитись на реалізації python sklearn.


Список літератури

[1] http://nbviewer.ipython.org/urls/gist.githubusercontent.com/AlexanderFabisch/1a0c648de22eff4a2a3e/raw/59d5bc5ed8f8bfd9ff1f7faa749d1b095aa97d5a/t-SNNE

[2] http://homepage.tudelft.nl/19j49/t-SNE.html

[3] /programming/16571150/how-to-capture-stdout-output-from-a-python-function-call

Відповіді:


4

Джерело TSNE в scikit-learn є в чистому Python. fit_transform()Метод Fit насправді викликає приватну _fit()функцію, яка потім викликає приватну _tsne()функцію. Ця _tsne()функція має локальну змінну, errorяка роздруковується в кінці підгонки. Здається, ви могли досить легко змінити один-два рядки вихідного коду, щоб повернути це значення fit_transform().


По суті, те, що я міг би зробити, - це встановити self.error = помилку в кінці _tsne (), щоб згодом отримати його з екземпляра TSNE. Так, але це означало б зміну кода sklearn.manifold, і мені було цікаво, чи розробники думали про якісь інші способи отримати інформацію, чи ні, чому вони не зробили (тобто: чи вважається "помилка" марною?). Крім того, якби я змінив цей код, мені знадобилося б, щоб усі люди, які керують моїм кодом, мали однаковий злом на своїх установках sklearn. Це те, що ви пропонуєте, чи я помилився?
жартівник

Так, саме це я запропонував як можливе рішення. Оскільки scikit-learn є відкритим кодом, ви також можете подати своє рішення як запит на виклик і побачити, чи автори включать це у майбутні випуски. Я не можу говорити, чому вони робили чи не включали різні речі.
Трей

2
Дякую. Якщо хтось ще зацікавлений у цьому, github.com/scikit-learn/scikit-learn/pull/3422 .
жартівник
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.