12 #ifndef MLPACK_METHODS_NEIGHBOR_SEARCH_LSH_SEARCH_IMPL_HPP 13 #define MLPACK_METHODS_NEIGHBOR_SEARCH_LSH_SEARCH_IMPL_HPP 22 template<
typename SortPolicy,
typename MatType>
26 const size_t numTables,
27 const double hashWidthIn,
28 const size_t secondHashSize,
29 const size_t bucketSize) :
32 hashWidth(hashWidthIn),
33 secondHashSize(secondHashSize),
34 bucketSize(bucketSize),
35 distanceEvaluations(0)
38 Train(std::move(referenceSet), numProj, numTables, hashWidthIn,
39 secondHashSize, bucketSize);
43 template<
typename SortPolicy,
typename MatType>
46 const arma::cube& projections,
47 const double hashWidthIn,
48 const size_t secondHashSize,
49 const size_t bucketSize) :
50 numProj(projections.n_cols),
51 numTables(projections.n_slices),
52 hashWidth(hashWidthIn),
53 secondHashSize(secondHashSize),
54 bucketSize(bucketSize),
55 distanceEvaluations(0)
58 Train(std::move(referenceSet), numProj, numTables, hashWidthIn,
59 secondHashSize, bucketSize, projections);
63 template<
typename SortPolicy,
typename MatType>
68 secondHashSize(99901),
70 distanceEvaluations(0)
75 template<
typename SortPolicy,
typename MatType>
77 referenceSet(other.referenceSet),
78 numProj(other.numProj),
79 numTables(other.numTables),
80 projections(other.projections),
81 offsets(other.offsets),
82 hashWidth(other.hashWidth),
83 secondHashSize(other.secondHashSize),
84 secondHashWeights(other.secondHashWeights),
85 bucketSize(other.bucketSize),
86 secondHashTable(other.secondHashTable),
87 bucketContentSize(other.bucketContentSize),
88 bucketRowInHashTable(other.bucketRowInHashTable),
89 distanceEvaluations(other.distanceEvaluations)
95 template<
typename SortPolicy,
typename MatType>
97 referenceSet(
std::move(other.referenceSet)),
98 numProj(other.numProj),
99 numTables(other.numTables),
100 projections(
std::move(other.projections)),
101 offsets(
std::move(other.offsets)),
102 hashWidth(other.hashWidth),
103 secondHashSize(other.secondHashSize),
104 secondHashWeights(
std::move(other.secondHashWeights)),
105 bucketSize(other.bucketSize),
106 secondHashTable(
std::move(other.secondHashTable)),
107 bucketContentSize(
std::move(other.bucketContentSize)),
108 bucketRowInHashTable(
std::move(other.bucketRowInHashTable)),
109 distanceEvaluations(other.distanceEvaluations)
115 other.secondHashSize = 99901;
116 other.bucketSize = 500;
117 other.distanceEvaluations = 0;
121 template<
typename SortPolicy,
typename MatType>
125 referenceSet = other.referenceSet;
126 numProj = other.numProj;
127 numTables = other.numTables;
128 projections = other.projections;
129 offsets = other.offsets;
130 hashWidth = other.hashWidth;
131 secondHashSize = other.secondHashSize;
132 secondHashWeights = other.secondHashWeights;
133 bucketSize = other.bucketSize;
134 secondHashTable = other.secondHashTable;
135 bucketContentSize = other.bucketContentSize;
136 bucketRowInHashTable = other.bucketRowInHashTable;
137 distanceEvaluations = other.distanceEvaluations;
143 template<
typename SortPolicy,
typename MatType>
147 referenceSet = std::move(other.referenceSet);
148 numProj = other.numProj;
149 numTables = other.numTables;
150 projections = std::move(other.projections);
151 offsets = std::move(other.offsets);
152 hashWidth = other.hashWidth;
153 secondHashSize = other.secondHashSize;
154 secondHashWeights = std::move(other.secondHashWeights);
155 bucketSize = other.bucketSize;
156 secondHashTable = std::move(other.secondHashTable);
157 bucketContentSize = std::move(other.bucketContentSize);
158 bucketRowInHashTable = std::move(other.bucketRowInHashTable);
159 distanceEvaluations = other.distanceEvaluations;
165 other.secondHashSize = 99901;
166 other.bucketSize = 500;
167 other.distanceEvaluations = 0;
173 template<
typename SortPolicy,
typename MatType>
175 const size_t numProj,
176 const size_t numTables,
177 const double hashWidthIn,
178 const size_t secondHashSize,
179 const size_t bucketSize,
180 const arma::cube& projection)
183 this->referenceSet = std::move(referenceSet);
186 this->numProj = numProj;
187 this->numTables = numTables;
188 this->hashWidth = hashWidthIn;
189 this->secondHashSize = secondHashSize;
190 this->bucketSize = bucketSize;
192 if (hashWidth == 0.0)
194 const size_t numSamples = 25;
196 for (
size_t i = 0; i < numSamples; ++i)
198 size_t p1 = (size_t)
math::RandInt(this->referenceSet.n_cols);
199 size_t p2 = (size_t)
math::RandInt(this->referenceSet.n_cols);
202 this->referenceSet.col(p1),
203 this->referenceSet.col(p2)));
206 hashWidth /= numSamples;
209 Log::Info <<
"Hash width chosen as: " << hashWidth << std::endl;
219 secondHashWeights = arma::floor(arma::randu(numProj) *
220 (
double) secondHashSize);
226 bucketRowInHashTable.set_size(secondHashSize);
227 bucketRowInHashTable.fill(secondHashSize);
232 offsets.randu(numProj, numTables);
233 offsets *= hashWidth;
238 if (projection.n_slices == 0)
244 projections.randn(this->referenceSet.n_rows, numProj, numTables);
246 else if (projection.n_slices == numTables)
248 projections = projection;
252 throw std::invalid_argument(
"LSHSearch::Train(): number of projection " 253 "tables provided must be equal to numProj");
259 arma::Mat<size_t> secondHashVectors(numTables, this->referenceSet.n_cols);
261 for (
size_t i = 0; i < numTables; ++i)
274 arma::mat offsetMat = arma::repmat(offsets.unsafe_col(i), 1,
275 this->referenceSet.n_cols);
276 arma::mat hashMat = projections.slice(i).t() * (this->referenceSet);
277 hashMat += offsetMat;
278 hashMat /= hashWidth;
283 arma::rowvec unmodVector = secondHashWeights.t() * arma::floor(hashMat);
284 for (
size_t j = 0; j < unmodVector.n_elem; ++j)
286 double shs = (double) secondHashSize;
287 if (unmodVector[j] >= 0.0)
289 const size_t key = size_t(fmod(unmodVector[j], shs));
290 secondHashVectors(i, j) = key;
294 const double mod = fmod(-unmodVector[j], shs);
295 const size_t key = (mod < 1.0) ? 0 : secondHashSize - size_t(mod);
296 secondHashVectors(i, j) = key;
303 arma::Row<size_t> secondHashBinCounts(secondHashSize, arma::fill::zeros);
304 for (
size_t i = 0; i < secondHashVectors.n_elem; ++i)
305 secondHashBinCounts[secondHashVectors[i]]++;
308 const size_t effectiveBucketSize = (bucketSize == 0) ? SIZE_MAX : bucketSize;
309 secondHashBinCounts.transform([effectiveBucketSize](
size_t val)
310 {
return std::min(val, effectiveBucketSize); });
312 const size_t numRowsInTable = arma::accu(secondHashBinCounts > 0);
313 bucketContentSize.zeros(numRowsInTable);
314 secondHashTable.resize(numRowsInTable);
318 size_t currentRow = 0;
319 for (
size_t i = 0; i < numTables; ++i)
323 for (
size_t j = 0; j < secondHashVectors.n_cols; ++j)
326 size_t hashInd = (size_t) secondHashVectors(i, j);
331 const size_t maxSize = secondHashBinCounts[hashInd];
332 if (bucketRowInHashTable[hashInd] == secondHashSize)
334 bucketRowInHashTable[hashInd] = currentRow;
335 secondHashTable[currentRow].set_size(maxSize);
340 const size_t index = bucketRowInHashTable[hashInd];
341 if (bucketContentSize[index] < maxSize)
342 secondHashTable[index](bucketContentSize[index]++) = j;
346 Log::Info <<
"Final hash table size: " << numRowsInTable <<
" rows, with a " 347 <<
"maximum length of " << arma::max(secondHashBinCounts) <<
", " 348 <<
"totaling " << arma::accu(secondHashBinCounts) <<
" elements." 354 template<
typename SortPolicy,
typename MatType>
357 const size_t queryIndex,
358 const arma::uvec& referenceIndices,
360 arma::Mat<size_t>& neighbors,
361 arma::mat& distances)
const 366 const Candidate def = std::make_pair(SortPolicy::WorstDistance(),
367 referenceSet.n_cols);
368 std::vector<Candidate> vect(k, def);
369 CandidateList pqueue(CandidateCmp(), std::move(vect));
371 for (
size_t j = 0; j < referenceIndices.n_elem; ++j)
373 const size_t referenceIndex = referenceIndices[j];
375 if (queryIndex == referenceIndex)
379 referenceSet.col(queryIndex),
380 referenceSet.col(referenceIndex));
382 Candidate c = std::make_pair(distance, referenceIndex);
384 if (CandidateCmp()(c, pqueue.top()))
391 for (
size_t j = 1; j <= k; ++j)
393 neighbors(k - j, queryIndex) = pqueue.top().second;
394 distances(k - j, queryIndex) = pqueue.top().first;
400 template<
typename SortPolicy,
typename MatType>
403 const size_t queryIndex,
404 const arma::uvec& referenceIndices,
406 const MatType& querySet,
407 arma::Mat<size_t>& neighbors,
408 arma::mat& distances)
const 413 const Candidate def = std::make_pair(SortPolicy::WorstDistance(),
414 referenceSet.n_cols);
415 std::vector<Candidate> vect(k, def);
416 CandidateList pqueue(CandidateCmp(), std::move(vect));
418 for (
size_t j = 0; j < referenceIndices.n_elem; ++j)
420 const size_t referenceIndex = referenceIndices[j];
422 querySet.col(queryIndex),
423 referenceSet.col(referenceIndex));
425 Candidate c = std::make_pair(distance, referenceIndex);
427 if (CandidateCmp()(c, pqueue.top()))
434 for (
size_t j = 1; j <= k; ++j)
436 neighbors(k - j, queryIndex) = pqueue.top().second;
437 distances(k - j, queryIndex) = pqueue.top().first;
442 template<
typename SortPolicy,
typename MatType>
445 const std::vector<bool>&
A,
446 const arma::vec& scores)
const 449 for (
size_t i = 0; i < A.size(); ++i)
455 template<
typename SortPolicy,
typename MatType>
458 std::vector<bool>& A)
const 461 for (
size_t i = 0; i < A.size(); ++i)
465 if (maxPos + 1 < A.size())
474 template<
typename SortPolicy,
typename MatType>
477 std::vector<bool>& A)
const 481 for (
size_t i = 0; i < A.size(); ++i)
485 if (maxPos + 1 < A.size())
493 template<
typename SortPolicy,
typename MatType>
496 const std::vector<bool>& A)
const 500 std::vector<bool> check(numProj);
502 if (A.size() > 2 * numProj)
506 for (
size_t i = 0; i < A.size(); ++i)
513 if (check[i % numProj] ==
false)
514 check[i % numProj] =
true;
523 template<
typename SortPolicy,
typename MatType>
525 const arma::vec& queryCode,
526 const arma::vec& queryCodeNotFloored,
528 arma::mat& additionalProbingBins)
const 535 additionalProbingBins.set_size(numProj, T);
539 for (
size_t c = 0; c < T; ++c)
540 additionalProbingBins.col(c) = queryCode;
544 arma::mat projection = queryCodeNotFloored;
547 arma::vec limLow = projection - queryCode * hashWidth;
548 arma::vec limHigh = hashWidth - limLow;
551 arma::vec scores(2 * numProj);
552 scores.rows(0, numProj - 1) = arma::pow(limLow, 2);
553 scores.rows(numProj, (2 * numProj) - 1) = arma::pow(limHigh, 2);
556 arma::Col<short int> actions(2 * numProj);
557 actions.rows(0, numProj - 1) =
558 -1 * arma::ones< arma::Col<short int> > (numProj);
559 actions.rows(numProj, (2 * numProj) - 1) =
560 arma::ones< arma::Col<short int> > (numProj);
565 arma::Col<size_t> positions(2 * numProj);
566 positions.rows(0, numProj - 1) =
567 arma::linspace< arma::Col<size_t> >(0, numProj - 1, numProj);
568 positions.rows(numProj, 2 * numProj - 1) =
569 arma::linspace< arma::Col<size_t> >(0, numProj - 1, numProj);
578 double minscore = scores[0];
580 for (
size_t s = 1; s < (2 * numProj); ++s)
582 if (minscore > scores[s])
584 minscore = scores[s];
590 additionalProbingBins(positions[minloc], 0) += actions[minloc];
603 double minscore2 = scores[0];
605 for (
size_t s = 0; s < (2 * numProj); ++s)
607 if (minscore2 > scores[s] && s != minloc)
609 minscore2 = scores[s];
615 additionalProbingBins(positions[minloc2], 1) += actions[minloc2];
621 arma::uvec sortidx = arma::sort_index(scores);
622 scores = scores(sortidx);
623 actions = actions(sortidx);
624 positions = positions(sortidx);
642 std::vector<bool> Ao(2 * numProj);
645 std::vector< std::vector<bool> > perturbationSets;
646 perturbationSets.push_back(Ao);
649 std::pair<double, size_t>,
651 std::pair<double, size_t>
653 std::greater< std::pair<double, size_t> >
657 minHeap.push(std::make_pair(PerturbationScore(Ao, scores), 0));
662 for (
size_t pvec = 0; pvec < T; ++pvec)
664 std::vector<bool> Ai;
668 Ai = perturbationSets[ minHeap.top().second ];
672 std::vector<bool> As = Ai;
675 if (PerturbationShift(As) && PerturbationValid(As))
677 perturbationSets.push_back(As);
679 std::make_pair(PerturbationScore(As, scores),
680 perturbationSets.size() - 1));
684 std::vector<bool> Ae = Ai;
687 if (PerturbationExpand(Ae) && PerturbationValid(Ae))
689 perturbationSets.push_back(Ae);
691 std::make_pair(PerturbationScore(Ae, scores),
692 perturbationSets.size() - 1));
694 }
while (!PerturbationValid(Ai));
697 for (
size_t pos = 0; pos < Ai.size(); ++pos)
700 additionalProbingBins(positions(pos), pvec) += Ai[pos] ? actions(pos) : 0;
705 template<
typename SortPolicy,
typename MatType>
706 template<
typename VecType>
708 const VecType& queryPoint,
709 arma::uvec& referenceIndices,
710 size_t numTablesToSearch,
711 const size_t T)
const 714 if (numTablesToSearch == 0)
715 numTablesToSearch = numTables;
719 if (numTablesToSearch > numTables)
720 numTablesToSearch = numTables;
728 arma::mat allProjInTables(numProj, numTablesToSearch);
729 arma::mat queryCodesNotFloored(numProj, numTablesToSearch);
730 for (
size_t i = 0; i < numTablesToSearch; ++i)
731 queryCodesNotFloored.unsafe_col(i) = projections.slice(i).t() * queryPoint;
733 queryCodesNotFloored += offsets.cols(0, numTablesToSearch - 1);
734 allProjInTables = arma::floor(queryCodesNotFloored / hashWidth);
738 arma::Mat<size_t> hashMat;
739 hashMat.set_size(T + 1, numTablesToSearch);
743 hashMat.row(0) = arma::conv_to<arma::Row<size_t>>
744 ::from(secondHashWeights.t() * allProjInTables);
746 for (
size_t i = 0; i < numTablesToSearch; ++i)
747 hashMat(0, i) = (hashMat(0, i) % secondHashSize);
752 for (
size_t i = 0; i < numTablesToSearch; ++i)
755 arma::mat additionalProbingBins;
756 GetAdditionalProbingBins(allProjInTables.unsafe_col(i),
757 queryCodesNotFloored.unsafe_col(i),
759 additionalProbingBins);
763 hashMat(arma::span(1, T), i) =
764 arma::conv_to< arma::Col<size_t> >::
765 from(secondHashWeights.t() * additionalProbingBins);
766 for (
size_t p = 1; p < T + 1; ++p)
767 hashMat(p, i) = (hashMat(p, i) % secondHashSize);
772 size_t maxNumPoints = 0;
773 for (
size_t i = 0; i < numTablesToSearch; ++i)
775 for (
size_t p = 0; p < T + 1; ++p)
777 const size_t hashInd = hashMat(p, i);
778 const size_t tableRow = bucketRowInHashTable[hashInd];
779 if (tableRow < secondHashSize)
780 maxNumPoints += bucketContentSize[tableRow];
791 const float cutoff = 0.1;
792 const float selectivity =
static_cast<float>(maxNumPoints) /
793 static_cast<float>(referenceSet.n_cols);
795 if (selectivity > cutoff)
800 arma::Col<size_t> refPointsConsidered;
801 refPointsConsidered.zeros(referenceSet.n_cols);
803 for (
size_t i = 0; i < numTablesToSearch; ++i)
805 for (
size_t p = 0; p < T + 1; ++p)
808 size_t hashInd = hashMat(p, i);
809 size_t tableRow = bucketRowInHashTable[hashInd];
811 if (tableRow < secondHashSize && bucketContentSize[tableRow] > 0)
814 for (
size_t j = 0; j < bucketContentSize[tableRow]; ++j)
815 refPointsConsidered[ secondHashTable[tableRow](j) ]++;
821 referenceIndices = arma::find(refPointsConsidered > 0);
829 arma::uvec refPointsConsideredSmall;
830 refPointsConsideredSmall.zeros(maxNumPoints);
835 for (
size_t i = 0; i < numTablesToSearch; ++i)
837 for (
size_t p = 0; p < T + 1; ++p)
839 const size_t hashInd = hashMat(p, i);
840 const size_t tableRow = bucketRowInHashTable[hashInd];
842 if (tableRow < secondHashSize)
845 for (
size_t j = 0; j < bucketContentSize[tableRow]; ++j)
846 refPointsConsideredSmall(start++) = secondHashTable[tableRow](j);
852 referenceIndices = arma::unique(refPointsConsideredSmall);
858 template<
typename SortPolicy,
typename MatType>
860 const MatType& querySet,
862 arma::Mat<size_t>& resultingNeighbors,
863 arma::mat& distances,
864 const size_t numTablesToSearch,
868 util::CheckSameDimensionality(querySet, referenceSet,
"LSHSearch::Search()",
871 if (k > referenceSet.n_cols)
873 std::ostringstream oss;
874 oss <<
"LSHSearch::Search(): requested " << k <<
" approximate nearest " 875 <<
"neighbors, but reference set has " << referenceSet.n_cols
876 <<
" points!" << std::endl;
877 throw std::invalid_argument(oss.str());
881 resultingNeighbors.set_size(k, querySet.n_cols);
882 distances.set_size(k, querySet.n_cols);
890 size_t Teffective = T;
891 if (T > ((
size_t) ((1 << numProj) - 1)))
893 Teffective = (1 << numProj) - 1;
894 Log::Warn <<
"Requested " << T <<
" additional bins are more than " 895 <<
"theoretical maximum. Using " << Teffective <<
" instead." 901 Log::Info <<
"Running multiprobe LSH with " << Teffective
902 <<
" additional probing bins per table per query." << std::endl;
904 size_t avgIndicesReturned = 0;
909 #pragma omp parallel for \ 910 shared(resultingNeighbors, distances) \ 912 reduction(+:avgIndicesReturned) 913 for (omp_size_t i = 0; i < (omp_size_t) querySet.n_cols; ++i)
918 arma::uvec refIndices;
919 ReturnIndicesFromTable(querySet.col(i), refIndices, numTablesToSearch,
926 avgIndicesReturned = avgIndicesReturned + refIndices.n_elem;
930 BaseCase(i, refIndices, k, querySet, resultingNeighbors, distances);
935 distanceEvaluations += avgIndicesReturned;
936 avgIndicesReturned /= querySet.n_cols;
937 Log::Info << avgIndicesReturned <<
" distinct indices returned on average." <<
942 template<
typename SortPolicy,
typename MatType>
945 arma::Mat<size_t>& resultingNeighbors,
946 arma::mat& distances,
947 const size_t numTablesToSearch,
951 resultingNeighbors.set_size(k, referenceSet.n_cols);
952 distances.set_size(k, referenceSet.n_cols);
956 size_t Teffective = T;
957 if (T > ((
size_t) ((1 << numProj) - 1)))
959 Teffective = (1 << numProj) - 1;
960 Log::Warn <<
"Requested " << T <<
" additional bins are more than " 961 <<
"theoretical maximum. Using " << Teffective <<
" instead." 967 Log::Info <<
"Running multiprobe LSH with " << Teffective <<
968 " additional probing bins per table per query."<< std::endl;
970 size_t avgIndicesReturned = 0;
975 #pragma omp parallel for \ 976 shared(resultingNeighbors, distances) \ 978 reduction(+:avgIndicesReturned) 979 for (omp_size_t i = 0; i < (omp_size_t) referenceSet.n_cols; ++i)
984 arma::uvec refIndices;
985 ReturnIndicesFromTable(referenceSet.col(i), refIndices, numTablesToSearch,
992 avgIndicesReturned += refIndices.n_elem;
996 BaseCase(i, refIndices, k, resultingNeighbors, distances);
1001 distanceEvaluations += avgIndicesReturned;
1002 avgIndicesReturned /= referenceSet.n_cols;
1003 Log::Info << avgIndicesReturned <<
" distinct indices returned on average." <<
1007 template<
typename SortPolicy,
typename MatType>
1009 const arma::Mat<size_t>& foundNeighbors,
1010 const arma::Mat<size_t>& realNeighbors)
1012 if (foundNeighbors.n_rows != realNeighbors.n_rows ||
1013 foundNeighbors.n_cols != realNeighbors.n_cols)
1014 throw std::invalid_argument(
"LSHSearch::ComputeRecall(): matrices provided" 1015 " must have equal size");
1017 const size_t queries = foundNeighbors.n_cols;
1018 const size_t neighbors = foundNeighbors.n_rows;
1022 for (
size_t col = 0; col < queries; ++col)
1023 for (
size_t row = 0; row < neighbors; ++row)
1024 for (
size_t nei = 0; nei < realNeighbors.n_rows; ++nei)
1025 if (realNeighbors(row, col) == foundNeighbors(nei, col))
1031 return ((
double) found) / realNeighbors.n_elem;
1034 template<
typename SortPolicy,
typename MatType>
1035 template<
typename Archive>
1039 ar(CEREAL_NVP(referenceSet));
1040 ar(CEREAL_NVP(numProj));
1041 ar(CEREAL_NVP(numTables));
1044 if (cereal::is_loading<Archive>())
1045 projections.reset();
1047 ar(CEREAL_NVP(projections));
1048 ar(CEREAL_NVP(offsets));
1049 ar(CEREAL_NVP(hashWidth));
1050 ar(CEREAL_NVP(secondHashSize));
1051 ar(CEREAL_NVP(secondHashWeights));
1052 ar(CEREAL_NVP(bucketSize));
1053 ar(CEREAL_NVP(secondHashTable));
1054 ar(CEREAL_NVP(bucketContentSize));
1055 ar(CEREAL_NVP(bucketRowInHashTable));
1056 ar(CEREAL_NVP(distanceEvaluations));
static void Start(const std::string &name)
Start the given timer.
Definition: timers.cpp:28
Linear algebra utility functions, generally performed on matrices or vectors.
Definition: cv.hpp:1
The core includes that mlpack expects; standard C++ includes and Armadillo.
Definition: pointer_wrapper.hpp:23
void serialize(Archive &ar, const uint32_t version)
Serialize the LSH model.
Definition: lsh_search_impl.hpp:1036
Definition: sfinae_test.cpp:18
LSHSearch & operator=(const LSHSearch &other)
Copy the given LSH model.
Definition: lsh_search_impl.hpp:122
void Train(MatType referenceSet, const size_t numProj, const size_t numTables, const double hashWidth=0.0, const size_t secondHashSize=99901, const size_t bucketSize=500, const arma::cube &projection=arma::cube())
Train the LSH model on the given dataset.
Definition: lsh_search_impl.hpp:174
The LSHSearch class; this class builds a hash on the reference set and uses this hash to compute the ...
Definition: lsh_search.hpp:72
static VecTypeA::elem_type Evaluate(const VecTypeA &a, const VecTypeB &b)
Computes the distance between two points.
Definition: lmetric_impl.hpp:24
static MLPACK_EXPORT util::PrefixedOutStream Warn
Prints warning messages prefixed with [WARN ].
Definition: log.hpp:87
static double ComputeRecall(const arma::Mat< size_t > &foundNeighbors, const arma::Mat< size_t > &realNeighbors)
Compute the recall (% of neighbors found) given the neighbors returned by LSHSearch::Search and a "gr...
Definition: lsh_search_impl.hpp:1008
static void Stop(const std::string &name)
Stop the given timer.
Definition: timers.cpp:36
static MLPACK_EXPORT util::PrefixedOutStream Info
Prints informational messages if –verbose is specified, prefixed with [INFO ].
Definition: log.hpp:84
Miscellaneous math random-related routines.
int RandInt(const int hiExclusive)
Generates a uniform random integer.
Definition: random.hpp:110
void Search(const MatType &querySet, const size_t k, arma::Mat< size_t > &resultingNeighbors, arma::mat &distances, const size_t numTablesToSearch=0, const size_t T=0)
Compute the nearest neighbors of the points in the given query set and store the output in the given ...
Definition: lsh_search_impl.hpp:859
LSHSearch()
Create an untrained LSH model.
Definition: lsh_search_impl.hpp:64