[mlpack] 23/30: Don't initialize emissions randomly; initialize them in a way that reflects the training data distribution.

Barak A. Pearlmutter barak+git at pearlmutter.net
Mon Dec 26 10:15:27 UTC 2016


This is an automated email from the git hooks/post-receive script.

bap pushed a commit to branch master
in repository mlpack.

commit 45fe8206b86a174b1bc8401f89a94ce468fae640
Author: Ryan Curtin <ryan at ratml.org>
Date:   Mon Dec 19 15:11:14 2016 -0500

    Don't initialize emissions randomly; initialize them in a way that reflects the training data distribution.
    
    This solves a problem where points with large norm would have probability 0 in
    the initialized emissions, causing HMM training to fail.
---
 src/mlpack/methods/hmm/hmm_train_main.cpp | 111 +++++++++++++++++++++++-------
 1 file changed, 86 insertions(+), 25 deletions(-)

diff --git a/src/mlpack/methods/hmm/hmm_train_main.cpp b/src/mlpack/methods/hmm/hmm_train_main.cpp
index 1b500a1..6d2cc44 100644
--- a/src/mlpack/methods/hmm/hmm_train_main.cpp
+++ b/src/mlpack/methods/hmm/hmm_train_main.cpp
@@ -311,14 +311,37 @@ int main(int argc, char** argv)
         hmm.Transition().randu();
         for (size_t c = 0; c < hmm.Transition().n_cols; ++c)
           hmm.Transition().col(c) /= arma::accu(hmm.Transition().col(c));
+      }
 
-        for (size_t e = 0; e < hmm.Emission().size(); ++e)
+      // Initialize emissions using the distribution of the full data.
+      DiscreteDistribution sampleEmission;
+      if (trainSeq.size() > 1)
+      {
+        // Flatten data matrix for training of an emission distribution.  This
+        // is not efficient!
+        size_t totalCols = 0;
+        for (size_t i = 0; i < trainSeq.size(); ++i)
+          totalCols += trainSeq[i].n_cols;
+
+        arma::mat flatData(trainSeq[0].n_rows, totalCols);
+        size_t currentCol = 0;
+        for (size_t i = 0; i < trainSeq.size(); ++i)
         {
-          hmm.Emission()[e].Probabilities().randu();
-          hmm.Emission()[e].Probabilities() /=
-              arma::accu(hmm.Emission()[e].Probabilities());
+          flatData.cols(currentCol, currentCol + trainSeq[i].n_cols - 1) =
+              trainSeq[i];
+          currentCol += trainSeq[i].n_cols;
         }
+
+        sampleEmission.Train(flatData);
       }
+      else
+      {
+        sampleEmission.Train(trainSeq[0]);
+      }
+
+      // Apply initialized emissions.
+      for (size_t e = 0; e < hmm.Transition().n_cols; ++e)
+        hmm.Emission()[e] = sampleEmission;
 
       // Now train it.  Pass the already-loaded training data.
       Train::Apply(hmm, &trainSeq);
@@ -344,15 +367,37 @@ int main(int argc, char** argv)
         hmm.Transition().randu();
         for (size_t c = 0; c < hmm.Transition().n_cols; ++c)
           hmm.Transition().col(c) /= arma::accu(hmm.Transition().col(c));
+      }
 
-        for (size_t e = 0; e < hmm.Emission().size(); ++e)
+      // Initialize emissions using the distribution of the full data.
+      GaussianDistribution sampleEmission;
+      if (trainSeq.size() > 1)
+      {
+        // Flatten data matrix for training of an emission distribution.  This
+        // is not efficient!
+        size_t totalCols = 0;
+        for (size_t i = 0; i < trainSeq.size(); ++i)
+          totalCols += trainSeq[i].n_cols;
+
+        arma::mat flatData(trainSeq[0].n_rows, totalCols);
+        size_t currentCol = 0;
+        for (size_t i = 0; i < trainSeq.size(); ++i)
         {
-          hmm.Emission()[e].Mean().randu();
-          // Generate random covariance.
-          arma::mat r = arma::randu<arma::mat>(dimensionality, dimensionality);
-          hmm.Emission()[e].Covariance(r * r.t());
+          flatData.cols(currentCol, currentCol + trainSeq[i].n_cols - 1) =
+              trainSeq[i];
+          currentCol += trainSeq[i].n_cols;
         }
+
+        sampleEmission.Train(flatData);
       }
+      else
+      {
+        sampleEmission.Train(trainSeq[0]);
+      }
+
+      // Set all emissions to the initialized emission.
+      for (size_t e = 0; e < hmm.Transition().n_cols; ++e)
+        hmm.Emission()[e] = sampleEmission;
 
       // Now train it.
       Train::Apply(hmm, &trainSeq);
@@ -382,26 +427,42 @@ int main(int argc, char** argv)
         hmm.Transition().randu();
         for (size_t c = 0; c < hmm.Transition().n_cols; ++c)
           hmm.Transition().col(c) /= arma::accu(hmm.Transition().col(c));
+      }
 
-        for (size_t e = 0; e < hmm.Emission().size(); ++e)
+      // Initialize emissions using the distribution of the full data.
+      // Super-simple emission training: we don't want it to take long at all.
+      GMM sampleEmission;
+      EMFit<> fitter(1, 0.01); // Only one iteration of EM GMM training.
+      if (trainSeq.size() > 1)
+      {
+        // Flatten data matrix for training of an emission distribution.  This
+        // is not efficient!
+        size_t totalCols = 0;
+        for (size_t i = 0; i < trainSeq.size(); ++i)
+          totalCols += trainSeq[i].n_cols;
+
+        arma::mat flatData(trainSeq[0].n_rows, totalCols);
+        size_t currentCol = 0;
+        for (size_t i = 0; i < trainSeq.size(); ++i)
         {
-          // Random weights.
-          hmm.Emission()[e].Weights().randu();
-          hmm.Emission()[e].Weights() /=
-              arma::accu(hmm.Emission()[e].Weights());
-
-          // Random means and covariances.
-          for (int g = 0; g < gaussians; ++g)
-          {
-            hmm.Emission()[e].Component(g).Mean().randu();
-
-            // Generate random covariance.
-            arma::mat r = arma::randu<arma::mat>(dimensionality,
-                dimensionality);
-            hmm.Emission()[e].Component(g).Covariance(r * r.t());
-          }
+          flatData.cols(currentCol, currentCol + trainSeq[i].n_cols - 1) =
+              trainSeq[i];
+          currentCol += trainSeq[i].n_cols;
         }
+
+        sampleEmission.Train(flatData, 1, false, fitter);
       }
+      else
+      {
+        sampleEmission.Train(trainSeq[0], 1, false, fitter);
+      }
+
+      // Set all emissions to the initialized emission.
+      for (size_t e = 0; e < hmm.Transition().n_cols; ++e)
+        hmm.Emission()[e] = sampleEmission;
+
+      // Now train it.
+      Train::Apply(hmm, &trainSeq);
 
       // Issue a warning if the user didn't give labels.
       if (!CLI::HasParam("labels_file"))

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/mlpack.git



More information about the debian-science-commits mailing list