public void LearnTest1() { // Create a Continuous density Hidden Markov Model Sequence Classifier // to detect a univariate sequence and the same sequence backwards. double[][] sequences = new double[][] { new double[] { 0,1,2,3,4 }, // This is the first sequence with label = 0 new double[] { 4,3,2,1,0 }, // This is the second sequence with label = 1 }; // Labels for the sequences int[] labels = { 0, 1 }; // Creates a sequence classifier containing 2 hidden Markov Models // with 2 states and an underlying Normal distribution as density. NormalDistribution density = new NormalDistribution(); var classifier = new HiddenMarkovClassifier<NormalDistribution, double>(2, new Ergodic(2), density); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning<NormalDistribution, double>(classifier) { // Train each model until the log-likelihood changes less than 0.001 Learner = modelIndex => new BaumWelchLearning<NormalDistribution, double>(classifier.Models[modelIndex]) { Tolerance = 0.0001, Iterations = 0 } }; // Train the sequence classifier using the algorithm teacher.Learn(sequences, labels); double logLikelihood = teacher.LogLikelihood; // Calculate the probability that the given // sequences originated from the model double likelihood1, likelihood2; // Try to classify the first sequence (output should be 0) int c1 = classifier.Decide(sequences[0]); likelihood1 = classifier.Probability(sequences[0]); // Try to classify the second sequence (output should be 1) int c2 = classifier.Decide(sequences[1]); likelihood2 = classifier.Probability(sequences[1]); Assert.AreEqual(0, c1); Assert.AreEqual(1, c2); Assert.AreEqual(-13.271981026832929, logLikelihood, 1e-10); Assert.AreEqual(0.99999791320102149, likelihood1, 1e-10); Assert.AreEqual(0.99999791320102149, likelihood2, 1e-10); }
private static double testThresholdModel(int[][] inputs, int[] outputs, HiddenMarkovClassifier<GeneralDiscreteDistribution, int> classifier, double likelihood) { var threshold = classifier.Threshold; Assert.AreEqual(classifier.Models[0].LogTransitions[0][0], threshold.LogTransitions[0][0], 1e-10); Assert.AreEqual(classifier.Models[0].LogTransitions[1][1], threshold.LogTransitions[1][1], 1e-10); Assert.AreEqual(classifier.Models[0].LogTransitions[2][2], threshold.LogTransitions[2][2], 1e-10); Assert.AreEqual(classifier.Models[1].LogTransitions[0][0], threshold.LogTransitions[3][3], 1e-10); Assert.AreEqual(classifier.Models[1].LogTransitions[1][1], threshold.LogTransitions[4][4], 1e-10); Assert.AreEqual(classifier.Models[1].LogTransitions[2][2], threshold.LogTransitions[5][5], 1e-10); for (int i = 0; i < 3; i++) for (int j = 3; j < 6; j++) Assert.AreEqual(Double.NegativeInfinity, threshold.LogTransitions[i][j]); for (int i = 3; i < 6; i++) for (int j = 0; j < 3; j++) Assert.AreEqual(Double.NegativeInfinity, threshold.LogTransitions[i][j]); Assert.IsFalse(Matrix.HasNaN(threshold.LogTransitions)); classifier.Sensitivity = 0.5; // Will assert the models have learned the sequences correctly. for (int i = 0; i < inputs.Length; i++) { int expected = outputs[i]; int actual = classifier.Decide(inputs[i]); likelihood = classifier.Probability(inputs[i]); Assert.AreEqual(expected, actual); } int[] r0 = new int[] { 1, 1, 0, 0, 2 }; double logRejection; int c = classifier.Decide(r0); logRejection = classifier.Probability(r0); Assert.AreEqual(-1, c); Assert.AreEqual(0.99993993054384978, logRejection); logRejection = threshold.LogLikelihood(r0); Assert.AreEqual(-5.6367018741984483, logRejection); Assert.IsFalse(double.IsNaN(logRejection)); threshold.Decode(r0, out logRejection); Assert.AreEqual(-8.1618027917853073, logRejection); Assert.IsFalse(double.IsNaN(logRejection)); foreach (var model in classifier.Models) { double[,] A = model.LogTransitions.ToMatrix(); for (int i = 0; i < A.GetLength(0); i++) { double[] row = A.Exp().GetRow(i); double sum = row.Sum(); Assert.AreEqual(1, sum, 1e-10); } } { double[,] A = classifier.Threshold.LogTransitions.ToMatrix(); for (int i = 0; i < A.GetLength(0); i++) { double[] row = A.GetRow(i); double sum = row.Exp().Sum(); Assert.AreEqual(1, sum, 1e-6); } } return likelihood; }
public void LearnTest7() { // Create a Continuous density Hidden Markov Model Sequence Classifier // to detect a multivariate sequence and the same sequence backwards. double[][][] sequences = new double[][][] { new double[][] { // This is the first sequence with label = 0 new double[] { 0, 1 }, new double[] { 1, 2 }, new double[] { 2, 3 }, new double[] { 3, 4 }, new double[] { 4, 5 }, }, new double[][] { // This is the second sequence with label = 1 new double[] { 4, 3 }, new double[] { 3, 2 }, new double[] { 2, 1 }, new double[] { 1, 0 }, new double[] { 0, -1 }, } }; // Labels for the sequences int[] labels = { 0, 1 }; var initialDensity = new MultivariateNormalDistribution(2); // Creates a sequence classifier containing 2 hidden Markov Models with 2 states // and an underlying multivariate mixture of Normal distributions as density. var classifier = new HiddenMarkovClassifier<MultivariateNormalDistribution, double[]>( classes: 2, topology: new Forward(2), initial: initialDensity); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning<MultivariateNormalDistribution, double[]>(classifier) { // Train each model until the log-likelihood changes less than 0.0001 Learner = modelIndex => new BaumWelchLearning<MultivariateNormalDistribution, double[], NormalOptions>(classifier.Models[modelIndex]) { Tolerance = 0.0001, Iterations = 0, FittingOptions = new NormalOptions() { Diagonal = true, // only diagonal covariance matrices Regularization = 1e-5 // avoid non-positive definite errors } } }; // Train the sequence classifier using the algorithm teacher.Learn(sequences, labels); double logLikelihood = teacher.LogLikelihood; // Calculate the probability that the given // sequences originated from the model double likelihood, likelihood2; int c1 = classifier.Decide(sequences[0]); likelihood = classifier.Probability(sequences[0]); // Try to classify the second sequence (output should be 1) int c2 = classifier.Decide(sequences[1]); likelihood2 = classifier.Probability(sequences[1]); Assert.AreEqual(0, c1); Assert.AreEqual(1, c2); Assert.AreEqual(-24.560663315259973, logLikelihood, 1e-10); Assert.AreEqual(0.99999999998805045, likelihood, 1e-10); Assert.AreEqual(0.99999999998805045, likelihood2, 1e-10); Assert.IsFalse(double.IsNaN(logLikelihood)); Assert.IsFalse(double.IsNaN(likelihood)); Assert.IsFalse(double.IsNaN(likelihood2)); }
public void LearnTest6() { // Create a Continuous density Hidden Markov Model Sequence Classifier // to detect a multivariate sequence and the same sequence backwards. double[][][] sequences = new double[][][] { new double[][] { // This is the first sequence with label = 0 new double[] { 0, 1 }, new double[] { 1, 2 }, new double[] { 2, 3 }, new double[] { 3, 4 }, new double[] { 4, 5 }, }, new double[][] { // This is the second sequence with label = 1 new double[] { 4, 3 }, new double[] { 3, 2 }, new double[] { 2, 1 }, new double[] { 1, 0 }, new double[] { 0, -1 }, } }; // Labels for the sequences int[] labels = { 0, 1 }; var density = new MultivariateNormalDistribution(2); try { new HiddenMarkovClassifier<MultivariateNormalDistribution>( 2, new Custom(new double[2, 2], new double[2]), density); Assert.Fail(); } catch (ArgumentException) { } var topology = new Custom( new[,] { { 1 / 2.0, 1 / 2.0 }, { 1 / 2.0, 1 / 2.0 } }, new[] { 1.0, 0.0 }); Array.Clear(topology.Initial, 0, topology.Initial.Length); Array.Clear(topology.Transitions, 0, topology.Transitions.Length); // Creates a sequence classifier containing 2 hidden Markov Models with 2 states // and an underlying multivariate mixture of Normal distributions as density. var classifier = new HiddenMarkovClassifier<MultivariateNormalDistribution, double[]>( 2, topology, density); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning<MultivariateNormalDistribution, double[]>(classifier) { // Train each model until the log-likelihood changes less than 0.0001 Learner = modelIndex => new BaumWelchLearning<MultivariateNormalDistribution, double[]>(classifier.Models[modelIndex]) { Tolerance = 0.0001, Iterations = 0, FittingOptions = new NormalOptions() { Diagonal = true } } }; // Train the sequence classifier using the algorithm teacher.Learn(sequences, labels); double logLikelihood = teacher.LogLikelihood; // Calculate the probability that the given // sequences originated from the model double response1, response2; // Try to classify the first sequence (output should be 0) int c1 = classifier.Decide(sequences[0]); response1 = classifier.Probability(sequences[0]); // Try to classify the second sequence (output should be 1) int c2 = classifier.Decide(sequences[1]); response2 = classifier.Probability(sequences[1]); Assert.AreEqual(double.NegativeInfinity, logLikelihood); Assert.AreEqual(0, response1); Assert.AreEqual(0, response2); }
public void LearnTest5() { // Create a Continuous density Hidden Markov Model Sequence Classifier // to detect a multivariate sequence and the same sequence backwards. double[][][] sequences = new double[][][] { new double[][] { // This is the first sequence with label = 0 new double[] { 0, 1 }, new double[] { 1, 2 }, new double[] { 2, 3 }, new double[] { 3, 4 }, new double[] { 4, 5 }, }, new double[][] { // This is the second sequence with label = 1 new double[] { 4, 3 }, new double[] { 3, 2 }, new double[] { 2, 1 }, new double[] { 1, 0 }, new double[] { 0, -1 }, } }; // Labels for the sequences int[] labels = { 0, 1 }; var density = new MultivariateNormalDistribution(2); // Creates a sequence classifier containing 2 hidden Markov Models with 2 states // and an underlying multivariate mixture of Normal distributions as density. var classifier = new HiddenMarkovClassifier<MultivariateNormalDistribution, double[]>( 2, new Ergodic(2), density); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning<MultivariateNormalDistribution, double[]>(classifier) { // Train each model until the log-likelihood changes less than 0.0001 Learner = modelIndex => new BaumWelchLearning<MultivariateNormalDistribution, double[]>(classifier.Models[modelIndex]) { Tolerance = 0.0001, Iterations = 0, FittingOptions = new NormalOptions() { Diagonal = true } } }; // Train the sequence classifier using the algorithm teacher.Learn(sequences, labels); double logLikelihood = teacher.LogLikelihood; // Calculate the probability that the given // sequences originated from the model double logLikelihood1, logLikelihood2; int c1, c2; // Try to classify the 1st sequence (output should be 0) logLikelihood1 = classifier.Probability(sequences[0], out c1); // Try to classify the 2nd sequence (output should be 1) logLikelihood2 = classifier.Probability(sequences[1], out c2); Assert.AreEqual(0, c1); Assert.AreEqual(1, c2); Assert.AreEqual(-24.560599651649841, logLikelihood, 1e-10); Assert.AreEqual(0.99999999998806466, logLikelihood1, 1e-10); Assert.AreEqual(0.99999999998806466, logLikelihood2, 1e-10); }
public void LearnTest4() { // Create a Continuous density Hidden Markov Model Sequence Classifier // to detect a multivariate sequence and the same sequence backwards. double[][][] sequences = new double[][][] { new double[][] { // This is the first sequence with label = 0 new double[] { 0 }, new double[] { 1 }, new double[] { 2 }, new double[] { 3 }, new double[] { 4 }, }, new double[][] { // This is the second sequence with label = 1 new double[] { 4 }, new double[] { 3 }, new double[] { 2 }, new double[] { 1 }, new double[] { 0 }, } }; // Labels for the sequences int[] labels = { 0, 1 }; // Create a mixture of two 1-dimensional normal distributions (by default, // initialized with zero mean and unit covariance matrices). var density = new MultivariateMixture<MultivariateNormalDistribution>( new MultivariateNormalDistribution(1), new MultivariateNormalDistribution(1)); // Creates a sequence classifier containing 2 hidden Markov Models with 2 states // and an underlying multivariate mixture of Normal distributions as density. var classifier = new HiddenMarkovClassifier<MultivariateMixture<MultivariateNormalDistribution>, double[]>( 2, new Ergodic(2), density); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning<MultivariateMixture<MultivariateNormalDistribution>, double[]>(classifier) { // Train each model until the log-likelihood changes less than 0.0001 Learner = modelIndex => new BaumWelchLearning<MultivariateMixture<MultivariateNormalDistribution>, double[]>(classifier.Models[modelIndex]) { Tolerance = 0.0001, Iterations = 0, } }; // Train the sequence classifier using the algorithm teacher.Learn(sequences, labels); double logLikelihood = teacher.LogLikelihood; // Calculate the probability that the given // sequences originated from the model double likelihood1, likelihood2; int c1, c2; // Try to classify the 1st sequence (output should be 0) likelihood1 = classifier.Probability(sequences[0], out c1); // Try to classify the 2nd sequence (output should be 1) likelihood2 = classifier.Probability(sequences[1], out c2); Assert.AreEqual(0, c1); Assert.AreEqual(1, c2); Assert.AreEqual(-13.271981026832933, logLikelihood, 1e-10); Assert.AreEqual(0.99999791320102149, likelihood1, 1e-10); Assert.AreEqual(0.99999791320102149, likelihood2, 1e-10); }