From 39b399edceb8bf1afbcda5edcccae3a4e60327c0 Mon Sep 17 00:00:00 2001 From: Kim SangYeon Date: Wed, 2 Jan 2019 18:37:56 +0900 Subject: [PATCH] Added RandomPointSelection module --- src/mlpack/methods/dbscan/CMakeLists.txt | 1 + src/mlpack/methods/dbscan/dbscan_impl.hpp | 9 +++--- src/mlpack/methods/dbscan/dbscan_main.cpp | 23 +++++++++++--- .../methods/dbscan/random_point_selection.hpp | 30 ++++++++++++++----- 4 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/mlpack/methods/dbscan/CMakeLists.txt b/src/mlpack/methods/dbscan/CMakeLists.txt index 70939c9d05..4c5f07ec8f 100644 --- a/src/mlpack/methods/dbscan/CMakeLists.txt +++ b/src/mlpack/methods/dbscan/CMakeLists.txt @@ -4,6 +4,7 @@ set(SOURCES dbscan.hpp dbscan_impl.hpp random_point_selection.hpp + ordered_point_selection.hpp ) # Add directory name to sources. diff --git a/src/mlpack/methods/dbscan/dbscan_impl.hpp b/src/mlpack/methods/dbscan/dbscan_impl.hpp index a27784af13..4e9a5073dc 100644 --- a/src/mlpack/methods/dbscan/dbscan_impl.hpp +++ b/src/mlpack/methods/dbscan/dbscan_impl.hpp @@ -192,13 +192,14 @@ void DBSCAN::BatchCluster( // Now loop over all points. for (size_t i = 0; i < data.n_cols; ++i) { - // Union to all neighbors. - for (size_t j = 0; j < neighbors[i].size(); ++j) - uf.Union(i, neighbors[i][j]); + // Get the next index. + const size_t index = pointSelector.Select(i, data); + for (size_t j = 0; j < neighbors[index].size(); ++j) + uf.Union(index, neighbors[index][j]); } } } // namespace dbscan } // namespace mlpack -#endif +#endif \ No newline at end of file diff --git a/src/mlpack/methods/dbscan/dbscan_main.cpp b/src/mlpack/methods/dbscan/dbscan_main.cpp index c4afc3c85f..81e43a86dc 100644 --- a/src/mlpack/methods/dbscan/dbscan_main.cpp +++ b/src/mlpack/methods/dbscan/dbscan_main.cpp @@ -15,7 +15,7 @@ #include #include #include - +#include #include "dbscan.hpp" using namespace mlpack; @@ -76,6 +76,8 @@ PARAM_FLAG("single_mode", "If set, single-tree range search (not dual-tree) " "will be used.", "S"); PARAM_FLAG("naive", "If set, brute-force range search (not tree-based) " "will be used.", "N"); +PARAM_FLAG("random_selection", "If set, random point selection (not ordered) " + "will be used.", "R"); // Actually run the clustering, and process the output. template @@ -86,13 +88,26 @@ void RunDBSCAN(RangeSearchType rs = RangeSearchType()) // Load dataset. arma::mat dataset = std::move(CLI::GetParam("input")); - + const double epsilon = CLI::GetParam("epsilon"); const size_t minSize = (size_t) CLI::GetParam("min_size"); - DBSCAN d(epsilon, minSize, !CLI::HasParam("single_mode"), - rs); + + // Check if random selection is used. + if (!CLI::HasParam("random_selection")) + { + DBSCAN d(epsilon, minSize, !CLI::HasParam("single_mode"), + rs); + } + else + { + DBSCAN d(epsilon, minSize, + !CLI::HasParam("single_mode"), rs); + } + DBSCAN d(epsilon, minSize, + !CLI::HasParam("single_mode"), rs); + // If possible, avoid the overhead of calculating centroids. arma::Row assignments; if (CLI::HasParam("centroids")) diff --git a/src/mlpack/methods/dbscan/random_point_selection.hpp b/src/mlpack/methods/dbscan/random_point_selection.hpp index a555830769..1c9ee61605 100644 --- a/src/mlpack/methods/dbscan/random_point_selection.hpp +++ b/src/mlpack/methods/dbscan/random_point_selection.hpp @@ -27,16 +27,24 @@ class RandomPointSelection /** * Select the next point to use, randomly. * - * @param unvisited Bitset indicating which points are unvisited. - * @param data Unused data. + * @param point Unused data. + * @param data Dataset to cluster. */ template - static size_t Select(const boost::dynamic_bitset<>& unvisited, - const MatType& /* data */) + size_t Select(const size_t /* point */, + const MatType& data /* data */) { + // Initialize the length of the unvisited bitset + size_t size = data.n_cols; // Get the size of points. + if (unvisited.size() != size) + { + unvisited.resize(size); // Resize & Set bitset to one + unvisited.set(); + } + const size_t max = unvisited.count(); const size_t index = math::RandInt(max); - + // Select the index'th unvisited point. size_t found = 0; for (size_t i = 0; i < unvisited.size(); ++i) @@ -45,14 +53,20 @@ class RandomPointSelection ++found; if (found > index) + { + unvisited[i].flip(); // Set unvisited point to visited point return i; + } } - return 0; // Not sure if it is possible to get here. } -}; + private: + // Bitmask for unvisited points, If true, mean unvisited. + boost::dynamic_bitset<> unvisited; +}; + } // namespace dbscan } // namespace mlpack -#endif +#endif \ No newline at end of file