[mlpack-svn] r14889 - mlpack/trunk/src/mlpack/core/dists

fastlab-svn at coffeetalk-1.cc.gatech.edu fastlab-svn at coffeetalk-1.cc.gatech.edu
Wed Apr 10 17:09:46 EDT 2013


Author: rcurtin
Date: 2013-04-10 17:09:46 -0400 (Wed, 10 Apr 2013)
New Revision: 14889

Modified:
   mlpack/trunk/src/mlpack/core/dists/gaussian_distribution.cpp
Log:
Put in checks for non-invertible covariances after training; add perturbation to
avoid them where necessary.  Also avoid dividing by zero.


Modified: mlpack/trunk/src/mlpack/core/dists/gaussian_distribution.cpp
===================================================================
--- mlpack/trunk/src/mlpack/core/dists/gaussian_distribution.cpp	2013-04-10 19:41:43 UTC (rev 14888)
+++ mlpack/trunk/src/mlpack/core/dists/gaussian_distribution.cpp	2013-04-10 21:09:46 UTC (rev 14889)
@@ -22,8 +22,6 @@
  */
 void GaussianDistribution::Estimate(const arma::mat& observations)
 {
-  // Calculate the mean and covariance with each point.  Because this is a
-  // std::vector and not a matrix, this is a little more difficult.
   if (observations.n_cols > 0)
   {
     mean.zeros(observations.n_rows);
@@ -33,6 +31,7 @@
   {
     mean.zeros(0);
     covariance.zeros(0);
+    return;
   }
 
   // Calculate the mean.
@@ -52,6 +51,17 @@
   // Finish estimating the covariance by normalizing, with the (1 / (n - 1)) so
   // that it is the unbiased estimator.
   covariance /= (observations.n_cols - 1);
+
+  // Ensure that there are no zeros on the diagonal.
+  for (size_t d = 0; d < covariance.n_rows; ++d)
+  {
+    if (covariance(d, d) == 0.0)
+    {
+      Log::Debug << "GaussianDistribution::Estimate(): covariance diagonal "
+          << "element " << d << " is 0; adding perturbation." << std::endl;
+      covariance(d, d) = 1e-50;
+    }
+  }
 }
 
 /**
@@ -71,6 +81,7 @@
   {
     mean.zeros(0);
     covariance.zeros(0);
+    return;
   }
 
   double sumProb = 0;
@@ -83,6 +94,14 @@
     sumProb += probabilities[i];
   }
 
+  if (sumProb == 0)
+  {
+    // Nothing in this Gaussian!  At least set the covariance so that it's
+    // invertible.
+    covariance.diag() += 1e-50;
+    return;
+  }
+
   // Normalize.
   mean /= sumProb;
 
@@ -96,6 +115,16 @@
   // This is probably biased, but I don't know how to unbias it.
   covariance /= sumProb;
 
+  // Ensure that there are no zeros on the diagonal.
+  for (size_t d = 0; d < covariance.n_rows; ++d)
+  {
+    if (covariance(d, d) == 0.0)
+    {
+      Log::Debug << "GaussianDistribution::Estimate(): covariance diagonal "
+          << "element " << d << " is 0; adding perturbation." << std::endl;
+      covariance(d, d) = 1e-50;
+    }
+  }
 }
 
 /**




More information about the mlpack-svn mailing list