Thực hiện Python t-SNE: Phân kỳ Kullback-Leibler


11

t-SNE, như trong [1], hoạt động bằng cách giảm dần phân kỳ Kullback-Leibler (KL), cho đến khi một điều kiện nhất định được đáp ứng. Những người tạo ra t-SNE đề nghị sử dụng phân kỳ KL làm tiêu chí hiệu suất cho các hình ảnh trực quan:

bạn có thể so sánh các phân kỳ Kullback-Leibler mà t-SNE báo cáo. Hoàn toàn ổn khi chạy t-SNE mười lần và chọn giải pháp có độ phân kỳ KL thấp nhất [2]

Tôi đã thử hai triển khai của t-SNE:

  • trăn : sklearn.manifold.TSNE ().
  • R : tsne, từ thư viện (tsne).

Cả hai triển khai này, khi độ dài được đặt, in lỗi (phân kỳ Kullback-Leibler) cho mỗi lần lặp. Tuy nhiên, họ không cho phép người dùng nhận thông tin này, điều này có vẻ hơi lạ đối với tôi.

Ví dụ: mã:

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)

sản xuất:

[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

Bây giờ, theo tôi hiểu, 0,270186 phải là phân kỳ KL. Tuy nhiên tôi không thể có được thông tin này, từ mô hình cũng như từ t (đó là một numpy.ndarray đơn giản).

Để giải quyết vấn đề này, tôi có thể: i) Tự tính toán phân kỳ KL, ii) Làm điều gì đó khó chịu trong python để chụp và phân tích đầu ra của hàm TSNE () [3]. Tuy nhiên: i) sẽ khá ngu ngốc khi tính lại phân kỳ KL, khi TSNE () đã tính toán nó, ii) sẽ hơi bất thường về mặt mã.

Bạn có đề nghị nào khác không? Có một cách tiêu chuẩn để có được thông tin này bằng thư viện này?

Tôi đã đề cập rằng tôi đã thử thư viện tsne của R , nhưng tôi thích các câu trả lời tập trung vào việc thực hiện sklearn python .


Người giới thiệu

[1] http://nbviewer.ipython.org/urls/gist.githubusercontent.com/AlexanderFabisch/1a0c648de22eff4a2a3e/raw/59d5bc5ed8f8bfd9ff1f7faa749bbbbb

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

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

Câu trả lời:


4

Nguồn TSNE trong scikit-learn là bằng Python thuần túy. fit_transform()Phương thức Fit thực sự đang gọi một _fit()hàm riêng mà sau đó gọi một _tsne()hàm riêng . _tsne()Hàm đó có một biến cục bộ errorđược in ra ở phần cuối của sự phù hợp. Có vẻ như bạn có thể dễ dàng thay đổi một hoặc hai dòng mã nguồn để trả lại giá trị đó fit_transform().


Về cơ bản, những gì tôi có thể làm là đặt self.error = error ở cuối _tsne (), để lấy nó từ phiên bản TSNE sau đó. Có, nhưng điều đó có nghĩa là thay đổi mã sklearn.manifold và tôi tự hỏi liệu các nhà phát triển có nghĩ ra một số cách khác để lấy thông tin hay không, tại sao họ không (ví dụ: "lỗi" có bị họ coi là vô dụng không?). Hơn nữa, nếu tôi thay đổi mã đó, tôi sẽ cần tất cả những người chạy mã của tôi có cùng một bản hack trên các bản cài đặt sklearn của họ. Đó là những gì bạn đề nghị, hoặc tôi đã hiểu sai?
đùa

Vâng, đó là những gì tôi đề nghị như là một giải pháp có thể. Vì scikit-learn là nguồn mở, bạn cũng có thể gửi giải pháp của mình dưới dạng yêu cầu kéo và xem liệu các tác giả có đưa nó vào các bản phát hành trong tương lai không. Tôi không thể nói lý do tại sao họ đã làm hoặc không bao gồm nhiều thứ khác nhau.
Trey

2
Cảm ơn. Nếu bất cứ ai khác quan tâm đến điều này, github.com/scikit-learn/scikit-learn/pull/3422 .
đùa
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.