Added RandomPointSelection module

This commit is contained in:
Kim SangYeon
2019-01-02 18:37:56 +09:00
parent 5941468a62
commit 39b399edce
4 changed files with 47 additions and 16 deletions
+1
View File
@@ -4,6 +4,7 @@ set(SOURCES
dbscan.hpp
dbscan_impl.hpp
random_point_selection.hpp
ordered_point_selection.hpp
)
# Add directory name to sources.
+5 -4
View File
@@ -192,13 +192,14 @@ void DBSCAN<RangeSearchType, PointSelectionPolicy>::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
+19 -4
View File
@@ -15,7 +15,7 @@
#include <mlpack/core/tree/binary_space_tree.hpp>
#include <mlpack/core/tree/rectangle_tree.hpp>
#include <mlpack/core/tree/cover_tree.hpp>
#include <mlpack/methods/dbscan/random_point_selection.hpp>
#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<typename RangeSearchType>
@@ -86,13 +88,26 @@ void RunDBSCAN(RangeSearchType rs = RangeSearchType())
// Load dataset.
arma::mat dataset = std::move(CLI::GetParam<arma::mat>("input"));
const double epsilon = CLI::GetParam<double>("epsilon");
const size_t minSize = (size_t) CLI::GetParam<int>("min_size");
DBSCAN<RangeSearchType> d(epsilon, minSize, !CLI::HasParam("single_mode"),
rs);
// Check if random selection is used.
if (!CLI::HasParam("random_selection"))
{
DBSCAN<RangeSearchType> d(epsilon, minSize, !CLI::HasParam("single_mode"),
rs);
}
else
{
DBSCAN<RangeSearchType, RandomPointSelection> d(epsilon, minSize,
!CLI::HasParam("single_mode"), rs);
}
DBSCAN<RangeSearchType, RandomPointSelection> d(epsilon, minSize,
!CLI::HasParam("single_mode"), rs);
// If possible, avoid the overhead of calculating centroids.
arma::Row<size_t> assignments;
if (CLI::HasParam("centroids"))
@@ -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<typename MatType>
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