MLPACK  1.0.7
phi.hpp
Go to the documentation of this file.
1 
23 #ifndef __MLPACK_METHODS_MOG_PHI_HPP
24 #define __MLPACK_METHODS_MOG_PHI_HPP
25 
26 #include <mlpack/core.hpp>
27 
28 namespace mlpack {
29 namespace gmm {
30 
46 inline double phi(const double x, const double mean, const double var)
47 {
48  return exp(-1.0 * ((x - mean) * (x - mean) / (2 * var)))
49  / sqrt(2 * M_PI * var);
50 }
51 
68 inline double phi(const arma::vec& x,
69  const arma::vec& mean,
70  const arma::mat& cov)
71 {
72  arma::vec diff = mean - x;
73 
74  // Parentheses required for Armadillo 3.0.0 bug.
75  arma::vec exponent = -0.5 * (trans(diff) * inv(cov) * diff);
76 
77  // TODO: What if det(cov) < 0?
78  return pow(2 * M_PI, (double) x.n_elem / -2.0) * pow(det(cov), -0.5) *
79  exp(exponent[0]);
80 }
81 
94 inline double phi(const arma::vec& x,
95  const arma::vec& mean,
96  const arma::mat& cov,
97  const std::vector<arma::mat>& d_cov,
98  arma::vec& g_mean,
99  arma::vec& g_cov)
100 {
101  // We don't call out to another version of the function to avoid inverting the
102  // covariance matrix more than once.
103  arma::mat cinv = inv(cov);
104 
105  arma::vec diff = mean - x;
106  // Parentheses required for Armadillo 3.0.0 bug.
107  arma::vec exponent = -0.5 * (trans(diff) * inv(cov) * diff);
108 
109  long double f = pow(2 * M_PI, (double) x.n_elem / 2) * pow(det(cov), -0.5)
110  * exp(exponent[0]);
111 
112  // Calculate the g_mean values; this is a (1 x dim) vector.
113  arma::vec invDiff = cinv * diff;
114  g_mean = f * invDiff;
115 
116  // Calculate the g_cov values; this is a (1 x (dim * (dim + 1) / 2)) vector.
117  for (size_t i = 0; i < d_cov.size(); i++)
118  {
119  arma::mat inv_d = cinv * d_cov[i];
120 
121  g_cov[i] = f * dot(d_cov[i] * invDiff, invDiff) +
122  accu(inv_d.diag()) / 2;
123  }
124 
125  return f;
126 }
127 
138 inline void phi(const arma::mat& x,
139  const arma::vec& mean,
140  const arma::mat& cov,
141  arma::vec& probabilities)
142 {
143  // Column i of 'diffs' is the difference between x.col(i) and the mean.
144  arma::mat diffs = x - (mean * arma::ones<arma::rowvec>(x.n_cols));
145 
146  // Now, we only want to calculate the diagonal elements of (diffs' * cov^-1 *
147  // diffs). We just don't need any of the other elements. We can calculate
148  // the right hand part of the equation (instead of the left side) so that
149  // later we are referencing columns, not rows -- that is faster.
150  arma::mat rhs = -0.5 * inv(cov) * diffs;
151  arma::vec exponents(diffs.n_cols); // We will now fill this.
152  for (size_t i = 0; i < diffs.n_cols; i++)
153  exponents(i) = exp(accu(diffs.unsafe_col(i) % rhs.unsafe_col(i)));
154 
155  probabilities = pow(2 * M_PI, (double) mean.n_elem / -2.0) *
156  pow(det(cov), -0.5) * exponents;
157 }
158 
159 }; // namespace gmm
160 }; // namespace mlpack
161 
162 #endif
#define M_PI
Definition: core.hpp:169
double phi(const double x, const double mean, const double var)
Calculates the univariate Gaussian probability density function.
Definition: phi.hpp:46