From ba57edcce2ba9b011c73c4f2bd21584e33b61bed Mon Sep 17 00:00:00 2001 From: Zach Bjornson Date: Sat, 25 Jul 2020 02:28:48 +0000 Subject: [PATCH] Obey initialize_embeddings parameter in B-H tSNE Fixes #2549 --- CHANGELOG.md | 1 + cpp/include/cuml/manifold/tsne.h | 4 ++-- cpp/src/tsne/barnes_hut.cuh | 14 ++++++++++---- cpp/src/tsne/exact_tsne.cuh | 6 +++--- cpp/src/tsne/tsne.cu | 8 +++++--- python/cuml/manifold/t_sne.pyx | 2 +- 6 files changed, 22 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da51e00c17..a272ad1179 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ## Bug Fixes - PR #2983: Fix seeding of KISS99 RNG +- PR #3011: Fix unused initialize_embeddings parameter in Barnes-Hut t-SNE # cuML 0.16.0 (Date TBD) diff --git a/cpp/include/cuml/manifold/tsne.h b/cpp/include/cuml/manifold/tsne.h index b6ffc05ba3..e94d1dd4d7 100644 --- a/cpp/include/cuml/manifold/tsne.h +++ b/cpp/include/cuml/manifold/tsne.h @@ -59,7 +59,7 @@ namespace ML { * or >= 0 for reproducible outputs. * @param[in] verbosity verbosity level for logging messages during * execution - * @param[in] intialize_embeddings Whether to overwrite the current Y vector + * @param[in] initialize_embeddings Whether to overwrite the current Y vector * with random noise. * @param[in] barnes_hut Whether to use the fast Barnes Hut or use the * slower exact version. @@ -85,6 +85,6 @@ void TSNE_fit(const raft::handle_t &handle, const float *X, float *Y, const float pre_momentum = 0.5, const float post_momentum = 0.8, const long long random_state = -1, int verbosity = CUML_LEVEL_INFO, - const bool intialize_embeddings = true, bool barnes_hut = true); + const bool initialize_embeddings = true, bool barnes_hut = true); } // namespace ML diff --git a/cpp/src/tsne/barnes_hut.cuh b/cpp/src/tsne/barnes_hut.cuh index f9ad78c687..145f33a7e9 100644 --- a/cpp/src/tsne/barnes_hut.cuh +++ b/cpp/src/tsne/barnes_hut.cuh @@ -46,6 +46,7 @@ namespace TSNE { * @param[in] pre_momentum: The momentum used during the exaggeration phase. * @param[in] post_momentum: The momentum used after the exaggeration phase. * @param[in] random_state: Set this to -1 for pure random intializations or >= 0 for reproducible outputs. + * @param[in] initialize_embeddings: Whether to overwrite the current Y vector with random noise. */ void Barnes_Hut(float *VAL, const int *COL, const int *ROW, const int NNZ, const raft::handle_t &handle, float *Y, const int n, @@ -56,7 +57,8 @@ void Barnes_Hut(float *VAL, const int *COL, const int *ROW, const int NNZ, const float post_learning_rate = 500.0f, const int max_iter = 1000, const float min_grad_norm = 1e-7, const float pre_momentum = 0.5, const float post_momentum = 0.8, - const long long random_state = -1) { + const long long random_state = -1, + const bool initialize_embeddings = true) { auto d_alloc = handle.get_device_allocator(); cudaStream_t stream = handle.get_stream(); @@ -131,9 +133,13 @@ void Barnes_Hut(float *VAL, const int *COL, const int *ROW, const int NNZ, cudaMemsetAsync(old_forces.data(), 0, sizeof(float) * n * 2, stream)); MLCommon::device_buffer YY(d_alloc, stream, (nnodes + 1) * 2); - // TODO bug #2549: this should be conditional on bool initialize_embeddings. - random_vector(YY.data(), -0.0001f, 0.0001f, (nnodes + 1) * 2, stream, - random_state); + if (initialize_embeddings) { + random_vector(YY.data(), -0.0001f, 0.0001f, (nnodes + 1) * 2, stream, + random_state); + } else { + raft::copy(YY.data(), Y, n, stream); + raft::copy(YY.data() + nnodes + 1, Y + n, n, stream); + } // Set cache levels for faster algorithm execution //--------------------------------------------------- diff --git a/cpp/src/tsne/exact_tsne.cuh b/cpp/src/tsne/exact_tsne.cuh index c2bc00757b..ed0f7b80f3 100644 --- a/cpp/src/tsne/exact_tsne.cuh +++ b/cpp/src/tsne/exact_tsne.cuh @@ -44,7 +44,7 @@ namespace TSNE { * @param[in] pre_momentum: The momentum used during the exaggeration phase. * @param[in] post_momentum: The momentum used after the exaggeration phase. * @param[in] random_state: Set this to -1 for pure random intializations or >= 0 for reproducible outputs. - * @param[in] intialize_embeddings: Whether to overwrite the current Y vector with random noise. + * @param[in] initialize_embeddings: Whether to overwrite the current Y vector with random noise. */ void Exact_TSNE(float *VAL, const int *COL, const int *ROW, const int NNZ, const raft::handle_t &handle, float *Y, const int n, @@ -55,11 +55,11 @@ void Exact_TSNE(float *VAL, const int *COL, const int *ROW, const int NNZ, const int max_iter = 1000, const float min_grad_norm = 1e-7, const float pre_momentum = 0.5, const float post_momentum = 0.8, const long long random_state = -1, - const bool intialize_embeddings = true) { + const bool initialize_embeddings = true) { auto d_alloc = handle.get_device_allocator(); cudaStream_t stream = handle.get_stream(); - if (intialize_embeddings) + if (initialize_embeddings) random_vector(Y, -0.0001f, 0.0001f, n * dim, stream, random_state); // Allocate space diff --git a/cpp/src/tsne/tsne.cu b/cpp/src/tsne/tsne.cu index cc971cbd1b..648bcb1ea9 100644 --- a/cpp/src/tsne/tsne.cu +++ b/cpp/src/tsne/tsne.cu @@ -36,7 +36,8 @@ void TSNE_fit(const raft::handle_t &handle, const float *X, float *Y, const float post_learning_rate, const int max_iter, const float min_grad_norm, const float pre_momentum, const float post_momentum, const long long random_state, - int verbosity, const bool intialize_embeddings, bool barnes_hut) { + int verbosity, const bool initialize_embeddings, + bool barnes_hut) { ASSERT(n > 0 && p > 0 && dim > 0 && n_neighbors > 0 && X != NULL && Y != NULL, "Wrong input args"); ML::Logger::get().setLevel(verbosity); @@ -118,12 +119,13 @@ void TSNE_fit(const raft::handle_t &handle, const float *X, float *Y, TSNE::Barnes_Hut(VAL, COL, ROW, NNZ, handle, Y, n, theta, epssq, early_exaggeration, exaggeration_iter, min_gain, pre_learning_rate, post_learning_rate, max_iter, - min_grad_norm, pre_momentum, post_momentum, random_state); + min_grad_norm, pre_momentum, post_momentum, random_state, + initialize_embeddings); } else { TSNE::Exact_TSNE(VAL, COL, ROW, NNZ, handle, Y, n, dim, early_exaggeration, exaggeration_iter, min_gain, pre_learning_rate, post_learning_rate, max_iter, min_grad_norm, pre_momentum, - post_momentum, random_state, intialize_embeddings); + post_momentum, random_state, initialize_embeddings); } } diff --git a/python/cuml/manifold/t_sne.pyx b/python/cuml/manifold/t_sne.pyx index 12cd8a51f4..15e91118c5 100644 --- a/python/cuml/manifold/t_sne.pyx +++ b/python/cuml/manifold/t_sne.pyx @@ -67,7 +67,7 @@ cdef extern from "cuml/manifold/tsne.h" namespace "ML" nogil: const float post_momentum, const long long random_state, int verbosity, - const bool intialize_embeddings, + const bool initialize_embeddings, bool barnes_hut) except +