pavlin-policar / openTSNE

Extensible, parallel implementations of t-SNE
https://opentsne.rtfd.io
BSD 3-Clause "New" or "Revised" License
1.48k stars 165 forks source link

Store the last update between optimize() calls #229

Closed dkobak closed 1 year ago

dkobak commented 1 year ago

Fix #228 and add a corresponding test.

dkobak commented 1 year ago

I don't understand why the pickling test fails here.

pavlin-policar commented 1 year ago

The tests likely fail because the pickling/unpickling process is quite brittle. I'll take a look. Thanks for tracking this down. This is definitely something we want to implement.

dkobak commented 1 year ago

When the test fails, it happens in pickle.dumps(embedding), and the error is triggered in __reduce__():

    957         new_state = state[2] + (
--> 958             self.optimizer,
    959             self.affinities,
    960             self.gradient_descent_params,

AttributeError: 'TSNEEmbedding' object has no attribute 'optimizer'

What is weird, is that embedding.optimizer actually does exist, and moreover, calling embedding.__reduce__() also works fine, but calling pickle.dumps(embedding) triggers the above error...

dkobak commented 1 year ago

I FOUND THE BUG!!! Only took me two weeks :-) The update array needed to be converted from TSNEEmbedding to np.array. All checks pass now.

pavlin-policar commented 1 year ago

That's wonderful news! That must have been a pain to track down. This looks good to me, and, again, thanks for finding and fixing this bug :)