Refactor tests to avoid sometimes-failing GMM training.
This commit is contained in:
@@ -120,55 +120,25 @@ BOOST_AUTO_TEST_CASE(HMMGenerateGaussianHMMCheckDimensionsTest)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(HMMGenerateGMMHMMCheckDimensionsTest)
|
||||
{
|
||||
// Load data to train a Gaussian Mixture Model HMM model with.
|
||||
std::vector<GMM> gmms(2, GMM(2, 2));
|
||||
gmms[0].Weights() = arma::vec("0.3 0.7");
|
||||
|
||||
// N([2.25 3.10], [1.00 0.20; 0.20 0.89])
|
||||
gmms[0].Component(0) = GaussianDistribution("4.25 3.10",
|
||||
"1.00 0.20; 0.20 0.89");
|
||||
|
||||
// N([4.10 1.01], [1.00 0.00; 0.00 1.01])
|
||||
gmms[0].Component(1) = GaussianDistribution("7.10 5.01",
|
||||
"1.00 0.00; 0.00 1.01");
|
||||
|
||||
gmms[1].Weights() = arma::vec("0.20 0.80");
|
||||
|
||||
gmms[1].Component(0) = GaussianDistribution("-3.00 -6.12",
|
||||
"1.00 0.00; 0.00 1.00");
|
||||
|
||||
gmms[1].Component(1) = GaussianDistribution("-4.25 -2.12",
|
||||
"1.50 0.60; 0.60 1.20");
|
||||
|
||||
// Transition matrix.
|
||||
arma::mat transMat("0.40 0.60;"
|
||||
"0.60 0.40");
|
||||
|
||||
// Make a sequence of observations.
|
||||
std::vector<arma::mat> observations(5, arma::mat(2, 50));
|
||||
std::vector<arma::Row<size_t> > states(5, arma::Row<size_t>(50));
|
||||
for (size_t obs = 0; obs < 5; obs++)
|
||||
{
|
||||
states[obs][0] = 0;
|
||||
observations[obs].col(0) = gmms[0].Random();
|
||||
|
||||
for (size_t i = 1; i < 50; i++)
|
||||
{
|
||||
double randValue = (double) rand() / (double) RAND_MAX;
|
||||
|
||||
if (randValue <= transMat(0, states[obs][i - 1]))
|
||||
states[obs][i] = 0;
|
||||
else
|
||||
states[obs][i] = 1;
|
||||
|
||||
observations[obs].col(i) = gmms[states[obs][i]].Random();
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize and train a GMM HMM model.
|
||||
HMMModel* h = new HMMModel(GaussianMixtureModelHMM);
|
||||
h->PerformAction<InitHMMModel, std::vector<arma::mat>>(&observations);
|
||||
h->PerformAction<TrainHMMModel, std::vector<arma::mat>>(&observations);
|
||||
*(h->GMMHMM()) = HMM<GMM>(2, GMM(2, 2));
|
||||
|
||||
// Manually set the components.
|
||||
h->GMMHMM()->Transition() = arma::mat("0.40 0.60; 0.60 0.40");
|
||||
h->GMMHMM()->Emission().resize(2);
|
||||
h->GMMHMM()->Emission()[0] = GMM(2, 2);
|
||||
h->GMMHMM()->Emission()[0].Weights() = arma::vec("0.3 0.7");
|
||||
h->GMMHMM()->Emission()[0].Component(0) = GaussianDistribution("4.25 3.10",
|
||||
"1.00 0.20; 0.20 0.89");
|
||||
h->GMMHMM()->Emission()[0].Component(1) = GaussianDistribution("7.10 5.01",
|
||||
"1.00 0.00; 0.00 1.01");
|
||||
h->GMMHMM()->Emission()[1] = GMM(2, 2);
|
||||
h->GMMHMM()->Emission()[1].Weights() = arma::vec("0.20 0.80");
|
||||
h->GMMHMM()->Emission()[1].Component(0) = GaussianDistribution("-3.00 -6.12",
|
||||
"1.00 0.00; 0.00 1.00");
|
||||
h->GMMHMM()->Emission()[1].Component(1) = GaussianDistribution("-4.25 -2.12",
|
||||
"1.50 0.60; 0.60 1.20");
|
||||
|
||||
// Now that we have a trained HMM model, we can use it to generate a sequence
|
||||
// of states and observations - using the hmm_generate utility.
|
||||
@@ -184,16 +154,16 @@ BOOST_AUTO_TEST_CASE(HMMGenerateGMMHMMCheckDimensionsTest)
|
||||
// Get the generated observation sequence. Ensure that the generated sequence
|
||||
// has the correct length (as provided in the input).
|
||||
arma::mat obsSeq = CLI::GetParam<arma::mat>("output");
|
||||
BOOST_REQUIRE_EQUAL(obsSeq.n_cols, (size_t)length);
|
||||
BOOST_REQUIRE_EQUAL(obsSeq.n_rows, (size_t)2);
|
||||
BOOST_REQUIRE_EQUAL(obsSeq.n_elem, (size_t)(length*2));
|
||||
BOOST_REQUIRE_EQUAL(obsSeq.n_cols, (size_t) length);
|
||||
BOOST_REQUIRE_EQUAL(obsSeq.n_rows, (size_t) 2);
|
||||
BOOST_REQUIRE_EQUAL(obsSeq.n_elem, (size_t) (length*2));
|
||||
|
||||
// Get the generated state sequence. Ensure that the generated sequence
|
||||
// has the correct length (as provided in the input).
|
||||
arma::Mat<size_t> stateSeq = CLI::GetParam<arma::Mat<size_t>>("state");
|
||||
BOOST_REQUIRE_EQUAL(stateSeq.n_cols, (size_t)length);
|
||||
BOOST_REQUIRE_EQUAL(stateSeq.n_rows, (size_t)1);
|
||||
BOOST_REQUIRE_EQUAL(stateSeq.n_elem, (size_t)length);
|
||||
BOOST_REQUIRE_EQUAL(stateSeq.n_cols, (size_t) length);
|
||||
BOOST_REQUIRE_EQUAL(stateSeq.n_rows, (size_t) 1);
|
||||
BOOST_REQUIRE_EQUAL(stateSeq.n_elem, (size_t) length);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(HMMGenerateLengthPositiveTest)
|
||||
|
||||
@@ -106,62 +106,56 @@ BOOST_AUTO_TEST_CASE(HMMViterbiGaussianHMMCheckDimensionsTest)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(HMMViterbiGMMHMMCheckDimensionsTest)
|
||||
{
|
||||
// Load data to train a Gaussian Mixture Model HMM model with.
|
||||
std::vector<GMM> gmms(2, GMM(2, 2));
|
||||
gmms[0].Weights() = arma::vec("0.3 0.7");
|
||||
|
||||
// N([2.25 3.10], [1.00 0.20; 0.20 0.89])
|
||||
gmms[0].Component(0) = GaussianDistribution("4.25 3.10",
|
||||
"1.00 0.20; 0.20 0.89");
|
||||
|
||||
// N([4.10 1.01], [1.00 0.00; 0.00 1.01])
|
||||
"1.00 0.20; 0.20 0.89");
|
||||
gmms[0].Component(1) = GaussianDistribution("7.10 5.01",
|
||||
"1.00 0.00; 0.00 1.01");
|
||||
|
||||
"1.00 0.00; 0.00 1.01");
|
||||
gmms[1].Weights() = arma::vec("0.20 0.80");
|
||||
|
||||
gmms[1].Component(0) = GaussianDistribution("-3.00 -6.12",
|
||||
"1.00 0.00; 0.00 1.00");
|
||||
|
||||
"1.00 0.00; 0.00 1.00");
|
||||
gmms[1].Component(1) = GaussianDistribution("-4.25 -2.12",
|
||||
"1.50 0.60; 0.60 1.20");
|
||||
"1.50 0.60; 0.60 1.20");
|
||||
|
||||
// Transition matrix.
|
||||
arma::mat transMat("0.40 0.60;"
|
||||
"0.60 0.40");
|
||||
arma::mat transMat("0.40 0.60; 0.60 0.40");
|
||||
|
||||
// Make a sequence of observations.
|
||||
std::vector<arma::mat> observations(5, arma::mat(2, 50));
|
||||
std::vector<arma::Row<size_t> > states(5, arma::Row<size_t>(50));
|
||||
for (size_t obs = 0; obs < 5; obs++)
|
||||
// Make some observations.
|
||||
arma::mat observations(2, 50);
|
||||
arma::Row<size_t> states(50);
|
||||
|
||||
states[0] = 0;
|
||||
observations.col(0) = gmms[0].Random();
|
||||
|
||||
for (size_t i = 1; i < 50; ++i)
|
||||
{
|
||||
states[obs][0] = 0;
|
||||
observations[obs].col(0) = gmms[0].Random();
|
||||
double randValue = (double) rand() / (double) RAND_MAX;
|
||||
|
||||
for (size_t i = 1; i < 50; i++)
|
||||
{
|
||||
double randValue = (double) rand() / (double) RAND_MAX;
|
||||
if (randValue <= transMat(0, states[i - 1]))
|
||||
states[i] = 0;
|
||||
else
|
||||
states[i] = 1;
|
||||
|
||||
if (randValue <= transMat(0, states[obs][i - 1]))
|
||||
states[obs][i] = 0;
|
||||
else
|
||||
states[obs][i] = 1;
|
||||
|
||||
observations[obs].col(i) = gmms[states[obs][i]].Random();
|
||||
}
|
||||
observations.col(i) = gmms[states[i]].Random();
|
||||
}
|
||||
|
||||
// Initialize and train a GMM HMM model.
|
||||
HMMModel* h = new HMMModel(GaussianMixtureModelHMM);
|
||||
h->PerformAction<InitHMMModel, std::vector<arma::mat>>(&observations);
|
||||
h->PerformAction<TrainHMMModel, std::vector<arma::mat>>(&observations);
|
||||
*(h->GMMHMM()) = HMM<GMM>(2, GMM(2, 2));
|
||||
|
||||
// Manually set the components.
|
||||
h->GMMHMM()->Transition() = transMat;
|
||||
h->GMMHMM()->Emission() = gmms;
|
||||
|
||||
// Now that we have a trained HMM model, we can use it to predict the state
|
||||
// sequence for a given observation sequence - using the Viterbi algorithm.
|
||||
// Load the input model to be used for inference and the sequence over which
|
||||
// inference is to be performed.
|
||||
SetInputParam("input_model", h);
|
||||
SetInputParam("input", observations[0]);
|
||||
SetInputParam("input", observations);
|
||||
|
||||
// Call to hmm_viterbi_main.
|
||||
mlpackMain();
|
||||
@@ -172,7 +166,7 @@ BOOST_AUTO_TEST_CASE(HMMViterbiGMMHMMCheckDimensionsTest)
|
||||
// Output sequence length must be the same as input sequence length and
|
||||
// there should only be one row (since states are single dimensional values).
|
||||
BOOST_REQUIRE_EQUAL(out.n_rows, 1);
|
||||
BOOST_REQUIRE_EQUAL(out.n_cols, observations[0].n_cols);
|
||||
BOOST_REQUIRE_EQUAL(out.n_cols, observations.n_cols);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
Reference in New Issue
Block a user