-
Notifications
You must be signed in to change notification settings - Fork 525
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[REVIEW] Deterministic UMAP with floating point rounding. #3848
[REVIEW] Deterministic UMAP with floating point rounding. #3848
Conversation
Related:
I will look into them once issue in |
@trivialfis, I compiled and executed both of your approaches against the current approach to reproducibility. So far, it does look like this approach is faster and I've verified that it appears to be reproducible. It would still be nice for completeness to do some profiling and isolate where the bottlenecks exist in the warp-reduction approach but this approach does have the benefit of requiring less changes to the code. Here's some preliminary results from a very informal benchmark on a V100 (using defaults). Notice your truncation approach is right about the same timing as the non-reproducible approach of the current UMAP implementation >>> def do_it():
... import time
... s = time.time()
... m = UMAP().fit(X)
... print("TooK %ss" % (time.time() - s))
Current UMAP (non-reproducible)
>>> X, y = make_blobs(100000, 256)
>>> do_it()
TooK 0.7839245796203613s
>>> do_it()
TooK 0.790290355682373s
Current UMAP (reproducible)
>>> X, y = make_blobs(100000, 256)
>>> do_it()
TooK 1.065580129623413s
>>> do_it()
Warp-level reductions:
>>> X, y = make_blobs(100000, 128)
>>> do_it()
TooK 1.012941837310791s
>>> do_it()
TooK 0.9855947494506836s
>>> X, y = make_blobs(100000, 256)
>>> do_it()
TooK 1.2152369022369385s
Truncation:
>>> X, y = make_blobs(100000, 256)
>>> do_it()
TooK 1.2795426845550537s
>>> do_it()
TooK 0.7870500087738037s
>>> do_it()
TooK 0.7900457382202148s
>>> do_it()
TooK 0.7811644077301025s >>> def do_it():
... import time
... s = time.time()
... m = UMAP(random_state=42).fit(X)
... print("TooK %ss" % (time.time() - s))
... print(m.embedding_)
...
>>> do_it()
TooK 0.9100887775421143s
[[-8.367687 -3.012333 ]
[-9.082779 -4.595929 ]
[-0.6999092 1.0279074]
...
[ 8.140747 3.4932442]
[ 8.890211 3.0183897]
[ 8.434332 2.4182014]]
>>> do_it()
TooK 0.7889752388000488s
[[-8.367687 -3.012333 ]
[-9.082779 -4.595929 ]
[-0.6999092 1.0279074]
...
[ 8.140747 3.4932442]
[ 8.890211 3.0183897]
[ 8.434332 2.4182014]]
>>> do_it()
TooK 0.7994036674499512s
[[-8.367687 -3.012333 ]
[-9.082779 -4.595929 ]
[-0.6999092 1.0279074]
...
[ 8.140747 3.4932442]
[ 8.890211 3.0183897]
[ 8.434332 2.4182014]]
>>> do_it()
TooK 0.8132762908935547s
[[-8.367687 -3.012333 ]
[-9.082779 -4.595929 ]
[-0.6999092 1.0279074]
...
[ 8.140747 3.4932442]
[ 8.890211 3.0183897]
[ 8.434332 2.4182014]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just providing some initial feedback. I'll go through another round when you're ready. So far I'm excited by the timings I'm seeing for both approaches.
It seems the mnmg test is flaky. Update: NVM, fixed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Finished last review round. Have you gotten a chance to run these changes on larger datasets such as fashion mnist or google news embeddings? It would help just to test against some datasets just to verify there aren't any violated assumptions in the rounding. Otherwise, these changes are looking great.
b850a33
to
bc26e07
Compare
Codecov Report
@@ Coverage Diff @@
## branch-0.20 #3848 +/- ##
===============================================
- Coverage 85.96% 77.35% -8.61%
===============================================
Files 225 214 -11
Lines 16986 16552 -434
===============================================
- Hits 14602 12804 -1798
- Misses 2384 3748 +1364
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
This is a breaking change as the batch size parameter is removed. * Add procedure for rounding the gradient updates. * Add buffer for gradient updates. * Add an internal parameter `deterministic`, which should be set to `true` when `random_state` is set. * Cleanup tests.
bc26e07
to
3945822
Compare
Rebased onto branch-21.06. Not sure why is conda failing. |
rerun tests |
rerun tests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. The evaluation on the datasets I've seen look great.
@gpucibot merge |
@cjnolet Thanks for all the advice! Learned a lot during this. |
Closes #4725 #3848 removes the usage of `optim_batch_size` in code. This PR removes the parameter from the docstring and in `UMAPParams`. Authors: - Thomas J. Fan (https://github.com/thomasjpfan) Approvers: - Dante Gama Dessavre (https://github.com/dantegd) URL: #4732
Use floating rounding to make UMAP optimization deterministic. This is a breaking change as the batch size parameter is removed. * Add procedure for rounding the gradient updates. * Add buffer for gradient updates. * Add an internal parameter `deterministic`, which should be set to `true` when `random_state` is set. The test file is removed due to rapidsai#3849 . Authors: - Jiaming Yuan (https://github.com/trivialfis) Approvers: - Corey J. Nolet (https://github.com/cjnolet) URL: rapidsai#3848
) Closes rapidsai#4725 rapidsai#3848 removes the usage of `optim_batch_size` in code. This PR removes the parameter from the docstring and in `UMAPParams`. Authors: - Thomas J. Fan (https://github.com/thomasjpfan) Approvers: - Dante Gama Dessavre (https://github.com/dantegd) URL: rapidsai#4732
Use floating rounding to make UMAP optimization deterministic. This is a breaking change as the batch size parameter is removed.
deterministic
, which should be set totrue
whenrandom_state
is set.The test file is removed due to #3849 .