// Canvas events - obsolete private void inputCanvas_MouseUp(object sender, MouseEventArgs e) { double[][] input = Sequence.Preprocess(Get3DSequence()); if (input.Length < 5) { panelUserLabeling.Visible = false; panelClassification.Visible = false; return; } if (hmm == null && hcrf == null) { panelUserLabeling.Visible = true; panelClassification.Visible = false; } else { int index = (hcrf != null) ? hcrf.Compute(input) : hmm.Compute(input); string label = database.Classes[index]; //int[] path = ; lbHaveYouDrawn.Text = String.Format("Have you painted a {0}?", label); panelClassification.Visible = true; panelUserLabeling.Visible = false; } }
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>(2, new Ergodic(2), density); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning<NormalDistribution>(classifier, // Train each model until the log-likelihood changes less than 0.001 modelIndex => new BaumWelchLearning<NormalDistribution>(classifier.Models[modelIndex]) { Tolerance = 0.0001, Iterations = 0 } ); // Train the sequence classifier using the algorithm double logLikelihood = teacher.Run(sequences, labels); // 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.Compute(sequences[0], out likelihood1); // Try to classify the second sequence (output should be 1) int c2 = classifier.Compute(sequences[1], out likelihood2); 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); Assert.IsFalse(double.IsNaN(logLikelihood)); Assert.IsFalse(double.IsNaN(likelihood1)); Assert.IsFalse(double.IsNaN(likelihood2)); }
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>(2, new Ergodic(2), density); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning <NormalDistribution>(classifier, // Train each model until the log-likelihood changes less than 0.001 modelIndex => new BaumWelchLearning <NormalDistribution>(classifier.Models[modelIndex]) { Tolerance = 0.0001, Iterations = 0 } ); // Train the sequence classifier using the algorithm double logLikelihood = teacher.Run(sequences, labels); // 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.Compute(sequences[0], out likelihood1); // Try to classify the second sequence (output should be 1) int c2 = classifier.Compute(sequences[1], out likelihood2); 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); Assert.IsFalse(double.IsNaN(logLikelihood)); Assert.IsFalse(double.IsNaN(likelihood1)); Assert.IsFalse(double.IsNaN(likelihood2)); }
public static void LearnAndPredictContinuous() { // 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 new Continuous-density Hidden Markov Model Sequence Classifier // containing 2 hidden Markov Models with 2 states and an underlying Normal // distribution as the continuous probability density. Gaussian density = new Gaussian(); var classifier = new HiddenMarkovClassifier(2, new Ergodic(2), density); // Create a new learning algorithm to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning(classifier, // Train each model until the log-likelihood changes less than 0.001 modelIndex => new BaumWelchLearning(classifier.Models[modelIndex]) { Tolerance = 0.0001, Iterations = 0 } ); // Train the sequence classifier using the algorithm teacher.Run(sequences, labels); // Calculate the probability that the given // sequences originated from the model double likelihood; // Try to classify the first sequence (output should be 0) int c1 = classifier.Compute(sequences[0], out likelihood); Console.WriteLine("c1: {0}", c1); // Try to classify the second sequence (output should be 1) int c2 = classifier.Compute(sequences[1], out likelihood); Console.WriteLine("c2: {0}", c2); }
public int Classify(double[][][] trainDataSet, int[] trainLabels, double[][] testData, String[] classes) { int states = 5; int dimensionsOfFeatures = 12; int numberOfClasses = classes.Length; int iterations = 0; double tolerance = 0.01; HiddenMarkovClassifier <MultivariateNormalDistribution> hmm = new HiddenMarkovClassifier <MultivariateNormalDistribution> (numberOfClasses, new Forward(states), new MultivariateNormalDistribution(dimensionsOfFeatures), classes); // Create the learning algorithm for the ensemble classifier var teacher = new HiddenMarkovClassifierLearning <MultivariateNormalDistribution>(hmm, // Train each model using the selected convergence criteria i => new BaumWelchLearning <MultivariateNormalDistribution>(hmm.Models[i]) { Tolerance = tolerance, Iterations = iterations, FittingOptions = new NormalOptions() { Regularization = 1e-5 } } ); teacher.Empirical = true; teacher.Rejection = false; // Run the learning algorithm double error = teacher.Run(trainDataSet, trainLabels); int predictedResult = hmm.Compute(testData); return(predictedResult); }
public int Recognize(ISoundSignalReader signal, HiddenMarkovClassifier hmm, out string name, SignalVisitor voiceVisitor = null) { var featureUtility = new FeatureUtility(_engineParameters); signal.Reset(); var features = featureUtility.ExtractFeatures(signal, voiceVisitor).First(); var observations = _codeBook.Quantize(features.Select(item => new Point(item)).ToArray()); double[] responsabilities; var ret = hmm.Compute(observations, out responsabilities); var models = hmm.Models; var likelyHoodValue = Double.MinValue; name = string.Empty; foreach (var model in models) { var val = model.Evaluate(observations); if (val > likelyHoodValue) { likelyHoodValue = val; name = model.Tag.ToString(); } } return ret; }
private void classify(Canvas canvas, ZedGraphControl graph, System.Windows.Forms.Label output) { int[] sequence = GetFeatures(canvas.GetSequence()); if (classifier == null || sequence.Length <= 10) { output.Text = "-"; return; } double[] responses; int index = classifier.Compute(sequence, out responses); output.Text = (index == -1) ? "-" : classifier.Models[index].Tag as string; // Scale the responses to a [0,1] interval double max = responses.Max(); double min = responses.Min(); for (int i = 0; i < responses.Length; i++) { responses[i] = Accord.Math.Tools.Scale(min, max, 0, 1, responses[i]); } // Create the bar graph to show the relative responses CreateBarGraph(graph, responses); }
private void button1_Click(object sender, EventArgs e) { Point[] P = new Point[30000]; for (int i = 0; i < points.Count; i++) { P[i] = points[i]; richTextBox1.AppendText(P[i].ToString()); } double[][] input = Sequence.Preprocess(P); //if (input.Length < 5) //{ // panelUserLabeling.Visible = false; // panelClassification.Visible = false; // return; //} if (hmm == null && hcrf == null) { panelUserLabeling.Visible = true; panelClassification.Visible = false; } else { int index = (hcrf != null) ? hcrf.Compute(input) : hmm.Compute(input); string label = database.Classes[index]; lbHaveYouDrawn.Text = String.Format("Have you drawn a {0}?", label); panelClassification.Visible = true; panelUserLabeling.Visible = false; } Application.Idle -= addCoord; }
public void LearnTest() { // Declare some testing data int[][] inputs = new int[][] { new int[] { 0,1,1,0 }, // Class 0 new int[] { 0,0,1,0 }, // Class 0 new int[] { 0,1,1,1,0 }, // Class 0 new int[] { 0,1,0 }, // Class 0 new int[] { 1,0,0,1 }, // Class 1 new int[] { 1,1,0,1 }, // Class 1 new int[] { 1,0,0,0,1 }, // Class 1 new int[] { 1,0,1 }, // Class 1 }; int[] outputs = new int[] { 0,0,0,0, // First four sequences are of class 0 1,1,1,1, // Last four sequences are of class 1 }; // We are trying to predict two different classes int classes = 2; // Each sequence may have up to two symbols (0 or 1) int symbols = 2; // Nested models will have two states each int[] states = new int[] { 2, 2 }; // Creates a new Hidden Markov Model Classifier with the given parameters HiddenMarkovClassifier classifier = new HiddenMarkovClassifier(classes, states, symbols); // Create a new learning algorithm to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning(classifier, // Train each model until the log-likelihood changes less than 0.001 modelIndex => new BaumWelchLearning(classifier.Models[modelIndex]) { Tolerance = 0.001, Iterations = 0 } ); // Train the sequence classifier using the algorithm double likelihood = teacher.Run(inputs, outputs); // Will assert the models have learned the sequences correctly. for (int i = 0; i < inputs.Length; i++) { int expected = outputs[i]; int actual = classifier.Compute(inputs[i], out likelihood); Assert.AreEqual(expected, actual); } }
public void Run() { /*Initialize the model * Read more tut on Code project for better understanding * http://www.codeproject.com/Articles/541428/Sequence-Classifiers-in-Csharp-Part-I-Hidden-Marko?msg=5219822#xx5219822xx * states is parameters for running forward algo * intteration is parameters for iterations * tolerance is parameters for threshold * */ int states = 3; int iterations = 100; double tolerance = 0.01; bool rejection = false; string[] classes = ActivityIndex.Keys.ToArray(); ITopology foward = new Forward(states: 3); hmm = new HiddenMarkovClassifier(classes: 12, topology: foward, symbols: 5); // Create the learning algorithm for the ensemble classifier var teacher = new HiddenMarkovClassifierLearning(hmm, // Train each model using the selected convergence criteria i => new BaumWelchLearning(hmm.Models[i]) { Tolerance = tolerance, Iterations = iterations, } ); teacher.Empirical = true; teacher.Rejection = rejection; // Run the learning algorithm double error = teacher.Run(input, output); Console.WriteLine("Error: {0}", error); //Run the test and compare the real value using (StreamWriter writer = new StreamWriter("compare.txt")) { for (int i = 0; i < outpuTest.Length; ++i) { int val = hmm.Compute(inpuTest[i]); if (val != outpuTest[i]) { string labelTestRetrieve = ActivityIndex.FirstOrDefault(x => x.Value == val).Key; string labelTestActity = ActivityIndex.FirstOrDefault(x => x.Value == outpuTest[i]).Key; writer.WriteLine(outputTestLabelFolder[i] + " - " + "false, label test retrieve: " + labelTestRetrieve + " label activity: " + labelTestActity); } else { string labelTestActity = ActivityIndex.FirstOrDefault(x => x.Value == outpuTest[i]).Key; writer.WriteLine(outputTestLabelFolder[i] + " - " + "true, label activity: " + labelTestActity); } } } }
/// <summary> /// learn Hmm model for samples in given database using Baum Welch unsupervised learning algorithm /// then used the learned model to classify the training samples /// </summary> /// <param name="database"></param> /// <returns></returns> static HiddenMarkovClassifier <MultivariateNormalDistribution> learnHMM(Database database) { BindingList <Sequence> samples = database.Samples; BindingList <String> classes = database.Classes; double[][][] inputs = new double[samples.Count][][]; int[] outputs = new int[samples.Count]; for (int i = 0; i < inputs.Length; i++) { inputs[i] = samples[i].Input; outputs[i] = samples[i].Output; } int states = 5; int iterations = 0; double tolerance = 0.1; bool rejection = true; HiddenMarkovClassifier <MultivariateNormalDistribution> hmm = new HiddenMarkovClassifier <MultivariateNormalDistribution>(classes.Count, new Forward(states), new MultivariateNormalDistribution(2), classes.ToArray()); // Create the learning algorithm for the ensemble classifier var teacher = new HiddenMarkovClassifierLearning <MultivariateNormalDistribution>(hmm, // Train each model using the selected convergence criteria i => new BaumWelchLearning <MultivariateNormalDistribution>(hmm.Models[i]) { Tolerance = tolerance, Iterations = iterations, FittingOptions = new NormalOptions() { Regularization = 1e-5 } } ); teacher.Empirical = true; teacher.Rejection = rejection; // Run the learning algorithm double error = teacher.Run(inputs, outputs); // Classify all training instances foreach (var sample in database.Samples) { sample.RecognizedAs = hmm.Compute(sample.Input); } return(hmm); }
private static void check4(double[][][] words, HiddenMarkovClassifier <Independent> model, MarkovMultivariateFunction target, HiddenConditionalRandomField <double[]> hcrf) { double actual; double expected; foreach (var x in words) { for (int c = 0; c < model.Classes; c++) { for (int i = 0; i < model[c].States; i++) { // Check initial state transitions double xa = model.Priors[c]; double xb = Math.Exp(model[c].Probabilities[i]); double xc = model[c].Emissions[i].ProbabilityDensityFunction(x[0]); expected = xa * xb * xc; actual = Math.Exp(target.Factors[c].Compute(-1, i, x, 0, c)); Assert.IsTrue(expected.IsRelativelyEqual(actual, 1e-10)); Assert.IsFalse(double.IsNaN(actual)); } for (int t = 1; t < x.Length; t++) { // Check normal state transitions for (int i = 0; i < model[c].States; i++) { for (int j = 0; j < model[c].States; j++) { double xb = Math.Exp(model[c].Transitions[i, j]); double xc = model[c].Emissions[j].ProbabilityDensityFunction(x[t]); expected = xb * xc; actual = Math.Exp(target.Factors[c].Compute(i, j, x, t, c)); Assert.IsTrue(expected.IsRelativelyEqual(actual, 1e-10)); Assert.IsFalse(double.IsNaN(actual)); } } } actual = Math.Exp(model.LogLikelihood(x, c)); expected = Math.Exp(hcrf.LogLikelihood(x, c)); Assert.AreEqual(expected, actual, 1e-10); Assert.IsFalse(double.IsNaN(actual)); actual = model.Compute(x); expected = hcrf.Compute(x); Assert.AreEqual(expected, actual); Assert.IsFalse(double.IsNaN(actual)); } } }
public void ComputeTest() { HiddenMarkovClassifier hmm = DiscreteHiddenMarkovClassifierPotentialFunctionTest.CreateModel1(); // Declare some testing data int[][] inputs = new int[][] { new int[] { 0, 1, 1, 0 }, // Class 0 new int[] { 0, 0, 1, 0 }, // Class 0 new int[] { 0, 1, 1, 1, 0 }, // Class 0 new int[] { 0, 1, 0 }, // Class 0 new int[] { 1, 0, 0, 1 }, // Class 1 new int[] { 1, 1, 0, 1 }, // Class 1 new int[] { 1, 0, 0, 0, 1 }, // Class 1 new int[] { 1, 0, 1 }, // Class 1 }; int[] outputs = new int[] { 0, 0, 0, 0, // First four sequences are of class 0 1, 1, 1, 1, // Last four sequences are of class 1 }; var function = new MarkovDiscreteFunction(hmm); var target = new HiddenConditionalRandomField <int>(function); for (int i = 0; i < inputs.Length; i++) { int expected = hmm.Compute(inputs[i]); int actual = target.Compute(inputs[i]); double h0 = hmm.LogLikelihood(inputs[i], 0); double h1 = hmm.LogLikelihood(inputs[i], 1); double c0 = target.LogLikelihood(inputs[i], 0); double c1 = target.LogLikelihood(inputs[i], 1); Assert.AreEqual(expected, actual); Assert.AreEqual(h0, c0, 1e-10); Assert.AreEqual(h1, c1, 1e-10); Assert.IsFalse(double.IsNaN(c0)); Assert.IsFalse(double.IsNaN(c1)); } }
public double ComputeError(int[][] inputs, int[] outputs) { int errors = 0; Parallel.For(0, inputs.Length, i => { int expectedOutput = outputs[i]; int actualOutput = mClassifier.Compute(inputs[i]); if (expectedOutput != actualOutput) { Interlocked.Increment(ref errors); } }); return(errors / (double)inputs.Length); }
/// <summary> /// Tests the ensemble /// </summary> private void btnTest_Click(object sender, EventArgs e) { int rows = dgvTesting.Rows.Count - 1; // Gets the input sequences int[][] sequences = new int[rows][]; for (int i = 0; i < rows; i++) { DataGridViewRow row = dgvTesting.Rows[i]; string sequence = row.Cells["colTestSequence"].Value as string; String trueLabel = row.Cells["colTestTrueClass"].Value as string; double likelihood; int label = hmmc.Compute(decode(sequence), out likelihood); string assignedLabel = hmmc.Models[label].Tag as string; row.Cells["colTestAssignedClass"].Value = assignedLabel; row.Cells["colTestLikelihood"].Value = likelihood; row.Cells["colTestMatch"].Value = trueLabel == assignedLabel; } }
/// <summary> /// Tests the ensemble /// </summary> private void btnTest_Click(object sender, EventArgs e) { int rows = dgvTesting.Rows.Count - 1; int[] expected = new int[rows]; int[] actual = new int[rows]; // Gets the input sequences int[][] sequences = new int[rows][]; // For each row in the testing data for (int i = 0; i < rows; i++) { // Get the row at the current index DataGridViewRow row = dgvTesting.Rows[i]; // Get the training sequence to feed the model int[] sequence = decode(row.Cells["colTestSequence"].Value as string); // Get the label associated with this sequence string label = row.Cells["colTestTrueClass"].Value as string; expected[i] = hmmc.Models.Find(x => x.Tag as string == label)[0]; // Compute the model output for this sequence and // get its associated likelihood. double likelihood; actual[i] = hmmc.Compute(sequence, out likelihood); row.Cells["colTestAssignedClass"].Value = hmmc.Models[actual[i]].Tag as string; row.Cells["colTestLikelihood"].Value = likelihood; row.Cells["colTestMatch"].Value = actual[i] == expected[i]; } // Use confusion matrix to compute some performance metrics dgvPerformance.DataSource = new[] { new GeneralConfusionMatrix(hmmc.Classes, actual, expected) }; }
private void button1_Click(object sender, EventArgs e) { var classes = 4; var states = new[] { 1, 2, 2, 3 }; var cat = new[] { "ខ្ញុំ", "ទៅ", "ខ្លួន", "ក" }; //var cat = new[] { "A", "B" }; _hmmc = new HiddenMarkovClassifier(classes, states, 4, cat); // Train the ensemble var sequences = new[] { new[] { 1, 1, 1 }, new[] { 0, 2 }, new[] { 0, 1, 2 }, new[] { 1, 2 } }; var labels = new[] { 0, 1, 2, 3 }; var teacher = new HiddenMarkovClassifierLearning(_hmmc, i => new BaumWelchLearning(_hmmc.Models[i]) { Iterations = 0, Tolerance = 0.0001 } ); teacher.Run(sequences, labels); var m = _hmmc.Models; var test = new[] { 1, 2 }; double likelihood; var label = _hmmc.Compute(test, out likelihood); MessageBox.Show(_hmmc.Models[label].Tag.ToString() + " P =" + likelihood); }
private void button1_Click(object sender, EventArgs e) { var classes = 4; var states = new[]{1,2,2,3}; var cat = new[] {"ខ្ញុំ", "ទៅ", "ខ្លួន", "ក"}; //var cat = new[] { "A", "B" }; _hmmc = new HiddenMarkovClassifier(classes, states, 4, cat); // Train the ensemble var sequences = new[] { new[] {1, 1, 1}, new[] {0, 2}, new[] {0, 1, 2}, new[] {1, 2} }; var labels = new[] {0, 1, 2, 3}; var teacher = new HiddenMarkovClassifierLearning(_hmmc, i => new BaumWelchLearning(_hmmc.Models[i]) { Iterations = 0, Tolerance = 0.0001 } ); teacher.Run(sequences, labels); var m = _hmmc.Models; var test = new[]{1,2}; double likelihood; var label = _hmmc.Compute(test, out likelihood); MessageBox.Show(_hmmc.Models[label].Tag.ToString()+ " P =" + likelihood); }
public void SimpleGestureRecognitionTest() { // Let's say we would like to do a very simple mechanism for // gesture recognition. In this example, we will be trying to // create a classifier that can distinguish between the words // "hello", "car", and "wardrobe". // Let's say we decided to acquire some data, and we asked some // people to perform those words in front of a Kinect camera, and, // using Microsoft's SDK, we were able to captured the x and y // coordinates of each hand while the word was being performed. // Let's say we decided to represent our frames as: // // double[] frame = { leftHandX, leftHandY, rightHandX, rightHandY }; // // Since we captured words, this means we captured sequences of // frames as we described above. Let's write some of those as // rough examples to explain how gesture recognition can be done: double[][] hello = { new double[] { 1.0, 0.1, 0.0, 0.0 }, // let's say the word new double[] { 0.0, 1.0, 0.1, 0.1 }, // hello took 6 frames new double[] { 0.0, 1.0, 0.1, 0.1 }, // to be recorded. new double[] { 0.0, 0.0, 1.0, 0.0 }, new double[] { 0.0, 0.0, 1.0, 0.0 }, new double[] { 0.0, 0.0, 0.1, 1.1 }, }; double[][] car = { new double[] { 0.0, 0.0, 0.0, 1.0 }, // the car word new double[] { 0.1, 0.0, 1.0, 0.1 }, // took only 4. new double[] { 0.0, 0.0, 0.1, 0.0 }, new double[] { 1.0, 0.0, 0.0, 0.0 }, }; double[][] wardrobe = { new double[] { 0.0, 0.0, 1.0, 0.0 }, // same for the new double[] { 0.1, 0.0, 1.0, 0.1 }, // wardrobe word. new double[] { 0.0, 0.1, 1.0, 0.0 }, new double[] { 0.1, 0.0, 1.0, 0.1 }, }; // Here, please note that a real-world example would involve *lots* // of samples for each word. Here, we are considering just one from // each class which is clearly sub-optimal and should _never_ be done // on practice. For example purposes, however, please disregard this. // Those are the words we have in our vocabulary: // double[][][] words = { hello, car, wardrobe }; // Now, let's associate integer labels with them. This is needed // for the case where there are multiple samples for each word. // int[] labels = { 0, 1, 2 }; // We will create our classifiers assuming an independent // Gaussian distribution for each component in our feature // vectors (like assuming a Naive Bayes assumption). var initial = new Independent<NormalDistribution> ( new NormalDistribution(0, 1), new NormalDistribution(0, 1), new NormalDistribution(0, 1), new NormalDistribution(0, 1) ); // Now, we can proceed and create our classifier. // int numberOfWords = 3; // we are trying to distinguish between 3 words int numberOfStates = 5; // this value can be found by trial-and-error var hmm = new HiddenMarkovClassifier<Independent<NormalDistribution>> ( classes: numberOfWords, topology: new Forward(numberOfStates), // word classifiers should use a forward topology initial: initial ); // Create a new learning algorithm to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning<Independent<NormalDistribution>>(hmm, // Train each model until the log-likelihood changes less than 0.001 modelIndex => new BaumWelchLearning<Independent<NormalDistribution>>(hmm.Models[modelIndex]) { Tolerance = 0.001, Iterations = 100, // This is necessary so the code doesn't blow up when it realize // there is only one sample per word class. But this could also be // needed in normal situations as well. // FittingOptions = new IndependentOptions() { InnerOption = new NormalOptions() { Regularization = 1e-5 } } } ); // Finally, we can run the learning algorithm! double logLikelihood = teacher.Run(words, labels); // At this point, the classifier should be successfully // able to distinguish between our three word classes: // int tc1 = hmm.Compute(hello); int tc2 = hmm.Compute(car); int tc3 = hmm.Compute(wardrobe); Assert.AreEqual(0, tc1); Assert.AreEqual(1, tc2); Assert.AreEqual(2, tc3); // Now, we can use the Markov classifier to initialize a HCRF var function = new MarkovMultivariateFunction(hmm); var hcrf = new HiddenConditionalRandomField<double[]>(function); // We can check that both are equivalent, although they have // formulations that can be learned with different methods // for (int i = 0; i < words.Length; i++) { // Should be the same int expected = hmm.Compute(words[i]); int actual = hcrf.Compute(words[i]); // Should be the same double h0 = hmm.LogLikelihood(words[i], 0); double c0 = hcrf.LogLikelihood(words[i], 0); double h1 = hmm.LogLikelihood(words[i], 1); double c1 = hcrf.LogLikelihood(words[i], 1); double h2 = hmm.LogLikelihood(words[i], 2); double c2 = hcrf.LogLikelihood(words[i], 2); Assert.AreEqual(expected, actual); Assert.AreEqual(h0, c0, 1e-10); Assert.IsTrue(h1.IsRelativelyEqual(c1, 1e-10)); Assert.IsTrue(h2.IsRelativelyEqual(c2, 1e-10)); Assert.IsFalse(double.IsNaN(c0)); Assert.IsFalse(double.IsNaN(c1)); Assert.IsFalse(double.IsNaN(c2)); } // Now we can learn the HCRF using one of the best learning // algorithms available, Resilient Backpropagation learning: // Create a learning algorithm var rprop = new HiddenResilientGradientLearning<double[]>(hcrf) { Iterations = 50, Tolerance = 1e-5 }; // Run the algorithm and learn the models double error = rprop.Run(words, labels); // At this point, the HCRF should be successfully // able to distinguish between our three word classes: // int hc1 = hcrf.Compute(hello); int hc2 = hcrf.Compute(car); int hc3 = hcrf.Compute(wardrobe); Assert.AreEqual(0, hc1); Assert.AreEqual(1, hc2); Assert.AreEqual(2, hc3); }
private void btnLearnHMM_Click(object sender, EventArgs e) { if (gridSamples.Rows.Count == 0) { MessageBox.Show("Please load or insert some data first."); return; } BindingList<Sequence> samples = database.Samples; BindingList<String> classes = database.Classes; double[][][] inputs = new double[samples.Count][][]; int[] outputs = new int[samples.Count]; for (int i = 0; i < inputs.Length; i++) { inputs[i] = samples[i].Input; outputs[i] = samples[i].Output; } int states = 5; int iterations = 0; double tolerance = 0.01; bool rejection = false; hmm = new HiddenMarkovClassifier<MultivariateNormalDistribution>(classes.Count, new Forward(states), new MultivariateNormalDistribution(2), classes.ToArray()); // Create the learning algorithm for the ensemble classifier var teacher = new HiddenMarkovClassifierLearning<MultivariateNormalDistribution>(hmm, // Train each model using the selected convergence criteria i => new BaumWelchLearning<MultivariateNormalDistribution>(hmm.Models[i]) { Tolerance = tolerance, Iterations = iterations, FittingOptions = new NormalOptions() { Regularization = 1e-5 } } ); teacher.Empirical = true; teacher.Rejection = rejection; // Run the learning algorithm double error = teacher.Run(inputs, outputs); // Classify all training instances foreach (var sample in database.Samples) { sample.RecognizedAs = hmm.Compute(sample.Input); } foreach (DataGridViewRow row in gridSamples.Rows) { var sample = row.DataBoundItem as Sequence; row.DefaultCellStyle.BackColor = (sample.RecognizedAs == sample.Output) ? Color.LightGreen : Color.White; } btnLearnHCRF.Enabled = true; }
public void LearnTest2() { // Declare some testing data int[][] inputs = new int[][] { new int[] { 0,0,1,2 }, // Class 0 new int[] { 0,1,1,2 }, // Class 0 new int[] { 0,0,0,1,2 }, // Class 0 new int[] { 0,1,2,2,2 }, // Class 0 new int[] { 2,2,1,0 }, // Class 1 new int[] { 2,2,2,1,0 }, // Class 1 new int[] { 2,2,2,1,0 }, // Class 1 new int[] { 2,2,2,2,1 }, // Class 1 }; int[] outputs = new int[] { 0,0,0,0, // First four sequences are of class 0 1,1,1,1, // Last four sequences are of class 1 }; // We are trying to predict two different classes int classes = 2; // Each sequence may have up to 3 symbols (0,1,2) int symbols = 3; // Nested models will have 3 states each int[] states = new int[] { 3, 3 }; // Creates a new Hidden Markov Model Classifier with the given parameters HiddenMarkovClassifier classifier = new HiddenMarkovClassifier(classes, states, symbols); // Create a new learning algorithm to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning(classifier, // Train each model until the log-likelihood changes less than 0.001 modelIndex => new BaumWelchLearning(classifier.Models[modelIndex]) { Tolerance = 0.001, Iterations = 0 } ); // Enable support for sequence rejection teacher.Rejection = true; // Train the sequence classifier using the algorithm double likelihood = teacher.Run(inputs, outputs); // Will assert the models have learned the sequences correctly. for (int i = 0; i < inputs.Length; i++) { int expected = outputs[i]; int actual = classifier.Compute(inputs[i], out likelihood); Assert.AreEqual(expected, actual); } HiddenMarkovModel threshold = classifier.Threshold; Assert.AreEqual(6, threshold.States); Assert.AreEqual(classifier.Models[0].Transitions[0, 0], threshold.Transitions[0, 0], 1e-10); Assert.AreEqual(classifier.Models[0].Transitions[1, 1], threshold.Transitions[1, 1], 1e-10); Assert.AreEqual(classifier.Models[0].Transitions[2, 2], threshold.Transitions[2, 2], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[0, 0], threshold.Transitions[3, 3], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[1, 1], threshold.Transitions[4, 4], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[2, 2], threshold.Transitions[5, 5], 1e-10); Assert.IsFalse(Matrix.HasNaN(threshold.Transitions)); int[] r0 = new int[] { 1, 1, 0, 0, 2 }; double logRejection; int c = classifier.Compute(r0, out logRejection); Assert.AreEqual(-1, c); Assert.AreEqual(0.99569011079012049, logRejection); Assert.IsFalse(double.IsNaN(logRejection)); logRejection = threshold.Evaluate(r0); Assert.AreEqual(-6.7949285513628528, logRejection, 1e-10); Assert.IsFalse(double.IsNaN(logRejection)); threshold.Decode(r0, out logRejection); Assert.AreEqual(-8.902077561009957, logRejection, 1e-10); Assert.IsFalse(double.IsNaN(logRejection)); }
static void runDiscreteDensityHiddenMarkovClassifierLearningExample() { // Observation sequences should only contain symbols that are greater than or equal to 0, and lesser than the number of symbols. int[][] observationSequences = { // First class of sequences: starts and ends with zeros, ones in the middle. new[] { 0, 1, 1, 1, 0 }, new[] { 0, 0, 1, 1, 0, 0 }, new[] { 0, 1, 1, 1, 1, 0 }, // Second class of sequences: starts with twos and switches to ones until the end. new[] { 2, 2, 2, 2, 1, 1, 1, 1, 1 }, new[] { 2, 2, 1, 2, 1, 1, 1, 1, 1 }, new[] { 2, 2, 2, 2, 2, 1, 1, 1, 1 }, // Third class of sequences: can start with any symbols, but ends with three. new[] { 0, 0, 1, 1, 3, 3, 3, 3 }, new[] { 0, 0, 0, 3, 3, 3, 3 }, new[] { 1, 0, 1, 2, 2, 2, 3, 3 }, new[] { 1, 1, 2, 3, 3, 3, 3 }, new[] { 0, 0, 1, 1, 3, 3, 3, 3 }, new[] { 2, 2, 0, 3, 3, 3, 3 }, new[] { 1, 0, 1, 2, 3, 3, 3, 3 }, new[] { 1, 1, 2, 3, 3, 3, 3 }, }; // Consider their respective class labels. // Class labels have to be zero-based and successive integers. int[] classLabels = { 0, 0, 0, // Sequences 1-3 are from class 0. 1, 1, 1, // Sequences 4-6 are from class 1. 2, 2, 2, 2, 2, 2, 2, 2 // Sequences 7-14 are from class 2. }; // Use a single topology for all inner models. ITopology forward = new Forward(states: 3); // Create a hidden Markov classifier with the given topology. HiddenMarkovClassifier hmc = new HiddenMarkovClassifier(classes: 3, topology: forward, symbols: 4); // Create a algorithms to teach each of the inner models. var trainer = new HiddenMarkovClassifierLearning( hmc, // Specify individual training options for each inner model. modelIndex => new BaumWelchLearning(hmc.Models[modelIndex]) { Tolerance = 0.001, // iterate until log-likelihood changes less than 0.001. Iterations = 0 // don't place an upper limit on the number of iterations. } ); // Call its Run method to start learning. double averageLogLikelihood = trainer.Run(observationSequences, classLabels); Console.WriteLine("average log-likelihood for the observations = {0}", averageLogLikelihood); // Check the output classificaton label for some sequences. int y1 = hmc.Compute(new[] { 0, 1, 1, 1, 0 }); // output is y1 = 0. Console.WriteLine("output class = {0}", y1); int y2 = hmc.Compute(new[] { 0, 0, 1, 1, 0, 0 }); // output is y2 = 0. Console.WriteLine("output class = {0}", y2); int y3 = hmc.Compute(new[] { 2, 2, 2, 2, 1, 1 }); // output is y3 = 1. Console.WriteLine("output class = {0}", y3); int y4 = hmc.Compute(new[] { 2, 2, 1, 1 }); // output is y4 = 1. Console.WriteLine("output class = {0}", y4); int y5 = hmc.Compute(new[] { 0, 0, 1, 3, 3, 3 }); // output is y5 = 2. Console.WriteLine("output class = {0}", y4); int y6 = hmc.Compute(new[] { 2, 0, 2, 2, 3, 3 }); // output is y6 = 2. Console.WriteLine("output class = {0}", y6); }
public void SimpleGestureRecognitionTest() { // Let's say we would like to do a very simple mechanism for // gesture recognition. In this example, we will be trying to // create a classifier that can distinguish between the words // "hello", "car", and "wardrobe". // Let's say we decided to acquire some data, and we asked some // people to perform those words in front of a Kinect camera, and, // using Microsoft's SDK, we were able to captured the x and y // coordinates of each hand while the word was being performed. // Let's say we decided to represent our frames as: // // double[] frame = { leftHandX, leftHandY, rightHandX, rightHandY }; // // Since we captured words, this means we captured sequences of // frames as we described above. Let's write some of those as // rough examples to explain how gesture recognition can be done: double[][] hello = { new double[] { 1.0, 0.1, 0.0, 0.0 }, // let's say the word new double[] { 0.0, 1.0, 0.1, 0.1 }, // hello took 6 frames new double[] { 0.0, 1.0, 0.1, 0.1 }, // to be recorded. new double[] { 0.0, 0.0, 1.0, 0.0 }, new double[] { 0.0, 0.0, 1.0, 0.0 }, new double[] { 0.0, 0.0, 0.1, 1.1 }, }; double[][] car = { new double[] { 0.0, 0.0, 0.0, 1.0 }, // the car word new double[] { 0.1, 0.0, 1.0, 0.1 }, // took only 4. new double[] { 0.0, 0.0, 0.1, 0.0 }, new double[] { 1.0, 0.0, 0.0, 0.0 }, }; double[][] wardrobe = { new double[] { 0.0, 0.0, 1.0, 0.0 }, // same for the new double[] { 0.1, 0.0, 1.0, 0.1 }, // wardrobe word. new double[] { 0.0, 0.1, 1.0, 0.0 }, new double[] { 0.1, 0.0, 1.0, 0.1 }, }; // Here, please note that a real-world example would involve *lots* // of samples for each word. Here, we are considering just one from // each class which is clearly sub-optimal and should _never_ be done // on practice. For example purposes, however, please disregard this. // Those are the words we have in our vocabulary: // double[][][] words = { hello, car, wardrobe }; // Now, let's associate integer labels with them. This is needed // for the case where there are multiple samples for each word. // int[] labels = { 0, 1, 2 }; // We will create our classifiers assuming an independent // Gaussian distribution for each component in our feature // vectors (like assuming a Naive Bayes assumption). Independent initial = new Independent ( new NormalDistribution(0, 1), new NormalDistribution(0, 1), new NormalDistribution(0, 1), new NormalDistribution(0, 1) ); // Now, we can proceed and create our classifier. // int numberOfWords = 3; // we are trying to distinguish between 3 words int numberOfStates = 5; // this value can be found by trial-and-error var classifier = new HiddenMarkovClassifier <Independent> ( classes: numberOfWords, topology: new Forward(numberOfStates), // word classifiers should use a forward topology initial: initial ); // Create a new learning algorithm to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning <Independent>(classifier, // Train each model until the log-likelihood changes less than 0.001 modelIndex => new BaumWelchLearning <Independent>(classifier.Models[modelIndex]) { Tolerance = 0.001, Iterations = 100, // This is necessary so the code doesn't blow up when it realize // there is only one sample per word class. But this could also be // needed in normal situations as well. // FittingOptions = new IndependentOptions() { InnerOption = new NormalOptions() { Regularization = 1e-5 } } } ); // Finally, we can run the learning algorithm! double logLikelihood = teacher.Run(words, labels); // At this point, the classifier should be successfully // able to distinguish between our three word classes: // int c1 = classifier.Compute(hello); int c2 = classifier.Compute(car); int c3 = classifier.Compute(wardrobe); Assert.AreEqual(0, c1); Assert.AreEqual(1, c2); Assert.AreEqual(2, c3); }
private static void check4(double[][][] words, HiddenMarkovClassifier<Independent> model, MarkovMultivariateFunction target, HiddenConditionalRandomField<double[]> hcrf) { double actual; double expected; foreach (var x in words) { for (int c = 0; c < model.Classes; c++) { for (int i = 0; i < model[c].States; i++) { // Check initial state transitions double xa = model.Priors[c]; double xb = Math.Exp(model[c].Probabilities[i]); double xc = model[c].Emissions[i].ProbabilityDensityFunction(x[0]); expected = xa * xb * xc; actual = Math.Exp(target.Factors[c].Compute(-1, i, x, 0, c)); Assert.IsTrue(expected.IsRelativelyEqual(actual, 1e-10)); Assert.IsFalse(double.IsNaN(actual)); } for (int t = 1; t < x.Length; t++) { // Check normal state transitions for (int i = 0; i < model[c].States; i++) { for (int j = 0; j < model[c].States; j++) { double xb = Math.Exp(model[c].Transitions[i, j]); double xc = model[c].Emissions[j].ProbabilityDensityFunction(x[t]); expected = xb * xc; actual = Math.Exp(target.Factors[c].Compute(i, j, x, t, c)); Assert.IsTrue(expected.IsRelativelyEqual(actual, 1e-10)); Assert.IsFalse(double.IsNaN(actual)); } } } actual = Math.Exp(model.LogLikelihood(x, c)); expected = Math.Exp(hcrf.LogLikelihood(x, c)); Assert.AreEqual(expected, actual, 1e-10); Assert.IsFalse(double.IsNaN(actual)); actual = model.Compute(x); expected = hcrf.Compute(x); Assert.AreEqual(expected, actual); Assert.IsFalse(double.IsNaN(actual)); } } }
public void LearnTest2() { // Declare some testing data int[][] inputs = new int[][] { new int[] { 0,0,1,2 }, // Class 0 new int[] { 0,1,1,2 }, // Class 0 new int[] { 0,0,0,1,2 }, // Class 0 new int[] { 0,1,2,2,2 }, // Class 0 new int[] { 2,2,1,0 }, // Class 1 new int[] { 2,2,2,1,0 }, // Class 1 new int[] { 2,2,2,1,0 }, // Class 1 new int[] { 2,2,2,2,1 }, // Class 1 }; int[] outputs = new int[] { 0,0,0,0, // First four sequences are of class 0 1,1,1,1, // Last four sequences are of class 1 }; // We are trying to predict two different classes int classes = 2; // Each sequence may have up to 3 symbols (0,1,2) int symbols = 3; // Nested models will have 3 states each int[] states = new int[] { 3, 3 }; // Creates a new Hidden Markov Model Classifier with the given parameters HiddenMarkovClassifier classifier = new HiddenMarkovClassifier(classes, states, symbols); // Create a new learning algorithm to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning(classifier, // Train each model until the log-likelihood changes less than 0.001 modelIndex => new BaumWelchLearning(classifier.Models[modelIndex]) { Tolerance = 0.001, Iterations = 0 } ); // Enable support for sequence rejection teacher.Rejection = true; // Train the sequence classifier using the algorithm double likelihood = teacher.Run(inputs, outputs); HiddenMarkovModel threshold = classifier.Threshold; Assert.AreEqual(6, threshold.States); Assert.AreEqual(classifier.Models[0].Transitions[0, 0], threshold.Transitions[0, 0], 1e-10); Assert.AreEqual(classifier.Models[0].Transitions[1, 1], threshold.Transitions[1, 1], 1e-10); Assert.AreEqual(classifier.Models[0].Transitions[2, 2], threshold.Transitions[2, 2], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[0, 0], threshold.Transitions[3, 3], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[1, 1], threshold.Transitions[4, 4], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[2, 2], threshold.Transitions[5, 5], 1e-10); for (int i = 0; i < 3; i++) for (int j = 3; j < 6; j++) Assert.AreEqual(Double.NegativeInfinity, threshold.Transitions[i, j]); for (int i = 3; i < 6; i++) for (int j = 0; j < 3; j++) Assert.AreEqual(Double.NegativeInfinity, threshold.Transitions[i, j]); Assert.IsFalse(Matrix.HasNaN(threshold.Transitions)); 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.Compute(inputs[i], out likelihood); Assert.AreEqual(expected, actual); } int[] r0 = new int[] { 1, 1, 0, 0, 2 }; double logRejection; int c = classifier.Compute(r0, out logRejection); Assert.AreEqual(-1, c); Assert.AreEqual(0.99906957195279988, logRejection); Assert.IsFalse(double.IsNaN(logRejection)); logRejection = threshold.Evaluate(r0); Assert.AreEqual(-4.5653702970734793, logRejection, 1e-10); Assert.IsFalse(double.IsNaN(logRejection)); threshold.Decode(r0, out logRejection); Assert.AreEqual(-8.21169955167614, logRejection, 1e-10); Assert.IsFalse(double.IsNaN(logRejection)); foreach (var model in classifier.Models) { double[,] A = model.Transitions; 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.Transitions; 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); } } }
public static void LearnAndPredict() { // Suppose we would like to learn how to classify the // following set of sequences among three class labels: int[][] inputSequences = { // First class of sequences: starts and // ends with zeros, ones in the middle: new[] { 0, 1, 1, 1, 0 }, new[] { 0, 0, 1, 1,0, 0 }, new[] { 0, 1, 1, 1,1, 0 }, // Second class of sequences: starts with // twos and switches to ones until the end. new[] { 2, 2, 2, 2,1, 1, 1, 1, 1 }, new[] { 2, 2, 1, 2,1, 1, 1, 1, 1 }, new[] { 2, 2, 2, 2,2, 1, 1, 1, 1 }, // Third class of sequences: can start // with any symbols, but ends with three. new[] { 0, 0, 1, 1,3, 3, 3, 3 }, new[] { 0, 0, 0, 3,3, 3, 3 }, new[] { 1, 0, 1, 2,2, 2, 3, 3 }, new[] { 1, 1, 2, 3,3, 3, 3 }, new[] { 0, 0, 1, 1,3, 3, 3, 3 }, new[] { 2, 2, 0, 3,3, 3, 3 }, new[] { 1, 0, 1, 2,3, 3, 3, 3 }, new[] { 1, 1, 2, 3,3, 3, 3 }, }; // Now consider their respective class labels int[] outputLabels = { /* Sequences 1-3 are from class 0: */ 0, 0, 0, /* Sequences 4-6 are from class 1: */ 1, 1, 1, /* Sequences 7-14 are from class 2: */ 2, 2, 2, 2, 2, 2, 2, 2 }; // We will use a single topology for all inner models, but we // could also have explicit led different topologies for each: ITopology forward = new Forward(state_count: 3); // Now we create a hidden Markov classifier with the given topology HiddenMarkovClassifier classifier = new HiddenMarkovClassifier(class_count: 3, topology: forward, symbol_count: 4); // And create a algorithms to teach each of the inner models var teacher = new HiddenMarkovClassifierLearning(classifier, // We can specify individual training options for each inner model: modelIndex => new BaumWelchLearning(classifier.Models[modelIndex]) { Tolerance = 0.001, // iterate until log-likelihood changes less than 0.001 Iterations = 0 // don't place an upper limit on the number of iterations }); // Then let's call its Run method to start learning double error = teacher.Run(inputSequences, outputLabels); // After training has finished, we can check the // output classificaton label for some sequences. int y1 = classifier.Compute(new[] { 0, 1, 1, 1, 0 }); // output is y1 = 0 int y2 = classifier.Compute(new[] { 0, 0, 1, 1, 0, 0 }); // output is y1 = 0 int y3 = classifier.Compute(new[] { 2, 2, 2, 2, 1, 1 }); // output is y2 = 1 int y4 = classifier.Compute(new[] { 2, 2, 1, 1 }); // output is y2 = 1 int y5 = classifier.Compute(new[] { 0, 0, 1, 3, 3, 3 }); // output is y3 = 2 int y6 = classifier.Compute(new[] { 2, 0, 2, 2, 3, 3 }); // output is y3 = 2 Console.WriteLine("y1 = {0}", y1); Console.WriteLine("y2 = {0}", y2); Console.WriteLine("y3 = {0}", y3); Console.WriteLine("y4 = {0}", y4); Console.WriteLine("y5 = {0}", y5); Console.WriteLine("y6 = {0}", y6); }
private void btnTrain_Click(object sender, EventArgs e) { if (dataGridView1.Rows.Count == 0) { MessageBox.Show("Please load or insert some data first."); return; } int states = (int)numStates.Value; int iterations = (int)numIterations.Value; double tolerance = (double)numConvergence.Value; if (rbStopIterations.Checked) tolerance = 0.0; if (rbStopConvergence.Checked) iterations = 0; // Retrieve the training data from the data grid view int rows = dataGridView1.Rows.Count; int[] outputs = new int[rows]; var sequences = new int[rows][]; for (int i = 0; i < rows; i++) { outputs[i] = (int)dataGridView1.Rows[i].Cells["colLabel"].Value - 1; sequences[i] = GetFeatures((double[][])dataGridView1.Rows[i].Tag); } int classes = outputs.Distinct().Count(); string[] labels = new string[classes]; for (int i = 0; i < labels.Length; i++) labels[i] = (i+1).ToString(); // Create a sequence classifier for 3 classes classifier = new HiddenMarkovClassifier(labels.Length, new Forward(states), symbols: 20, names: labels); // Create the learning algorithm for the ensemble classifier var teacher = new HiddenMarkovClassifierLearning(classifier, // Train each model using the selected convergence criteria i => new BaumWelchLearning(classifier.Models[i]) { Tolerance = tolerance, Iterations = iterations, } ); // Create and use a rejection threshold model teacher.Rejection = cbRejection.Checked; teacher.Empirical = true; teacher.Smoothing = (double)numSmoothing.Value; // Run the learning algorithm teacher.Run(sequences, outputs); double error = classifier.LogLikelihood(sequences, outputs); int hits = 0; toolStripProgressBar1.Visible = true; toolStripProgressBar1.Value = 0; toolStripProgressBar1.Step = 1; toolStripProgressBar1.Maximum = dataGridView1.Rows.Count; for (int i = 0; i < rows; i++) { double likelihood; int index = classifier.Compute(sequences[i], out likelihood); DataGridViewRow row = dataGridView1.Rows[i]; if (index == -1) { row.Cells["colClassification"].Value = String.Empty; } else { row.Cells["colClassification"].Value = classifier.Models[index].Tag; } int expected = (int)row.Cells["colLabel"].Value; if (expected == index + 1) { row.Cells[0].Style.BackColor = Color.LightGreen; row.Cells[1].Style.BackColor = Color.LightGreen; row.Cells[2].Style.BackColor = Color.LightGreen; hits++; } else { row.Cells[0].Style.BackColor = Color.White; row.Cells[1].Style.BackColor = Color.White; row.Cells[2].Style.BackColor = Color.White; } toolStripProgressBar1.PerformStep(); } dgvModels.DataSource = classifier.Models; toolStripProgressBar1.Visible = false; toolStripStatusLabel1.Text = String.Format("Training complete. Hits: {0}/{1} ({2:0%})", hits, dataGridView1.Rows.Count, (double)hits / dataGridView1.Rows.Count); }
private static double testThresholdModel(double[][] inputs, int[] outputs, HiddenMarkovClassifier<GeneralDiscreteDistribution> classifier, double likelihood) { var threshold = classifier.Threshold; Assert.AreEqual(classifier.Models[0].Transitions[0, 0], threshold.Transitions[0, 0], 1e-10); Assert.AreEqual(classifier.Models[0].Transitions[1, 1], threshold.Transitions[1, 1], 1e-10); Assert.AreEqual(classifier.Models[0].Transitions[2, 2], threshold.Transitions[2, 2], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[0, 0], threshold.Transitions[3, 3], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[1, 1], threshold.Transitions[4, 4], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[2, 2], threshold.Transitions[5, 5], 1e-10); for (int i = 0; i < 3; i++) for (int j = 3; j < 6; j++) Assert.AreEqual(Double.NegativeInfinity, threshold.Transitions[i, j]); for (int i = 3; i < 6; i++) for (int j = 0; j < 3; j++) Assert.AreEqual(Double.NegativeInfinity, threshold.Transitions[i, j]); Assert.IsFalse(Matrix.HasNaN(threshold.Transitions)); 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.Compute(inputs[i], out likelihood); Assert.AreEqual(expected, actual); } double[] r0 = new double[] { 1, 1, 0, 0, 2 }; double logRejection; int c = classifier.Compute(r0, out logRejection); Assert.AreEqual(-1, c); Assert.AreEqual(0.99993993054384978, logRejection); Assert.IsFalse(double.IsNaN(logRejection)); logRejection = threshold.Evaluate(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.Transitions; 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.Transitions; 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; }
private static double testThresholdModel(int[][] inputs, int[] outputs, HiddenMarkovClassifier classifier, double likelihood) { HiddenMarkovModel threshold = classifier.Threshold; Assert.AreEqual(6, threshold.States); Assert.AreEqual(classifier.Models[0].Transitions[0, 0], threshold.Transitions[0, 0], 1e-10); Assert.AreEqual(classifier.Models[0].Transitions[1, 1], threshold.Transitions[1, 1], 1e-10); Assert.AreEqual(classifier.Models[0].Transitions[2, 2], threshold.Transitions[2, 2], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[0, 0], threshold.Transitions[3, 3], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[1, 1], threshold.Transitions[4, 4], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[2, 2], threshold.Transitions[5, 5], 1e-10); for (int i = 0; i < 3; i++) for (int j = 3; j < 6; j++) Assert.AreEqual(Double.NegativeInfinity, threshold.Transitions[i, j]); for (int i = 3; i < 6; i++) for (int j = 0; j < 3; j++) Assert.AreEqual(Double.NegativeInfinity, threshold.Transitions[i, j]); Assert.IsFalse(Matrix.HasNaN(threshold.Transitions)); 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.Compute(inputs[i], out likelihood); Assert.AreEqual(expected, actual); } int[] r0 = new int[] { 1, 1, 0, 0, 2 }; double logRejection; int c = classifier.Compute(r0, out logRejection); Assert.AreEqual(-1, c); Assert.AreEqual(0.99994164708402866, logRejection); Assert.IsFalse(double.IsNaN(logRejection)); logRejection = threshold.Evaluate(r0); Assert.AreEqual(-5.6077079936209504, logRejection, 1e-10); Assert.IsFalse(double.IsNaN(logRejection)); threshold.Decode(r0, out logRejection); Assert.AreEqual(-9.3103554170761686, logRejection, 1e-10); Assert.IsFalse(double.IsNaN(logRejection)); foreach (var model in classifier.Models) { double[,] A = model.Transitions; 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.Transitions; 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 LearnTest2() { // Declare some testing data int[][] inputs = new int[][] { new int[] { 0, 0, 1, 2 }, // Class 0 new int[] { 0, 1, 1, 2 }, // Class 0 new int[] { 0, 0, 0, 1, 2 }, // Class 0 new int[] { 0, 1, 2, 2, 2 }, // Class 0 new int[] { 2, 2, 1, 0 }, // Class 1 new int[] { 2, 2, 2, 1, 0 }, // Class 1 new int[] { 2, 2, 2, 1, 0 }, // Class 1 new int[] { 2, 2, 2, 2, 1 }, // Class 1 }; int[] outputs = new int[] { 0, 0, 0, 0, // First four sequences are of class 0 1, 1, 1, 1, // Last four sequences are of class 1 }; // We are trying to predict two different classes int classes = 2; // Each sequence may have up to 3 symbols (0,1,2) int symbols = 3; // Nested models will have 3 states each int[] states = new int[] { 3, 3 }; // Creates a new Hidden Markov Model Classifier with the given parameters HiddenMarkovClassifier classifier = new HiddenMarkovClassifier(classes, states, symbols); // Create a new learning algorithm to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning(classifier, // Train each model until the log-likelihood changes less than 0.001 modelIndex => new BaumWelchLearning(classifier.Models[modelIndex]) { Tolerance = 0.001, Iterations = 0 } ); // Enable support for sequence rejection teacher.Rejection = true; // Train the sequence classifier using the algorithm double likelihood = teacher.Run(inputs, outputs); // Will assert the models have learned the sequences correctly. for (int i = 0; i < inputs.Length; i++) { int expected = outputs[i]; int actual = classifier.Compute(inputs[i], out likelihood); Assert.AreEqual(expected, actual); } HiddenMarkovModel threshold = classifier.Threshold; Assert.AreEqual(6, threshold.States); Assert.AreEqual(classifier.Models[0].Transitions[0, 0], threshold.Transitions[0, 0], 1e-10); Assert.AreEqual(classifier.Models[0].Transitions[1, 1], threshold.Transitions[1, 1], 1e-10); Assert.AreEqual(classifier.Models[0].Transitions[2, 2], threshold.Transitions[2, 2], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[0, 0], threshold.Transitions[3, 3], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[1, 1], threshold.Transitions[4, 4], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[2, 2], threshold.Transitions[5, 5], 1e-10); Assert.IsFalse(Matrix.HasNaN(threshold.Transitions)); int[] r0 = new int[] { 1, 1, 0, 0, 2 }; double logRejection; int c = classifier.Compute(r0, out logRejection); Assert.AreEqual(-1, c); Assert.AreEqual(0.99569011079012049, logRejection); Assert.IsFalse(double.IsNaN(logRejection)); logRejection = threshold.Evaluate(r0); Assert.AreEqual(-6.7949285513628528, logRejection, 1e-10); Assert.IsFalse(double.IsNaN(logRejection)); threshold.Decode(r0, out logRejection); Assert.AreEqual(-8.902077561009957, logRejection, 1e-10); Assert.IsFalse(double.IsNaN(logRejection)); }
private void MainForm_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { if (e.Button == MouseButtons.Left) { if (_isDown) { if (_points.Count >= 2) { PointR p = (PointR)_points[_points.Count - 1]; //_directionalCodewords = "" + getDirectionalCodewords(e.X, e.Y, p.X, p.Y); _directionalCodewordsQueue.Enqueue(getDirectionalCodewords(e.X, e.Y, p.X, p.Y)); if (_directionalCodewordsQueue.Count > _maxCount) { _directionalCodewordsQueue.Dequeue(); } } _points.Add(new PointR(e.X, e.Y, Environment.TickCount)); //info = info + "a"; if (_hmmc != null && _directionalCodewordsQueue.Count > 1 && !_recording) // not recording, so testing { Queue <int> directionalCodewordsQueueTemp = _directionalCodewordsQueue; while (directionalCodewordsQueueTemp.Count > 40) { //lblResult.Text = "Recognizing..."; _info = null; _info = _info + _rec.encode(_directionalCodewordsQueue.ToArray()) + "\n"; //int[] observations = _rec.decode(_directionalCodewords); int[] observations = directionalCodewordsQueueTemp.ToArray(); _info = _info + _hmmc.Compute(observations) + "\n"; string gestureName = (string)_hmms[0].Tag; double probTemp = 0; _hmmc[0].Decode(observations, out probTemp); //double probTemp = hmms[0].Evaluate(observations); foreach (HiddenMarkovModel hmm in _hmms) { //double prob = hmm.Evaluate(observations); double prob = 0; int[] viterbipath = hmm.Decode(observations, out prob); if (prob > probTemp) { gestureName = (string)hmm.Tag; probTemp = prob; } //info = info + hmm.Tag + "\t" + hmm.Evaluate(observations) + "\t"; _info = _info + hmm.Tag + "\t" + prob + "\t"; // = hmm.Decode(observations); foreach (int state in viterbipath) { _info = _info + state + " "; } _info = _info + "\n"; } double probTM = 0; int[] viterbipathTM = _hmmc.Threshold.Decode(observations, out probTM); _info = _info + "ThresholdModel\t" + probTM + "\t"; //hmmc.Threshold.Decode(observations); foreach (int state in viterbipathTM) { _info = _info + state + " "; } _info = _info + "\n"; if (probTM > probTemp) { gestureName = "Threshold"; _info = _info + "\n\n" + gestureName; } else { _info = _info + "\n\n" + gestureName; _directionalCodewordsQueue.Clear(); break; } for (int loop = 0; loop < 10; loop++) { directionalCodewordsQueueTemp.Dequeue(); } } } Invalidate(); } } //Invalidate(new Rectangle(e.X - 2, e.Y - 2, 4, 4)); }
private void btnLearnHMM_Click(object sender, EventArgs e) { if (gridSamples.Rows.Count == 0) { MessageBox.Show("Please load or insert some data first."); return; } BindingList <Sequence> samples = database.Samples; BindingList <String> classes = database.Classes; double[][][] inputs = new double[samples.Count][][]; int[] outputs = new int[samples.Count]; for (int i = 0; i < inputs.Length; i++) { inputs[i] = samples[i].Input; outputs[i] = samples[i].Output; } int states = 5; int iterations = 0; double tolerance = 0.01; bool rejection = false; hmm = new HiddenMarkovClassifier <MultivariateNormalDistribution>(classes.Count, new Forward(states), new MultivariateNormalDistribution(2), classes.ToArray()); // Create the learning algorithm for the ensemble classifier var teacher = new HiddenMarkovClassifierLearning <MultivariateNormalDistribution>(hmm, // Train each model using the selected convergence criteria i => new BaumWelchLearning <MultivariateNormalDistribution>(hmm.Models[i]) { Tolerance = tolerance, Iterations = iterations, FittingOptions = new NormalOptions() { Regularization = 1e-5 } } ); teacher.Empirical = true; teacher.Rejection = rejection; // Run the learning algorithm double error = teacher.Run(inputs, outputs); // Classify all training instances foreach (var sample in database.Samples) { sample.RecognizedAs = hmm.Compute(sample.Input); } foreach (DataGridViewRow row in gridSamples.Rows) { var sample = row.DataBoundItem as Sequence; row.DefaultCellStyle.BackColor = (sample.RecognizedAs == sample.Output) ? Color.LightGreen : Color.White; } btnLearnHCRF.Enabled = true; hcrf = null; }
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); // 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>( 2, new Custom(new double[2, 2], new double[2]), density); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning <MultivariateNormalDistribution>( classifier, // Train each model until the log-likelihood changes less than 0.0001 modelIndex => new BaumWelchLearning <MultivariateNormalDistribution>( classifier.Models[modelIndex]) { Tolerance = 0.0001, Iterations = 0, FittingOptions = new NormalOptions() { Diagonal = true } } ); // Train the sequence classifier using the algorithm double logLikelihood = teacher.Run(sequences, labels); // Calculate the probability that the given // sequences originated from the model double response1, response2; // Try to classify the 1st sequence (output should be 0) int c1 = classifier.Compute(sequences[0], out response1); // Try to classify the 2nd sequence (output should be 1) int c2 = classifier.Compute(sequences[1], out response2); Assert.AreEqual(double.NegativeInfinity, logLikelihood); Assert.AreEqual(0, response1); Assert.AreEqual(0, response2); Assert.IsFalse(double.IsNaN(logLikelihood)); Assert.IsFalse(double.IsNaN(response1)); Assert.IsFalse(double.IsNaN(response2)); }
private static double testThresholdModel(int[][] inputs, int[] outputs, HiddenMarkovClassifier classifier, double likelihood) { HiddenMarkovModel threshold = classifier.Threshold; Assert.AreEqual(6, threshold.States); Assert.AreEqual(classifier.Models[0].Transitions[0, 0], threshold.Transitions[0, 0], 1e-10); Assert.AreEqual(classifier.Models[0].Transitions[1, 1], threshold.Transitions[1, 1], 1e-10); Assert.AreEqual(classifier.Models[0].Transitions[2, 2], threshold.Transitions[2, 2], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[0, 0], threshold.Transitions[3, 3], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[1, 1], threshold.Transitions[4, 4], 1e-10); Assert.AreEqual(classifier.Models[1].Transitions[2, 2], threshold.Transitions[5, 5], 1e-10); for (int i = 0; i < 3; i++) { for (int j = 3; j < 6; j++) { Assert.AreEqual(Double.NegativeInfinity, threshold.Transitions[i, j]); } } for (int i = 3; i < 6; i++) { for (int j = 0; j < 3; j++) { Assert.AreEqual(Double.NegativeInfinity, threshold.Transitions[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.Compute(inputs[i], out likelihood); Assert.AreEqual(expected, actual); } int[] r0 = new int[] { 1, 1, 0, 0, 2 }; double logRejection; int c = classifier.Compute(r0, out logRejection); Assert.AreEqual(-1, c); Assert.AreEqual(0.99996241769427985, logRejection, 1e-10); logRejection = threshold.Evaluate(r0); Assert.AreEqual(-5.5993214137039073, logRejection, 1e-10); threshold.Decode(r0, out logRejection); Assert.AreEqual(-9.31035541707617, logRejection, 1e-10); foreach (var model in classifier.Models) { double[,] A = model.Transitions; 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.Transitions; 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>( classes: 2, topology: new Forward(2), initial: initialDensity); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning<MultivariateNormalDistribution>( classifier, // Train each model until the log-likelihood changes less than 0.0001 modelIndex => new BaumWelchLearning<MultivariateNormalDistribution>( 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 double logLikelihood = teacher.Run(sequences, labels); // Calculate the probability that the given // sequences originated from the model double likelihood, likelihood2; // Try to classify the 1st sequence (output should be 0) int c1 = classifier.Compute(sequences[0], out likelihood); // Try to classify the 2nd sequence (output should be 1) int c2 = classifier.Compute(sequences[1], out likelihood2); 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 SimpleGestureRecognitionTest() { // Let's say we would like to do a very simple mechanism for // gesture recognition. In this example, we will be trying to // create a classifier that can distinguish between the words // "hello", "car", and "wardrobe". // Let's say we decided to acquire some data, and we asked some // people to perform those words in front of a Kinect camera, and, // using Microsoft's SDK, we were able to captured the x and y // coordinates of each hand while the word was being performed. // Let's say we decided to represent our frames as: // // double[] frame = { leftHandX, leftHandY, rightHandX, rightHandY }; // // Since we captured words, this means we captured sequences of // frames as we described above. Let's write some of those as // rough examples to explain how gesture recognition can be done: double[][] hello = { new double[] { 1.0, 0.1, 0.0, 0.0 }, // let's say the word new double[] { 0.0, 1.0, 0.1, 0.1 }, // hello took 6 frames new double[] { 0.0, 1.0, 0.1, 0.1 }, // to be recorded. new double[] { 0.0, 0.0, 1.0, 0.0 }, new double[] { 0.0, 0.0, 1.0, 0.0 }, new double[] { 0.0, 0.0, 0.1, 1.1 }, }; double[][] car = { new double[] { 0.0, 0.0, 0.0, 1.0 }, // the car word new double[] { 0.1, 0.0, 1.0, 0.1 }, // took only 4. new double[] { 0.0, 0.0, 0.1, 0.0 }, new double[] { 1.0, 0.0, 0.0, 0.0 }, }; double[][] wardrobe = { new double[] { 0.0, 0.0, 1.0, 0.0 }, // same for the new double[] { 0.1, 0.0, 1.0, 0.1 }, // wardrobe word. new double[] { 0.0, 0.1, 1.0, 0.0 }, new double[] { 0.1, 0.0, 1.0, 0.1 }, }; // Here, please note that a real-world example would involve *lots* // of samples for each word. Here, we are considering just one from // each class which is clearly sub-optimal and should _never_ be done // on practice. For example purposes, however, please disregard this. // Those are the words we have in our vocabulary: // double[][][] words = { hello, car, wardrobe }; // Now, let's associate integer labels with them. This is needed // for the case where there are multiple samples for each word. // int[] labels = { 0, 1, 2 }; // We will create our classifiers assuming an independent // Gaussian distribution for each component in our feature // vectors (like assuming a Naive Bayes assumption). Independent initial = new Independent ( new NormalDistribution(0, 1), new NormalDistribution(0, 1), new NormalDistribution(0, 1), new NormalDistribution(0, 1) ); // Now, we can proceed and create our classifier. // int numberOfWords = 3; // we are trying to distinguish between 3 words int numberOfStates = 5; // this value can be found by trial-and-error var classifier = new HiddenMarkovClassifier<Independent> ( classes: numberOfWords, topology: new Forward(numberOfStates), // word classifiers should use a forward topology initial: initial ); // Create a new learning algorithm to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning<Independent>(classifier, // Train each model until the log-likelihood changes less than 0.001 modelIndex => new BaumWelchLearning<Independent>(classifier.Models[modelIndex]) { Tolerance = 0.001, Iterations = 100, // This is necessary so the code doesn't blow up when it realize // there is only one sample per word class. But this could also be // needed in normal situations as well. // FittingOptions = new IndependentOptions() { InnerOption = new NormalOptions() { Regularization = 1e-5 } } } ); // Finally, we can run the learning algorithm! double logLikelihood = teacher.Run(words, labels); // At this point, the classifier should be successfully // able to distinguish between our three word classes: // int c1 = classifier.Compute(hello); int c2 = classifier.Compute(car); int c3 = classifier.Compute(wardrobe); Assert.AreEqual(0, c1); Assert.AreEqual(1, c2); Assert.AreEqual(2, c3); }
public void LearnTest9() { double[][][] inputs = large_gestures; int[] outputs = large_outputs; int states = 5; int iterations = 100; double tolerance = 0.01; bool rejection = true; double sensitivity = 1E-85; int dimension = inputs[0][0].Length; var hmm = new HiddenMarkovClassifier<MultivariateNormalDistribution>(2, new Forward(states), new MultivariateNormalDistribution(dimension)); // Create the learning algorithm for the ensemble classifier var teacher = new HiddenMarkovClassifierLearning<MultivariateNormalDistribution>(hmm, // Train each model using the selected convergence criteria i => new BaumWelchLearning<MultivariateNormalDistribution>(hmm.Models[i]) { Tolerance = tolerance, Iterations = iterations, FittingOptions = new NormalOptions() { Regularization = 1e-5 } } ); teacher.Empirical = true; teacher.Rejection = rejection; // Run the learning algorithm double logLikelihood = teacher.Run(inputs, outputs); hmm.Sensitivity = sensitivity; for (int i = 0; i < large_gestures.Length; i++) { int actual = hmm.Compute(large_gestures[i]); int expected = large_outputs[i]; Assert.AreEqual(expected,actual); } }
static void runDiscreteDensityHiddenMarkovClassifierLearningExample() { // Observation sequences should only contain symbols that are greater than or equal to 0, and lesser than the number of symbols. int[][] observationSequences = { // First class of sequences: starts and ends with zeros, ones in the middle. new[] { 0, 1, 1, 1, 0 }, new[] { 0, 0, 1, 1,0, 0 }, new[] { 0, 1, 1, 1,1, 0 }, // Second class of sequences: starts with twos and switches to ones until the end. new[] { 2, 2, 2, 2,1, 1, 1, 1, 1 }, new[] { 2, 2, 1, 2,1, 1, 1, 1, 1 }, new[] { 2, 2, 2, 2,2, 1, 1, 1, 1 }, // Third class of sequences: can start with any symbols, but ends with three. new[] { 0, 0, 1, 1,3, 3, 3, 3 }, new[] { 0, 0, 0, 3,3, 3, 3 }, new[] { 1, 0, 1, 2,2, 2, 3, 3 }, new[] { 1, 1, 2, 3,3, 3, 3 }, new[] { 0, 0, 1, 1,3, 3, 3, 3 }, new[] { 2, 2, 0, 3,3, 3, 3 }, new[] { 1, 0, 1, 2,3, 3, 3, 3 }, new[] { 1, 1, 2, 3,3, 3, 3 }, }; // Consider their respective class labels. // Class labels have to be zero-based and successive integers. int[] classLabels = { 0, 0, 0, // Sequences 1-3 are from class 0. 1, 1, 1, // Sequences 4-6 are from class 1. 2, 2, 2, 2, 2, 2, 2, 2 // Sequences 7-14 are from class 2. }; // Use a single topology for all inner models. ITopology forward = new Forward(states: 3); // Create a hidden Markov classifier with the given topology. HiddenMarkovClassifier hmc = new HiddenMarkovClassifier(classes: 3, topology: forward, symbols: 4); // Create a algorithms to teach each of the inner models. var trainer = new HiddenMarkovClassifierLearning( hmc, // Specify individual training options for each inner model. modelIndex => new BaumWelchLearning(hmc.Models[modelIndex]) { Tolerance = 0.001, // iterate until log-likelihood changes less than 0.001. Iterations = 0 // don't place an upper limit on the number of iterations. } ); // Call its Run method to start learning. double averageLogLikelihood = trainer.Run(observationSequences, classLabels); Console.WriteLine("average log-likelihood for the observations = {0}", averageLogLikelihood); // Check the output classificaton label for some sequences. int y1 = hmc.Compute(new[] { 0, 1, 1, 1, 0 }); // output is y1 = 0. Console.WriteLine("output class = {0}", y1); int y2 = hmc.Compute(new[] { 0, 0, 1, 1, 0, 0 }); // output is y2 = 0. Console.WriteLine("output class = {0}", y2); int y3 = hmc.Compute(new[] { 2, 2, 2, 2, 1, 1 }); // output is y3 = 1. Console.WriteLine("output class = {0}", y3); int y4 = hmc.Compute(new[] { 2, 2, 1, 1 }); // output is y4 = 1. Console.WriteLine("output class = {0}", y4); int y5 = hmc.Compute(new[] { 0, 0, 1, 3, 3, 3 }); // output is y5 = 2. Console.WriteLine("output class = {0}", y4); int y6 = hmc.Compute(new[] { 2, 0, 2, 2, 3, 3 }); // output is y6 = 2. Console.WriteLine("output class = {0}", y6); }
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> >( 2, new Ergodic(2), density); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning <MultivariateMixture <MultivariateNormalDistribution> >( classifier, // Train each model until the log-likelihood changes less than 0.0001 modelIndex => new BaumWelchLearning <MultivariateMixture <MultivariateNormalDistribution> >( classifier.Models[modelIndex]) { Tolerance = 0.0001, Iterations = 0, } ); // Train the sequence classifier using the algorithm double logLikelihood = teacher.Run(sequences, labels); // Calculate the probability that the given // sequences originated from the model double logLikelihood1, logLikelihood2; // Try to classify the 1st sequence (output should be 0) int c1 = classifier.Compute(sequences[0], out logLikelihood1); // Try to classify the 2nd sequence (output should be 1) int c2 = classifier.Compute(sequences[1], out logLikelihood2); Assert.AreEqual(0, c1); Assert.AreEqual(1, c2); Assert.AreEqual(-13.271981026832933, logLikelihood, 1e-10); Assert.AreEqual(0.99999791320102149, logLikelihood1, 1e-10); Assert.AreEqual(0.99999791320102149, logLikelihood2, 1e-10); Assert.IsFalse(double.IsNaN(logLikelihood)); Assert.IsFalse(double.IsNaN(logLikelihood1)); Assert.IsFalse(double.IsNaN(logLikelihood2)); }
public void RecognizeAsync(ISoundSignalReader signal, HiddenMarkovClassifier hmm, Action<string> handleMessage, SignalVisitor voiceVisitor = null) { Action<List<double[]>> action = features => { var observations = _codeBook.Quantize(features.Select(item => new Point(item)).ToArray()); double[] responsabilities; var ret = hmm.Compute(observations, out responsabilities); var models = hmm.Models; var likelyHoodValue = Double.MinValue; foreach (var model in models) { var val = model.Evaluate(observations); if (val > likelyHoodValue) { likelyHoodValue = val; } } handleMessage(hmm[ret].Tag.ToString()); }; var featureUtility = new FeatureUtility(_engineParameters); featureUtility.ExtractFeaturesAsync(signal, action, voiceVisitor); }
private void btnTrain_Click(object sender, EventArgs e) { if (dataGridView1.Rows.Count == 0) { MessageBox.Show("Please load or insert some data first."); return; } int states = (int)numStates.Value; int iterations = (int)numIterations.Value; double tolerance = (double)numConvergence.Value; if (rbStopIterations.Checked) { tolerance = 0.0; } if (rbStopConvergence.Checked) { iterations = 0; } // Retrieve the training data from the data grid view int rows = dataGridView1.Rows.Count; int[] outputs = new int[rows]; var sequences = new int[rows][]; for (int i = 0; i < rows; i++) { outputs[i] = (int)dataGridView1.Rows[i].Cells["colLabel"].Value - 1; sequences[i] = GetFeatures((double[][])dataGridView1.Rows[i].Tag); } int classes = outputs.Distinct().Count(); string[] labels = new string[classes]; for (int i = 0; i < labels.Length; i++) { labels[i] = (i + 1).ToString(); } // Create a sequence classifier for 3 classes classifier = new HiddenMarkovClassifier(labels.Length, new Forward(states), symbols: 20, names: labels); // Create the learning algorithm for the ensemble classifier var teacher = new HiddenMarkovClassifierLearning(classifier, // Train each model using the selected convergence criteria i => new BaumWelchLearning(classifier.Models[i]) { Tolerance = tolerance, Iterations = iterations, } ); // Create and use a rejection threshold model teacher.Rejection = cbRejection.Checked; teacher.Empirical = true; teacher.Smoothing = (double)numSmoothing.Value; // Run the learning algorithm teacher.Run(sequences, outputs); double error = classifier.LogLikelihood(sequences, outputs); int hits = 0; toolStripProgressBar1.Visible = true; toolStripProgressBar1.Value = 0; toolStripProgressBar1.Step = 1; toolStripProgressBar1.Maximum = dataGridView1.Rows.Count; for (int i = 0; i < rows; i++) { double likelihood; int index = classifier.Compute(sequences[i], out likelihood); DataGridViewRow row = dataGridView1.Rows[i]; if (index == -1) { row.Cells["colClassification"].Value = String.Empty; } else { row.Cells["colClassification"].Value = classifier.Models[index].Tag; } int expected = (int)row.Cells["colLabel"].Value; if (expected == index + 1) { row.Cells[0].Style.BackColor = Color.LightGreen; row.Cells[1].Style.BackColor = Color.LightGreen; row.Cells[2].Style.BackColor = Color.LightGreen; hits++; } else { row.Cells[0].Style.BackColor = Color.White; row.Cells[1].Style.BackColor = Color.White; row.Cells[2].Style.BackColor = Color.White; } toolStripProgressBar1.PerformStep(); } dgvModels.DataSource = classifier.Models; toolStripProgressBar1.Visible = false; toolStripStatusLabel1.Text = String.Format("Training complete. Hits: {0}/{1} ({2:0%})", hits, dataGridView1.Rows.Count, (double)hits / dataGridView1.Rows.Count); }
public void SimpleGestureRecognitionTest() { // Let's say we would like to do a very simple mechanism for // gesture recognition. In this example, we will be trying to // create a classifier that can distinguish between the words // "hello", "car", and "wardrobe". // Let's say we decided to acquire some data, and we asked some // people to perform those words in front of a Kinect camera, and, // using Microsoft's SDK, we were able to captured the x and y // coordinates of each hand while the word was being performed. // Let's say we decided to represent our frames as: // // double[] frame = { leftHandX, leftHandY, rightHandX, rightHandY }; // // Since we captured words, this means we captured sequences of // frames as we described above. Let's write some of those as // rough examples to explain how gesture recognition can be done: double[][] hello = { new double[] { 1.0, 0.1, 0.0, 0.0 }, // let's say the word new double[] { 0.0, 1.0, 0.1, 0.1 }, // hello took 6 frames new double[] { 0.0, 1.0, 0.1, 0.1 }, // to be recorded. new double[] { 0.0, 0.0, 1.0, 0.0 }, new double[] { 0.0, 0.0, 1.0, 0.0 }, new double[] { 0.0, 0.0, 0.1, 1.1 }, }; double[][] car = { new double[] { 0.0, 0.0, 0.0, 1.0 }, // the car word new double[] { 0.1, 0.0, 1.0, 0.1 }, // took only 4. new double[] { 0.0, 0.0, 0.1, 0.0 }, new double[] { 1.0, 0.0, 0.0, 0.0 }, }; double[][] wardrobe = { new double[] { 0.0, 0.0, 1.0, 0.0 }, // same for the new double[] { 0.1, 0.0, 1.0, 0.1 }, // wardrobe word. new double[] { 0.0, 0.1, 1.0, 0.0 }, new double[] { 0.1, 0.0, 1.0, 0.1 }, }; // Here, please note that a real-world example would involve *lots* // of samples for each word. Here, we are considering just one from // each class which is clearly sub-optimal and should _never_ be done // on practice. For example purposes, however, please disregard this. // Those are the words we have in our vocabulary: // double[][][] words = { hello, car, wardrobe }; // Now, let's associate integer labels with them. This is needed // for the case where there are multiple samples for each word. // int[] labels = { 0, 1, 2 }; // We will create our classifiers assuming an independent // Gaussian distribution for each component in our feature // vectors (like assuming a Naive Bayes assumption). var initial = new Independent <NormalDistribution> ( new NormalDistribution(0, 1), new NormalDistribution(0, 1), new NormalDistribution(0, 1), new NormalDistribution(0, 1) ); // Now, we can proceed and create our classifier. // int numberOfWords = 3; // we are trying to distinguish between 3 words int numberOfStates = 5; // this value can be found by trial-and-error var hmm = new HiddenMarkovClassifier <Independent <NormalDistribution> > ( classes: numberOfWords, topology: new Forward(numberOfStates), // word classifiers should use a forward topology initial: initial ); // Create a new learning algorithm to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning <Independent <NormalDistribution> >(hmm, // Train each model until the log-likelihood changes less than 0.001 modelIndex => new BaumWelchLearning <Independent <NormalDistribution> >(hmm.Models[modelIndex]) { Tolerance = 0.001, Iterations = 100, // This is necessary so the code doesn't blow up when it realize // there is only one sample per word class. But this could also be // needed in normal situations as well. // FittingOptions = new IndependentOptions() { InnerOption = new NormalOptions() { Regularization = 1e-5 } } } ); // Finally, we can run the learning algorithm! double logLikelihood = teacher.Run(words, labels); // At this point, the classifier should be successfully // able to distinguish between our three word classes: // int tc1 = hmm.Compute(hello); int tc2 = hmm.Compute(car); int tc3 = hmm.Compute(wardrobe); Assert.AreEqual(0, tc1); Assert.AreEqual(1, tc2); Assert.AreEqual(2, tc3); // Now, we can use the Markov classifier to initialize a HCRF var function = new MarkovMultivariateFunction(hmm); var hcrf = new HiddenConditionalRandomField <double[]>(function); // We can check that both are equivalent, although they have // formulations that can be learned with different methods // for (int i = 0; i < words.Length; i++) { // Should be the same int expected = hmm.Compute(words[i]); int actual = hcrf.Compute(words[i]); // Should be the same double h0 = hmm.LogLikelihood(words[i], 0); double c0 = hcrf.LogLikelihood(words[i], 0); double h1 = hmm.LogLikelihood(words[i], 1); double c1 = hcrf.LogLikelihood(words[i], 1); double h2 = hmm.LogLikelihood(words[i], 2); double c2 = hcrf.LogLikelihood(words[i], 2); Assert.AreEqual(expected, actual); Assert.AreEqual(h0, c0, 1e-10); Assert.IsTrue(h1.IsRelativelyEqual(c1, 1e-10)); Assert.IsTrue(h2.IsRelativelyEqual(c2, 1e-10)); Assert.IsFalse(double.IsNaN(c0)); Assert.IsFalse(double.IsNaN(c1)); Assert.IsFalse(double.IsNaN(c2)); } // Now we can learn the HCRF using one of the best learning // algorithms available, Resilient Backpropagation learning: // Create a learning algorithm var rprop = new HiddenResilientGradientLearning <double[]>(hcrf) { Iterations = 50, Tolerance = 1e-5 }; // Run the algorithm and learn the models double error = rprop.Run(words, labels); // At this point, the HCRF should be successfully // able to distinguish between our three word classes: // int hc1 = hcrf.Compute(hello); int hc2 = hcrf.Compute(car); int hc3 = hcrf.Compute(wardrobe); Assert.AreEqual(0, hc1); Assert.AreEqual(1, hc2); Assert.AreEqual(2, hc3); }
/// <summary> /// learn Hmm model for samples in given database using Baum Welch unsupervised learning algorithm /// then used the learned model to classify the training samples /// </summary> /// <param name="database"></param> /// <returns></returns> static HiddenMarkovClassifier<MultivariateNormalDistribution> learnHMM(Database database) { BindingList<Sequence> samples = database.Samples; BindingList<String> classes = database.Classes; double[][][] inputs = new double[samples.Count][][]; int[] outputs = new int[samples.Count]; for (int i = 0; i < inputs.Length; i++) { inputs[i] = samples[i].Input; outputs[i] = samples[i].Output; } int states = 5; int iterations = 0; double tolerance = 0.1; bool rejection = true; HiddenMarkovClassifier<MultivariateNormalDistribution> hmm = new HiddenMarkovClassifier<MultivariateNormalDistribution>(classes.Count, new Forward(states), new MultivariateNormalDistribution(2), classes.ToArray()); // Create the learning algorithm for the ensemble classifier var teacher = new HiddenMarkovClassifierLearning<MultivariateNormalDistribution>(hmm, // Train each model using the selected convergence criteria i => new BaumWelchLearning<MultivariateNormalDistribution>(hmm.Models[i]) { Tolerance = tolerance, Iterations = iterations, FittingOptions = new NormalOptions() { Regularization = 1e-5 } } ); teacher.Empirical = true; teacher.Rejection = rejection; // Run the learning algorithm double error = teacher.Run(inputs, outputs); // Classify all training instances foreach (var sample in database.Samples) { sample.RecognizedAs = hmm.Compute(sample.Input); } return hmm; }
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>>( 2, new Ergodic(2), density); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning<MultivariateMixture<MultivariateNormalDistribution>>( classifier, // Train each model until the log-likelihood changes less than 0.0001 modelIndex => new BaumWelchLearning<MultivariateMixture<MultivariateNormalDistribution>>( classifier.Models[modelIndex]) { Tolerance = 0.0001, Iterations = 0, } ); // Train the sequence classifier using the algorithm double logLikelihood = teacher.Run(sequences, labels); // Calculate the probability that the given // sequences originated from the model double likelihood1, likelihood2; // Try to classify the 1st sequence (output should be 0) int c1 = classifier.Compute(sequences[0], out likelihood1); // Try to classify the 2nd sequence (output should be 1) int c2 = classifier.Compute(sequences[1], out likelihood2); 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); Assert.IsFalse(double.IsNaN(logLikelihood)); Assert.IsFalse(double.IsNaN(likelihood1)); Assert.IsFalse(double.IsNaN(likelihood2)); }
public int ComputeToInt(double[][] sequence) { return(classifer.Compute(sequence)); }
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); // 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>( 2, new Custom(new double[2, 2], new double[2]), density); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning<MultivariateNormalDistribution>( classifier, // Train each model until the log-likelihood changes less than 0.0001 modelIndex => new BaumWelchLearning<MultivariateNormalDistribution>( classifier.Models[modelIndex]) { Tolerance = 0.0001, Iterations = 0, FittingOptions = new NormalOptions() { Diagonal = true } } ); // Train the sequence classifier using the algorithm double logLikelihood = teacher.Run(sequences, labels); // Calculate the probability that the given // sequences originated from the model double response1, response2; // Try to classify the 1st sequence (output should be 0) int c1 = classifier.Compute(sequences[0], out response1); // Try to classify the 2nd sequence (output should be 1) int c2 = classifier.Compute(sequences[1], out response2); Assert.AreEqual(double.NegativeInfinity, logLikelihood); Assert.AreEqual(0, response1); Assert.AreEqual(0, response2); Assert.IsFalse(double.IsNaN(logLikelihood)); Assert.IsFalse(double.IsNaN(response1)); Assert.IsFalse(double.IsNaN(response2)); }
public Form1() { InitializeComponent(); //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 }; #region Old //Dictionary<string, List<List<double[]>>> dictAll; //using (System.IO.FileStream fs = new System.IO.FileStream(@".\SkeletonsAsDouble.serialized", System.IO.FileMode.Open)) //{ // BinaryFormatter bf = new BinaryFormatter(); // dictAll = (Dictionary<string, List<List<double[]>>>)bf.Deserialize(fs); //} //#region Export to CSV //using (System.IO.StreamWriter sw = new System.IO.StreamWriter(@".\SkeletonsAsCSV.csv")) //{ // double[] rgFirstFrame = dictAll[dictAll.Keys.ElementAt(0)][0][0]; // string strHeader = string.Empty; // for (int i = 0; i < rgFirstFrame.Length; i++) // { // strHeader += string.Format("F{0},", i); // } // strHeader += "Label"; // sw.WriteLine(strHeader); // foreach (KeyValuePair<string, List<List<double[]>>> kvp in dictAll) // { // foreach (List<double[]> lstGesture in kvp.Value) // { // foreach (double[] frame in lstGesture) // { // sw.WriteLine(string.Format("{0},{1}", string.Join(",", frame), kvp.Key)); // } // } // } //} #endregion #region CHANGE THESE PARAMETERS const int nStartHiddenCount = 2; const int nEndHiddenCount = 12; const int nFeatureCount = 8; // Both DataOrig.dat and Data.dat have dimensionality of 8 #endregion string strFile; int nClasses; #if STRHC1 // Data.dat = Second STRHC (10 classes but not as noisy) strFile = @".\Data.dat"; nClasses = 10; #else // Data1.dat = First STRHC (4 classes but very noisy) strFile = @".\DataOrig.dat"; nClasses = 4; #endif Dictionary <int, Tuple <Dictionary <string, List <List <double[]> > >, Dictionary <string, List <List <double[]> > > > > dict; using (System.IO.FileStream fs = new System.IO.FileStream(strFile, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { BinaryFormatter bf = new BinaryFormatter(); dict = bf.Deserialize(fs) as Dictionary <int, Tuple <Dictionary <string, List <List <double[]> > >, Dictionary <string, List <List <double[]> > > > >; } using (System.IO.StreamWriter sw = new System.IO.StreamWriter(@"HMMOutput.txt")) { for (int nHiddenCount = nStartHiddenCount; nHiddenCount <= nEndHiddenCount; nHiddenCount++) { double fAverage = 0.0; int nEpoch = 0; List <int> lstTrainTimes = new List <int>(); List <int> lstRecogTimes = new List <int>(); //for (int i = 1; i <= nEpochs; i++) foreach (KeyValuePair <int, Tuple <Dictionary <string, List <List <double[]> > >, Dictionary <string, List <List <double[]> > > > > kvpTT in dict) { nEpoch++; #region Old //Dictionary<string, List<List<double[]>>> dictTrain = new Dictionary<string, List<List<double[]>>>(); //Dictionary<string, List<List<double[]>>> dictTest = new Dictionary<string, List<List<double[]>>>(); //#region Divide the vectors into training and testing sets //foreach (KeyValuePair<string, List<List<double[]>>> kvp in dictAll) //{ // int nGroupSize = kvp.Value.Count / nEpochs; // List<List<double[]>> lstTrain; // List<List<double[]>> lstTest; // dictTrain.Add(kvp.Key, (lstTrain = new List<List<double[]>>())); // dictTest.Add(kvp.Key, (lstTest = new List<List<double[]>>())); // for (int j = 0; j < kvp.Value.Count; j++) // { // if (j < i * nGroupSize && j >= (i * nGroupSize) - nGroupSize) // { // lstTest.Add(kvp.Value[j]); // } // else // { // lstTrain.Add(kvp.Value[j]); // } // } //} //#endregion #endregion Dictionary <string, List <List <double[]> > > dictTrain = kvpTT.Value.Item1; Dictionary <string, List <List <double[]> > > dictTest = kvpTT.Value.Item2; double[][][] sequences = new double[dictTrain.Sum(kvp => kvp.Value.Count)][][]; int[] labels = new int[sequences.Length]; #region The Sequences int nIndex = 0; foreach (KeyValuePair <string, List <List <double[]> > > kvp in dictTrain) { foreach (List <double[]> lst in kvp.Value) { sequences[nIndex] = lst.ToArray(); labels[nIndex] = Array.IndexOf(dictTrain.Keys.ToArray(), kvp.Key); nIndex++; } } #endregion var initialDensity = new MultivariateNormalDistribution(nFeatureCount); // 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>( classes: nClasses, topology: new Forward(nHiddenCount), initial: initialDensity); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning <MultivariateNormalDistribution>( classifier, // Train each model until the log-likelihood changes less than 0.0001 modelIndex => new BaumWelchLearning <MultivariateNormalDistribution>( 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 System.Diagnostics.Stopwatch watchTrain = new System.Diagnostics.Stopwatch(); watchTrain.Start(); double logLikelihood = teacher.Run(sequences, labels); watchTrain.Stop(); lstTrainTimes.Add((int)watchTrain.ElapsedMilliseconds); //// Calculate the probability that the given //// sequences originated from the model //double likelihood, likelihood2; //// Try to classify the 1st sequence (output should be 0) //int c1 = classifier.Compute(sequences[0], out likelihood); //// Try to classify the 2nd sequence (output should be 1) //int c2 = classifier.Compute(sequences[1], out likelihood2); sw.WriteLine("Epoch: {0} -- Hidden State: {1}\t\tTotal Train Time: {2}", nEpoch, nHiddenCount, watchTrain.ElapsedMilliseconds.ToString()); int nCorrect = 0; int nIncorrect = 0; foreach (KeyValuePair <string, List <List <double[]> > > kvp in dictTest) { foreach (List <double[]> lst in kvp.Value) { System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); int nClassIndex = classifier.Compute(lst.ToArray()); watch.Stop(); sw.WriteLine(string.Format("Should be: {0}\tRecognized: {1}\t\tTime: {2} ms", kvp.Key, dictTest.Keys.ElementAt(nClassIndex), watch.ElapsedMilliseconds)); lstRecogTimes.Add((int)watch.ElapsedMilliseconds); if (dictTest.Keys.ElementAt(nClassIndex) == kvp.Key) { nCorrect++; } else { nIncorrect++; } } } fAverage += (double)nCorrect / (nCorrect + nIncorrect); sw.WriteLine(string.Format("Correct: {0} of {1} ({2:P3})", nCorrect, nCorrect + nIncorrect, (double)nCorrect / (nCorrect + nIncorrect))); sw.WriteLine(); sw.WriteLine(); } sw.WriteLine("Average Correct for {0} Hidden: {1:P3}", nHiddenCount, fAverage / 5); sw.WriteLine("Average Train Time for {0}: {1:F2}", nHiddenCount, lstTrainTimes.Select(v => (double)v).Average()); sw.WriteLine("Std. Dev. Train Time for {0}: {1:F2}", nHiddenCount, lstTrainTimes.Select(v => (double)v).StandardDeviation()); sw.WriteLine("Average Recog. Time for {0}: {1:F2}", nHiddenCount, lstRecogTimes.Select(v => (double)v).Average()); sw.WriteLine("Std. Dev. Recog. Time for {0}: {1:F2}", nHiddenCount, lstRecogTimes.Select(v => (double)v).StandardDeviation()); sw.WriteLine(); sw.WriteLine(); sw.WriteLine(); sw.WriteLine(); } } }