[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