Adapt LSHSearch to allow MatType template parameter.
This commit is contained in:
@@ -59,8 +59,12 @@ namespace neighbor {
|
||||
* queries.
|
||||
*
|
||||
* @tparam SortPolicy The sort policy for distances; see NearestNeighborSort.
|
||||
* @tparam MatType Type of matrix to use to store the data.
|
||||
*/
|
||||
template<typename SortPolicy = NearestNeighborSort>
|
||||
template<
|
||||
typename SortPolicy = NearestNeighborSort,
|
||||
typename MatType = arma::mat
|
||||
>
|
||||
class LSHSearch
|
||||
{
|
||||
public:
|
||||
@@ -86,7 +90,7 @@ class LSHSearch
|
||||
* value of 0 indicates that there is no limit (so the second hash table
|
||||
* can be arbitrarily large---be careful!).
|
||||
*/
|
||||
LSHSearch(arma::mat referenceSet,
|
||||
LSHSearch(MatType referenceSet,
|
||||
const arma::cube& projections,
|
||||
const double hashWidth = 0.0,
|
||||
const size_t secondHashSize = 99901,
|
||||
@@ -114,7 +118,7 @@ class LSHSearch
|
||||
* value of 0 indicates that there is no limit (so the second hash table
|
||||
* can be arbitrarily large---be careful!).
|
||||
*/
|
||||
LSHSearch(arma::mat referenceSet,
|
||||
LSHSearch(MatType referenceSet,
|
||||
const size_t numProj,
|
||||
const size_t numTables,
|
||||
const double hashWidth = 0.0,
|
||||
@@ -180,7 +184,7 @@ class LSHSearch
|
||||
* we set numProj = a, numTables = c. b is the reference set
|
||||
* dimensionality.
|
||||
*/
|
||||
void Train(arma::mat referenceSet,
|
||||
void Train(MatType referenceSet,
|
||||
const size_t numProj,
|
||||
const size_t numTables,
|
||||
const double hashWidth = 0.0,
|
||||
@@ -209,7 +213,7 @@ class LSHSearch
|
||||
* @param T The number of additional probing bins to examine with multiprobe
|
||||
* LSH. If T = 0, classic single-probe LSH is run (default).
|
||||
*/
|
||||
void Search(const arma::mat& querySet,
|
||||
void Search(const MatType& querySet,
|
||||
const size_t k,
|
||||
arma::Mat<size_t>& resultingNeighbors,
|
||||
arma::mat& distances,
|
||||
@@ -353,7 +357,7 @@ class LSHSearch
|
||||
void BaseCase(const size_t queryIndex,
|
||||
const arma::uvec& referenceIndices,
|
||||
const size_t k,
|
||||
const arma::mat& querySet,
|
||||
const MatType& querySet,
|
||||
arma::Mat<size_t>& neighbors,
|
||||
arma::mat& distances) const;
|
||||
|
||||
@@ -415,7 +419,7 @@ class LSHSearch
|
||||
bool PerturbationValid(const std::vector<bool>& A) const;
|
||||
|
||||
//! Reference dataset.
|
||||
arma::mat referenceSet;
|
||||
MatType referenceSet;
|
||||
|
||||
//! The number of projections.
|
||||
size_t numProj;
|
||||
|
||||
@@ -19,9 +19,9 @@ namespace mlpack {
|
||||
namespace neighbor {
|
||||
|
||||
// Construct the object with random tables
|
||||
template<typename SortPolicy>
|
||||
LSHSearch<SortPolicy>::
|
||||
LSHSearch(arma::mat referenceSet,
|
||||
template<typename SortPolicy, typename MatType>
|
||||
LSHSearch<SortPolicy, MatType>::
|
||||
LSHSearch(MatType referenceSet,
|
||||
const size_t numProj,
|
||||
const size_t numTables,
|
||||
const double hashWidthIn,
|
||||
@@ -35,14 +35,14 @@ LSHSearch(arma::mat referenceSet,
|
||||
distanceEvaluations(0)
|
||||
{
|
||||
// Pass work to training function.
|
||||
Train(referenceSet, numProj, numTables, hashWidthIn, secondHashSize,
|
||||
bucketSize);
|
||||
Train(std::move(referenceSet), numProj, numTables, hashWidthIn,
|
||||
secondHashSize, bucketSize);
|
||||
}
|
||||
|
||||
// Construct the object with given tables
|
||||
template<typename SortPolicy>
|
||||
LSHSearch<SortPolicy>::
|
||||
LSHSearch(arma::mat referenceSet,
|
||||
template<typename SortPolicy, typename MatType>
|
||||
LSHSearch<SortPolicy, MatType>::
|
||||
LSHSearch(MatType referenceSet,
|
||||
const arma::cube& projections,
|
||||
const double hashWidthIn,
|
||||
const size_t secondHashSize,
|
||||
@@ -60,8 +60,8 @@ LSHSearch(arma::mat referenceSet,
|
||||
}
|
||||
|
||||
// Empty constructor.
|
||||
template<typename SortPolicy>
|
||||
LSHSearch<SortPolicy>::LSHSearch() :
|
||||
template<typename SortPolicy, typename MatType>
|
||||
LSHSearch<SortPolicy, MatType>::LSHSearch() :
|
||||
numProj(0),
|
||||
numTables(0),
|
||||
hashWidth(0),
|
||||
@@ -72,8 +72,8 @@ LSHSearch<SortPolicy>::LSHSearch() :
|
||||
}
|
||||
|
||||
// Copy constructor.
|
||||
template<typename SortPolicy>
|
||||
LSHSearch<SortPolicy>::LSHSearch(const LSHSearch& other) :
|
||||
template<typename SortPolicy, typename MatType>
|
||||
LSHSearch<SortPolicy, MatType>::LSHSearch(const LSHSearch& other) :
|
||||
referenceSet(other.referenceSet), // Copy the other set.
|
||||
numProj(other.numProj),
|
||||
numTables(other.numTables),
|
||||
@@ -92,8 +92,8 @@ LSHSearch<SortPolicy>::LSHSearch(const LSHSearch& other) :
|
||||
}
|
||||
|
||||
// Move constructor.
|
||||
template<typename SortPolicy>
|
||||
LSHSearch<SortPolicy>::LSHSearch(LSHSearch&& other) :
|
||||
template<typename SortPolicy, typename MatType>
|
||||
LSHSearch<SortPolicy, MatType>::LSHSearch(LSHSearch&& other) :
|
||||
referenceSet(std::move(other.referenceSet)),
|
||||
numProj(other.numProj),
|
||||
numTables(other.numTables),
|
||||
@@ -118,8 +118,9 @@ LSHSearch<SortPolicy>::LSHSearch(LSHSearch&& other) :
|
||||
}
|
||||
|
||||
// Copy operator.
|
||||
template<typename SortPolicy>
|
||||
LSHSearch<SortPolicy>& LSHSearch<SortPolicy>::operator=(const LSHSearch& other)
|
||||
template<typename SortPolicy, typename MatType>
|
||||
LSHSearch<SortPolicy, MatType>& LSHSearch<SortPolicy, MatType>::operator=(
|
||||
const LSHSearch& other)
|
||||
{
|
||||
referenceSet = other.referenceSet;
|
||||
numProj = other.numProj;
|
||||
@@ -139,8 +140,9 @@ LSHSearch<SortPolicy>& LSHSearch<SortPolicy>::operator=(const LSHSearch& other)
|
||||
}
|
||||
|
||||
// Move operator.
|
||||
template<typename SortPolicy>
|
||||
LSHSearch<SortPolicy>& LSHSearch<SortPolicy>::operator=(LSHSearch&& other)
|
||||
template<typename SortPolicy, typename MatType>
|
||||
LSHSearch<SortPolicy, MatType>& LSHSearch<SortPolicy, MatType>::operator=(
|
||||
LSHSearch&& other)
|
||||
{
|
||||
referenceSet = std::move(other.referenceSet);
|
||||
numProj = other.numProj;
|
||||
@@ -168,14 +170,14 @@ LSHSearch<SortPolicy>& LSHSearch<SortPolicy>::operator=(LSHSearch&& other)
|
||||
}
|
||||
|
||||
// Train on a new reference set.
|
||||
template<typename SortPolicy>
|
||||
void LSHSearch<SortPolicy>::Train(arma::mat referenceSet,
|
||||
const size_t numProj,
|
||||
const size_t numTables,
|
||||
const double hashWidthIn,
|
||||
const size_t secondHashSize,
|
||||
const size_t bucketSize,
|
||||
const arma::cube &projection)
|
||||
template<typename SortPolicy, typename MatType>
|
||||
void LSHSearch<SortPolicy, MatType>::Train(MatType referenceSet,
|
||||
const size_t numProj,
|
||||
const size_t numTables,
|
||||
const double hashWidthIn,
|
||||
const size_t secondHashSize,
|
||||
const size_t bucketSize,
|
||||
const arma::cube& projection)
|
||||
{
|
||||
// Set new reference set.
|
||||
this->referenceSet = std::move(referenceSet);
|
||||
@@ -197,8 +199,8 @@ void LSHSearch<SortPolicy>::Train(arma::mat referenceSet,
|
||||
size_t p2 = (size_t) math::RandInt(this->referenceSet.n_cols);
|
||||
|
||||
hashWidth += std::sqrt(metric::EuclideanDistance::Evaluate(
|
||||
this->referenceSet.unsafe_col(p1),
|
||||
this->referenceSet.unsafe_col(p2)));
|
||||
this->referenceSet.col(p1),
|
||||
this->referenceSet.col(p2)));
|
||||
}
|
||||
|
||||
hashWidth /= numSamples;
|
||||
@@ -349,13 +351,14 @@ void LSHSearch<SortPolicy>::Train(arma::mat referenceSet,
|
||||
|
||||
// Base case where the query set is the reference set. (So, we can't return
|
||||
// ourselves as the nearest neighbor.)
|
||||
template<typename SortPolicy>
|
||||
template<typename SortPolicy, typename MatType>
|
||||
inline force_inline
|
||||
void LSHSearch<SortPolicy>::BaseCase(const size_t queryIndex,
|
||||
const arma::uvec& referenceIndices,
|
||||
const size_t k,
|
||||
arma::Mat<size_t>& neighbors,
|
||||
arma::mat& distances) const
|
||||
void LSHSearch<SortPolicy, MatType>::BaseCase(
|
||||
const size_t queryIndex,
|
||||
const arma::uvec& referenceIndices,
|
||||
const size_t k,
|
||||
arma::Mat<size_t>& neighbors,
|
||||
arma::mat& distances) const
|
||||
{
|
||||
// Let's build the list of candidate neighbors for the given query point.
|
||||
// It will be initialized with k candidates:
|
||||
@@ -373,8 +376,8 @@ void LSHSearch<SortPolicy>::BaseCase(const size_t queryIndex,
|
||||
continue;
|
||||
|
||||
const double distance = metric::EuclideanDistance::Evaluate(
|
||||
referenceSet.unsafe_col(queryIndex),
|
||||
referenceSet.unsafe_col(referenceIndex));
|
||||
referenceSet.col(queryIndex),
|
||||
referenceSet.col(referenceIndex));
|
||||
|
||||
Candidate c = std::make_pair(distance, referenceIndex);
|
||||
// If this distance is better than the worst candidate, let's insert it.
|
||||
@@ -394,14 +397,15 @@ void LSHSearch<SortPolicy>::BaseCase(const size_t queryIndex,
|
||||
}
|
||||
|
||||
// Base case for bichromatic search.
|
||||
template<typename SortPolicy>
|
||||
template<typename SortPolicy, typename MatType>
|
||||
inline force_inline
|
||||
void LSHSearch<SortPolicy>::BaseCase(const size_t queryIndex,
|
||||
const arma::uvec& referenceIndices,
|
||||
const size_t k,
|
||||
const arma::mat& querySet,
|
||||
arma::Mat<size_t>& neighbors,
|
||||
arma::mat& distances) const
|
||||
void LSHSearch<SortPolicy, MatType>::BaseCase(
|
||||
const size_t queryIndex,
|
||||
const arma::uvec& referenceIndices,
|
||||
const size_t k,
|
||||
const MatType& querySet,
|
||||
arma::Mat<size_t>& neighbors,
|
||||
arma::mat& distances) const
|
||||
{
|
||||
// Let's build the list of candidate neighbors for the given query point.
|
||||
// It will be initialized with k candidates:
|
||||
@@ -415,8 +419,8 @@ void LSHSearch<SortPolicy>::BaseCase(const size_t queryIndex,
|
||||
{
|
||||
const size_t referenceIndex = referenceIndices[j];
|
||||
const double distance = metric::EuclideanDistance::Evaluate(
|
||||
querySet.unsafe_col(queryIndex),
|
||||
referenceSet.unsafe_col(referenceIndex));
|
||||
querySet.col(queryIndex),
|
||||
referenceSet.col(referenceIndex));
|
||||
|
||||
Candidate c = std::make_pair(distance, referenceIndex);
|
||||
// If this distance is better than the worst candidate, let's insert it.
|
||||
@@ -435,9 +439,9 @@ void LSHSearch<SortPolicy>::BaseCase(const size_t queryIndex,
|
||||
}
|
||||
}
|
||||
|
||||
template<typename SortPolicy>
|
||||
template<typename SortPolicy, typename MatType>
|
||||
inline force_inline
|
||||
double LSHSearch<SortPolicy>::PerturbationScore(
|
||||
double LSHSearch<SortPolicy, MatType>::PerturbationScore(
|
||||
const std::vector<bool>& A,
|
||||
const arma::vec& scores) const
|
||||
{
|
||||
@@ -448,9 +452,10 @@ double LSHSearch<SortPolicy>::PerturbationScore(
|
||||
return score;
|
||||
}
|
||||
|
||||
template<typename SortPolicy>
|
||||
template<typename SortPolicy, typename MatType>
|
||||
inline force_inline
|
||||
bool LSHSearch<SortPolicy>::PerturbationShift(std::vector<bool>& A) const
|
||||
bool LSHSearch<SortPolicy, MatType>::PerturbationShift(
|
||||
std::vector<bool>& A) const
|
||||
{
|
||||
size_t maxPos = 0;
|
||||
for (size_t i = 0; i < A.size(); ++i)
|
||||
@@ -466,9 +471,10 @@ bool LSHSearch<SortPolicy>::PerturbationShift(std::vector<bool>& A) const
|
||||
return false; // invalid
|
||||
}
|
||||
|
||||
template<typename SortPolicy>
|
||||
template<typename SortPolicy, typename MatType>
|
||||
inline force_inline
|
||||
bool LSHSearch<SortPolicy>::PerturbationExpand(std::vector<bool>& A) const
|
||||
bool LSHSearch<SortPolicy, MatType>::PerturbationExpand(
|
||||
std::vector<bool>& A) const
|
||||
{
|
||||
// Find the last '1' in A.
|
||||
size_t maxPos = 0;
|
||||
@@ -484,9 +490,9 @@ bool LSHSearch<SortPolicy>::PerturbationExpand(std::vector<bool>& A) const
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename SortPolicy>
|
||||
template<typename SortPolicy, typename MatType>
|
||||
inline force_inline
|
||||
bool LSHSearch<SortPolicy>::PerturbationValid(
|
||||
bool LSHSearch<SortPolicy, MatType>::PerturbationValid(
|
||||
const std::vector<bool>& A) const
|
||||
{
|
||||
// Use check to mark dimensions we have seen before in A. If a dimension is
|
||||
@@ -514,8 +520,8 @@ bool LSHSearch<SortPolicy>::PerturbationValid(
|
||||
}
|
||||
|
||||
// Compute additional probing bins for a query
|
||||
template<typename SortPolicy>
|
||||
void LSHSearch<SortPolicy>::GetAdditionalProbingBins(
|
||||
template<typename SortPolicy, typename MatType>
|
||||
void LSHSearch<SortPolicy, MatType>::GetAdditionalProbingBins(
|
||||
const arma::vec& queryCode,
|
||||
const arma::vec& queryCodeNotFloored,
|
||||
const size_t T,
|
||||
@@ -696,9 +702,9 @@ void LSHSearch<SortPolicy>::GetAdditionalProbingBins(
|
||||
}
|
||||
}
|
||||
|
||||
template<typename SortPolicy>
|
||||
template<typename SortPolicy, typename MatType>
|
||||
template<typename VecType>
|
||||
void LSHSearch<SortPolicy>::ReturnIndicesFromTable(
|
||||
void LSHSearch<SortPolicy, MatType>::ReturnIndicesFromTable(
|
||||
const VecType& queryPoint,
|
||||
arma::uvec& referenceIndices,
|
||||
size_t numTablesToSearch,
|
||||
@@ -849,13 +855,14 @@ void LSHSearch<SortPolicy>::ReturnIndicesFromTable(
|
||||
}
|
||||
|
||||
// Search for nearest neighbors in a given query set.
|
||||
template<typename SortPolicy>
|
||||
void LSHSearch<SortPolicy>::Search(const arma::mat& querySet,
|
||||
const size_t k,
|
||||
arma::Mat<size_t>& resultingNeighbors,
|
||||
arma::mat& distances,
|
||||
const size_t numTablesToSearch,
|
||||
const size_t T)
|
||||
template<typename SortPolicy, typename MatType>
|
||||
void LSHSearch<SortPolicy, MatType>::Search(
|
||||
const MatType& querySet,
|
||||
const size_t k,
|
||||
arma::Mat<size_t>& resultingNeighbors,
|
||||
arma::mat& distances,
|
||||
const size_t numTablesToSearch,
|
||||
const size_t T)
|
||||
{
|
||||
// Ensure the dimensionality of the query set is correct.
|
||||
if (querySet.n_rows != referenceSet.n_rows)
|
||||
@@ -938,8 +945,8 @@ void LSHSearch<SortPolicy>::Search(const arma::mat& querySet,
|
||||
}
|
||||
|
||||
// Search for approximate neighbors of the reference set.
|
||||
template<typename SortPolicy>
|
||||
void LSHSearch<SortPolicy>::
|
||||
template<typename SortPolicy, typename MatType>
|
||||
void LSHSearch<SortPolicy, MatType>::
|
||||
Search(const size_t k,
|
||||
arma::Mat<size_t>& resultingNeighbors,
|
||||
arma::mat& distances,
|
||||
@@ -1003,8 +1010,8 @@ Search(const size_t k,
|
||||
std::endl;
|
||||
}
|
||||
|
||||
template<typename SortPolicy>
|
||||
double LSHSearch<SortPolicy>::ComputeRecall(
|
||||
template<typename SortPolicy, typename MatType>
|
||||
double LSHSearch<SortPolicy, MatType>::ComputeRecall(
|
||||
const arma::Mat<size_t>& foundNeighbors,
|
||||
const arma::Mat<size_t>& realNeighbors)
|
||||
{
|
||||
@@ -1030,10 +1037,10 @@ double LSHSearch<SortPolicy>::ComputeRecall(
|
||||
return ((double) found) / realNeighbors.n_elem;
|
||||
}
|
||||
|
||||
template<typename SortPolicy>
|
||||
template<typename SortPolicy, typename MatType>
|
||||
template<typename Archive>
|
||||
void LSHSearch<SortPolicy>::serialize(Archive& ar,
|
||||
const unsigned int version)
|
||||
void LSHSearch<SortPolicy, MatType>::serialize(Archive& ar,
|
||||
const unsigned int version)
|
||||
{
|
||||
ar & BOOST_SERIALIZATION_NVP(referenceSet);
|
||||
ar & BOOST_SERIALIZATION_NVP(numProj);
|
||||
|
||||
Reference in New Issue
Block a user