示例#1
0
        // 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));
        }
示例#3
0
        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;
        }
示例#7
0
        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);
        }
示例#8
0
        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);
            }
        }
示例#10
0
        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);
                    }
                }
            }
        }
示例#11
0
        /// <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);
        }
示例#15
0
        /// <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;
            }
        }
示例#16
0
        /// <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) };
        }
示例#17
0
        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);
        }
示例#18
0
    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);
        }
示例#20
0
        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);
        }
示例#23
0
        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);
        }
示例#27
0
        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));
        }
示例#32
0
        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;
        }
示例#33
0
        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));
        }
示例#34
0
        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 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 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);
            }
        }
示例#41
0
        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);
        }
示例#43
0
        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));
        }
示例#47
0
 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));
        }
示例#49
0
文件: Form1.cs 项目: sbreed/HMM
        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();
                }
            }
        }