Improve KDE docs and style

This commit is contained in:
Roberto Hueso Gomez
2019-07-17 20:40:33 +02:00
parent b72a08e2ef
commit 8c8da569cd
3 changed files with 43 additions and 25 deletions
+2
View File
@@ -111,6 +111,8 @@ PROGRAM_INFO("Kernel Density Estimation",
SEE_ALSO("@knn", "#knn"),
SEE_ALSO("Kernel density estimation on Wikipedia",
"https://en.wikipedia.org/wiki/Kernel_density_estimation"),
SEE_ALSO("Tree-Independent Dual-Tree Algorithms",
"https://arxiv.org/pdf/1304.4327.pdf"),
SEE_ALSO("Fast High-dimensional Kernel Summations Using the Monte Carlo "
"Multipole Method", "http://papers.nips.cc/paper/3539-fast-high-"
"dimensional-kernel-summations-using-the-monte-carlo-multipole-method."
+4 -4
View File
@@ -71,10 +71,10 @@ class KDERules
TreeType& referenceNode,
const double oldScore) const;
//! DoubleTree Score.
//! Dual-Tree Score.
double Score(TreeType& queryNode, TreeType& referenceNode);
//! DoubleTree Rescore.
//! Dual-Tree Rescore.
double Rescore(TreeType& queryNode,
TreeType& referenceNode,
const double oldScore) const;
@@ -193,10 +193,10 @@ class KDECleanRules
TreeType& /* referenceNode */,
const double oldScore) const { return oldScore; }
//! DoubleTree Score.
//! Dual-Tree Score.
double Score(TreeType& queryNode, TreeType& referenceNode);
//! DoubleTree Rescore.
//! Dual-Tree Rescore.
double Rescore(TreeType& /* queryNode */,
TreeType& /* referenceNode*/ ,
const double oldScore) const { return oldScore; }
+37 -21
View File
@@ -96,6 +96,7 @@ Score(const size_t queryIndex, TreeType& referenceNode)
double score, maxKernel, minKernel, bound, depthAlpha;
const arma::vec& queryPoint = querySet.unsafe_col(queryIndex);
const double minDistance = referenceNode.MinDistance(queryPoint);
// Calculations are not duplicated.
bool newCalculations = true;
// Calculate alpha if Monte Carlo is available.
@@ -149,23 +150,27 @@ Score(const size_t queryIndex, TreeType& referenceNode)
kernelIsGaussian)
{
// Monte Carlo probabilistic estimation.
// Calculate z using accumulated alpha if possible.
const double alpha = depthAlpha + accumMCAlpha(queryIndex);
const boost::math::normal normalDist;
const double z =
std::abs(boost::math::quantile(normalDist, alpha / 2));
// Auxiliary variables.
const size_t numDesc = referenceNode.NumDescendants();
arma::vec sample;
size_t m = initialSampleSize;
double meanSample;
bool useMonteCarloPredictions = true;
// Resample as long as confidence is not high enough.
while (m > 0)
{
const size_t oldSize = sample.size();
const size_t newSize = oldSize + m;
// Don't use probabilistic estimation if this is gonna take a close
// amount of computation to the exact calculation.
// Don't use probabilistic estimation if this is going to take a similar
// amount of computations to the exact calculation.
if (newSize >= mcBreakCoef * numDesc)
{
useMonteCarloPredictions = false;
@@ -195,7 +200,7 @@ Score(const size_t queryIndex, TreeType& referenceNode)
if (useMonteCarloPredictions)
{
// Use Monte Carlo estimation.
// Confidence is high enough so we can use Monte Carlo estimation.
densities(queryIndex) += numDesc * meanSample;
score = DBL_MAX;
@@ -218,7 +223,8 @@ Score(const size_t queryIndex, TreeType& referenceNode)
{
score = minDistance;
// If node is going to be exactly computed, reclaim not used alpha.
// If node is going to be exactly computed, reclaim not used alpha for
// Monte Carlo estimations.
if (kernelIsGaussian &&
monteCarlo &&
newCalculations &&
@@ -235,16 +241,16 @@ Score(const size_t queryIndex, TreeType& referenceNode)
}
template<typename MetricType, typename KernelType, typename TreeType>
inline double KDERules<MetricType, KernelType, TreeType>::Rescore(
const size_t /* queryIndex */,
TreeType& /* referenceNode */,
const double oldScore) const
inline force_inline double KDERules<MetricType, KernelType, TreeType>::
Rescore(const size_t /* queryIndex */,
TreeType& /* referenceNode */,
const double oldScore) const
{
// If it's pruned it continues to be pruned.
return oldScore;
}
//! Double-tree scoring function.
//! Dual-tree scoring function.
template<typename MetricType, typename KernelType, typename TreeType>
inline double KDERules<MetricType, KernelType, TreeType>::
Score(TreeType& queryNode, TreeType& referenceNode)
@@ -262,7 +268,8 @@ Score(TreeType& queryNode, TreeType& referenceNode)
else
depthAlpha = -1;
// Check if not used alpha can be reclaimed for this combination of nodes.
// Check if not used Monte Carlo alpha can be reclaimed for this combination
// of nodes.
const bool canReclaimAlpha =
kernelIsGaussian &&
monteCarlo &&
@@ -326,29 +333,35 @@ Score(TreeType& queryNode, TreeType& referenceNode)
kernelIsGaussian)
{
// Monte Carlo probabilistic estimation.
// Calculate z using accumulated alpha if possible.
const double alpha = depthAlpha + queryStat.AccumAlpha();
const boost::math::normal normalDist;
const double z =
std::abs(boost::math::quantile(normalDist, alpha / 2));
// Auxiliary variables.
const size_t numDesc = referenceNode.NumDescendants();
arma::vec sample;
arma::vec means = arma::zeros(queryNode.NumDescendants());
size_t m;
double meanSample;
bool useMonteCarloPredictions = true;
// Pick a sample for every query node.
for (size_t i = 0; i < queryNode.NumDescendants(); ++i)
{
const size_t queryIndex = queryNode.Descendant(i);
sample.clear();
m = initialSampleSize;
// Resample as long as confidence is not high enough.
while (m > 0)
{
const size_t oldSize = sample.size();
const size_t newSize = oldSize + m;
// Don't use probabilistic estimation if this is gonna take a close
// amount of computation to the exact calculation.
// Don't use probabilistic estimation if this is going to take a similar
// amount of computations to the exact calculation.
if (newSize >= mcBreakCoef * numDesc)
{
useMonteCarloPredictions = false;
@@ -376,6 +389,7 @@ Score(TreeType& queryNode, TreeType& referenceNode)
m = 0;
}
// Store mean for the i_th query node descendant point.
if (useMonteCarloPredictions)
means(i) = meanSample;
else
@@ -384,11 +398,13 @@ Score(TreeType& queryNode, TreeType& referenceNode)
if (useMonteCarloPredictions)
{
// Use Monte Carlo estimation.
queryStat.AccumAlpha() = 0;
// Confidence is high enough so we can use Monte Carlo estimation.
score = DBL_MAX;
for (size_t i = 0; i < queryNode.NumDescendants(); ++i)
densities(queryNode.Descendant(i)) += numDesc * means(i);
// Accumulated alpha has been used.
queryStat.AccumAlpha() = 0;
}
else
{
@@ -397,7 +413,7 @@ Score(TreeType& queryNode, TreeType& referenceNode)
if (canReclaimAlpha)
{
// Reclaim not used alpha for Monte Carlo since the nodes will be
// Reclaim not used Monte Carlo alpha since the nodes will be
// exactly computed.
queryStat.AccumAlpha() += depthAlpha;
}
@@ -407,8 +423,8 @@ Score(TreeType& queryNode, TreeType& referenceNode)
{
score = minDistance;
// The node will be exactly computed, so we reclaim not used Monte Carlo
// alpha.
// If node is going to be exactly computed, reclaim not used alpha for
// Monte Carlo estimations.
if (canReclaimAlpha)
queryStat.AccumAlpha() += depthAlpha;
}
@@ -420,9 +436,9 @@ Score(TreeType& queryNode, TreeType& referenceNode)
return score;
}
//! Double-tree rescore.
//! Dual-tree rescore.
template<typename MetricType, typename KernelType, typename TreeType>
inline double KDERules<MetricType, KernelType, TreeType>::
inline force_inline double KDERules<MetricType, KernelType, TreeType>::
Rescore(TreeType& /*queryNode*/,
TreeType& /*referenceNode*/,
const double oldScore) const