t-SNE Python-Implementierung: Kullback-Leibler-Divergenz

11

t-SNE reduziert wie in [1] schrittweise die Kullback-Leibler (KL) -Divergenz, bis eine bestimmte Bedingung erfüllt ist. Die Entwickler von t-SNE schlagen vor, die KL-Divergenz als Leistungskriterium für die Visualisierungen zu verwenden:

Sie können die von t-SNE gemeldeten Kullback-Leibler-Divergenzen vergleichen. Es ist vollkommen in Ordnung, t-SNE zehnmal auszuführen und die Lösung mit der geringsten KL-Divergenz auszuwählen [2].

Ich habe zwei Implementierungen von t-SNE ausprobiert:

  • Python : sklearn.manifold.TSNE ().
  • R : tsne, aus der Bibliothek (tsne).

Beide Implementierungen drucken bei eingestellter Ausführlichkeit den Fehler (Kullback-Leibler-Divergenz) für jede Iteration. Sie erlauben dem Benutzer jedoch nicht, diese Informationen abzurufen, was für mich etwas seltsam aussieht.

Zum Beispiel der Code:

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)

produziert:

[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

Soweit ich weiß, sollte 0,270186 die KL-Divergenz sein. Allerdings kann ich diese Informationen weder vom Modell noch von t (was eine einfache numpy.ndarray ist) erhalten.

Um dieses Problem zu lösen, könnte ich: i) die KL-Divergenz selbst berechnen, ii) etwas Böses in Python tun, um die Ausgabe der TSNE () -Funktion zu erfassen und zu analysieren [3]. Allerdings: i) wäre es ziemlich dumm, die KL-Divergenz neu zu berechnen, wenn TSNE () sie bereits berechnet hat, ii) wäre in Bezug auf den Code etwas ungewöhnlich.

Hast du noch einen anderen Vorschlag? Gibt es eine Standardmethode, um diese Informationen mithilfe dieser Bibliothek abzurufen?

Ich erwähnte , habe ich versucht , R ‚s tsne Bibliothek, aber ich würde es vorziehen , die Antworten auf die konzentrieren Python sklearn Implementierung.


Verweise

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

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

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

Joker
quelle

Antworten:

4

Die TSNE-Quelle in scikit-learn ist in reinem Python. Die Fit- fit_transform()Methode ruft tatsächlich eine private _fit()Funktion auf, die dann eine private _tsne()Funktion aufruft . Diese _tsne()Funktion verfügt über eine lokale Variable, errordie am Ende der Anpassung ausgedruckt wird. Es scheint, als könnten Sie ziemlich einfach eine oder zwei Zeilen Quellcode ändern, um diesen Wert zurückzugeben fit_transform().

Trey
quelle
Im Wesentlichen könnte ich self.error = error am Ende von _tsne () setzen, um es anschließend aus der TSNE-Instanz abzurufen. Ja, aber das würde bedeuten, den Code von sklearn.manifold zu ändern, und ich habe mich gefragt, ob die Entwickler über andere Möglichkeiten nachgedacht haben, um die Informationen zu erhalten, oder ob sie dies nicht getan haben (dh: Wird 'Fehler' von ihnen als nutzlos angesehen?). Wenn ich diesen Code ändern würde, müssten alle Benutzer, die meinen Code ausführen, denselben Hack auf ihren sklearn-Installationen haben. Schlagen Sie das vor oder habe ich es falsch verstanden?
Joker
Ja, das habe ich als mögliche Lösung vorgeschlagen. Da scikit-learn Open Source ist, können Sie Ihre Lösung auch als Pull-Anfrage einreichen und prüfen, ob die Autoren dies in zukünftigen Versionen berücksichtigen würden. Ich kann nicht darüber sprechen, warum sie verschiedene Dinge aufgenommen haben oder nicht.
Trey
2
Vielen Dank. Wenn jemand anderes daran interessiert ist, github.com/scikit-learn/scikit-learn/pull/3422 .
Joker