bpp-core3  3.0.0
AdaptiveKernelDensityEstimation.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
6 #include "Matrix/MatrixTools.h"
7 #include "NumConstants.h"
8 
9 using namespace bpp;
10 using namespace std;
11 
13 {
14  // Compute the covariance matrix of the sample:
15  MatrixTools::covar(x_, covar_);
16 
17  // Compute the mean vector
18  sampleMean_(x_, xMean_);
19 
20  // Compute the inverse of the square root of the covariance matrix:
21  MatrixTools::pow<double>(covar_, -0.5, invSqrtCovar_);
22 
23  // Compute the bandwidth:
24  h_ = std::pow(4. / ((2 * static_cast<double>(r_) + 1.) * static_cast<double>(n_)), 1. / (static_cast<double>(r_) + 4.));
25  // Compute as much as we can in advance to simplify the density calculation:
26  c1_ = 1. / (std::sqrt(MatrixTools::det(covar_)) * static_cast<double>(n_) * std::pow(h_, static_cast<int>(r_)));
27 
28  // Now compute the local tuning of the bandwidth.
29  // First estimate the pilot density:
30  vector<double> xi(r_);
31  LinearMatrix<double> diff_xi(r_, 1);
32  LinearMatrix<double> std_xi(r_, 1);
33  for (unsigned int i = 0; i < n_; i++)
34  {
35  // Get the current xi point to evaluate:
36  for (unsigned int k = 0; k < r_; k++)
37  {
38  xi[k] = x_(k, i);
39  }
40 
41  // Sum loop, over all xi's:
42  double sum = 0;
43  for (unsigned int j = 0; j < n_; j++)
44  {
45  for (unsigned int k = 0; k < r_; k++)
46  {
47  diff_xi(k, 0) = xi[k] - x_(k, j);
48  }
49  MatrixTools::mult(invSqrtCovar_, diff_xi, std_xi);
50  MatrixTools::scale(std_xi, 1. / h_);
51  sum += kernel_(std_xi);
52  }
53  pilot_[i] = c1_ * sum;
54  }
55 
56  // Compute the tuning parameters:
57  double g = 0;
58  for (unsigned int i = 0; i < n_; i++)
59  {
60  g += std::log(pilot_[i]);
61  }
62  g = std::exp(g / static_cast<double>(n_));
63  for (unsigned int i = 0; i < n_; i++)
64  {
65  lambda_[i] = std::pow(g / pilot_[i], gamma_);
66  }
67 
68  // Compute as much as we can in advance to simplify the density calculation:
69  for (unsigned int i = 0; i < n_; i++)
70  {
71  c2_[i] = std::pow(lambda_[i], -static_cast<double>(r_));
72  }
73 }
74 
75 void AdaptiveKernelDensityEstimation::sampleMean_(const Matrix<double>& x, std::vector<double>& mean)
76 {
77  size_t nc = x.getNumberOfColumns();
78  size_t nr = x.getNumberOfRows();
79  mean.resize(nr);
80  for (size_t i = 0; i < nr; i++)
81  {
82  mean[i] = 0;
83  for (size_t j = 0; j < nc; j++)
84  {
85  mean[i] += x(i, j);
86  }
87  mean[i] /= static_cast<double>(nc);
88  }
89 }
90 
92 {
93  // x is supposed to have only one column and r_ rows.
94  // We compute the scalar product of the column with itself:
95  double scalar = 0;
96  for (size_t i = 0; i < r_; i++)
97  {
98  scalar += std::pow(x(i, 0), 2.);
99  }
100 
101  return std::pow(2. * NumConstants::PI(), -static_cast<double>(r_) / 2.) * std::exp(-0.5 * scalar);
102 }
103 
104 double AdaptiveKernelDensityEstimation::kDensity(const std::vector<double>& x)
105 {
106  LinearMatrix<double> diff_xi(r_, 1);
107  LinearMatrix<double> std_xi(r_, 1);
108  // Sum loop, over all xi's:
109  double sum = 0;
110  for (unsigned int j = 0; j < n_; j++)
111  {
112  for (unsigned int k = 0; k < r_; k++)
113  {
114  diff_xi(k, 0) = x[k] - x_(k, j);
115  }
116  MatrixTools::mult(invSqrtCovar_, diff_xi, std_xi);
117  MatrixTools::scale(std_xi, 1. / (h_ * lambda_[j]));
118  sum += kernel_(std_xi) * c2_[j];
119  }
120  return c1_ * sum;
121 }
The matrix template interface.
Definition: Matrix.h:22
STL namespace.
Matrix storage in one vector.
Definition: Matrix.h:318
virtual size_t getNumberOfColumns() const =0
static void mult(const Matrix< Scalar > &A, const Matrix< Scalar > &B, Matrix< Scalar > &O)
Definition: MatrixTools.h:221
void sampleMean_(const Matrix< double > &x, std::vector< double > &mean)
static void scale(Matrix &A, Scalar a, Scalar b=0)
Multiply all elements of a matrix by a given value, and add a constant.
Definition: MatrixTools.h:201
double kernel_(const Matrix< double > &x)
The kernel function.
double kDensity(const std::vector< double > &x)
static double PI()
Definition: NumConstants.h:61
virtual size_t getNumberOfRows() const =0
static void covar(const Matrix< Scalar > &A, Matrix< Scalar > &O)
Compute the variance-covariance matrix of an input matrix.
Definition: MatrixTools.h:874
static double det(const Matrix< Scalar > &A)
Get determinant of a square matrix.
Definition: MatrixTools.h:816