public void LearnTest6()
{
Accord.Math.Tools.SetupGenerator(0);
// We will try to create a Hidden Markov Model which
// can detect if a given sequence starts with a zero
// and has any number of ones after that.
//
int[][] sequences = new int[][]
{
new int[] { 0,1,1,1,1,0,1,1,1,1 },
new int[] { 0,1,1,1,0,1,1,1,1,1 },
new int[] { 0,1,1,1,1,1,1,1,1,1 },
new int[] { 0,1,1,1,1,1 },
new int[] { 0,1,1,1,1,1,1 },
new int[] { 0,1,1,1,1,1,1,1,1,1 },
new int[] { 0,1,1,1,1,1,1,1,1,1 },
};
// Creates a new Hidden Markov Model with 3 states for
// an output alphabet of two characters (zero and one)
//
HiddenMarkovModel hmm = new HiddenMarkovModel(new Forward(3), 2);
// Try to fit the model to the data until the difference in
// the average log-likelihood changes only by as little as 0.0001
//
var teacher = new ViterbiLearning(hmm) { Tolerance = 0.0001, Iterations = 0 };
double ll = teacher.Run(sequences);
// Calculate the probability that the given
// sequences originated from the model
double l1 = hmm.Evaluate(new int[] { 0, 1 }); // 0.613
double l2 = hmm.Evaluate(new int[] { 0, 1, 1, 1 }); // 0.500
// Sequences which do not start with zero have much lesser probability.
double l3 = hmm.Evaluate(new int[] { 1, 1 }); // 0.186
double l4 = hmm.Evaluate(new int[] { 1, 0, 0, 0 }); // 0.003
// Sequences which contains few errors have higher probability
// than the ones which do not start with zero. This shows some
// of the temporal elasticity and error tolerance of the HMMs.
//
double l5 = hmm.Evaluate(new int[] { 0, 1, 0, 1, 1, 1, 1, 1, 1 }); // 0.033
double l6 = hmm.Evaluate(new int[] { 0, 1, 1, 1, 1, 1, 1, 0, 1 }); // 0.026
double pl = System.Math.Exp(ll);
double p1 = System.Math.Exp(l1);
double p2 = System.Math.Exp(l2);
double p3 = System.Math.Exp(l3);
double p4 = System.Math.Exp(l4);
double p5 = System.Math.Exp(l5);
double p6 = System.Math.Exp(l6);
Assert.AreEqual(1.754393540912413, pl, 1e-6);
Assert.AreEqual(0.61368718756104801, p1, 1e-6);
Assert.AreEqual(0.50049466955818356, p2, 1e-6);
Assert.AreEqual(0.18643340385264684, p3, 1e-6);
Assert.AreEqual(0.00300262431355424, p4, 1e-6);
Assert.AreEqual(0.03338686211012481, p5, 1e-6);
Assert.AreEqual(0.02659161933179825, p6, 1e-6);
Assert.IsTrue(l1 > l3 && l1 > l4);
Assert.IsTrue(l2 > l3 && l2 > l4);
}