public void GradientTest3()
        {
            double[][][] sequences2;
            int[]        labels2;
            var          hmm      = CreateModel3(out sequences2, out labels2);
            var          function = new MarkovMultivariateFunction(hmm);

            var model  = new HiddenConditionalRandomField <double[]>(function);
            var target = new ForwardBackwardGradient <double[]>(model);

            target.Regularization = 2;

            var inputs  = sequences2;
            var outputs = labels2;


            FiniteDifferences diff = new FiniteDifferences(function.Weights.Length);

            diff.Function = parameters => func(model, parameters, inputs, outputs, target.Regularization);

            double[] expected = diff.Compute(function.Weights);
            double[] actual   = target.Gradient(function.Weights, inputs, outputs);


            for (int i = 0; i < actual.Length; i++)
            {
                double e = expected[i];
                double a = actual[i];
                Assert.AreEqual(e, a, 1e-3);

                Assert.IsFalse(double.IsNaN(actual[i]));
                Assert.IsFalse(double.IsNaN(expected[i]));
            }
        }
Beispiel #2
0
        public void GradientTest4()
        {
            var hmm      = IndependentMarkovClassifierPotentialFunctionTest.CreateModel2();
            var function = new MarkovMultivariateFunction(hmm);

            var model  = new HiddenConditionalRandomField <double[]>(function);
            var target = new ForwardBackwardGradient <double[]>(model);

            target.Regularization = 0;

            FiniteDifferences diff = new FiniteDifferences(function.Weights.Length);

            diff.Function = parameters => func(model, parameters,
                                               IndependentMarkovClassifierPotentialFunctionTest.sequences,
                                               IndependentMarkovClassifierPotentialFunctionTest.labels);

            double[] expected = diff.Compute(function.Weights);
            double[] actual   = target.Gradient(function.Weights,
                                                IndependentMarkovClassifierPotentialFunctionTest.sequences,
                                                IndependentMarkovClassifierPotentialFunctionTest.labels);


            for (int i = 0; i < actual.Length; i++)
            {
                if (double.IsNaN(expected[i]))
                {
                    continue;
                }

                Assert.AreEqual(expected[i], actual[i], 1e-5);
                Assert.IsFalse(double.IsNaN(actual[i]));
            }
        }
Beispiel #3
0
        public void GradientTest_MarkovIndependentNormal_NoPriors()
        {
            double[][][] observations;
            int[]        labels;
            HiddenMarkovClassifier <Independent <NormalDistribution> > hmm =
                IndependentMarkovFunctionTest.CreateModel4(out observations, out labels, usePriors: false);

            var function = new MarkovMultivariateFunction(hmm);

            var model  = new HiddenConditionalRandomField <double[]>(function);
            var target = new ForwardBackwardGradient <double[]>(model);

            target.Regularization = 0;

            FiniteDifferences diff = new FiniteDifferences(function.Weights.Length);

            diff.Function = parameters => func(model, parameters,
                                               observations,
                                               labels);

            double[] expected = diff.Compute(function.Weights);
            double[] actual   = target.Gradient(function.Weights, observations, labels);


            for (int i = 0; i < actual.Length; i++)
            {
                if (double.IsNaN(expected[i]))
                {
                    continue;
                }

                Assert.AreEqual(expected[i], actual[i], 1e-5);
                Assert.IsFalse(double.IsNaN(actual[i]));
            }
        }
        public void LogBackwardTest2()
        {
            HiddenMarkovClassifier <Independent> hmm = IndependentMarkovClassifierPotentialFunctionTest
                                                       .CreateModel3();

            MarkovMultivariateFunction function = new MarkovMultivariateFunction(hmm);

            double[][][] observations = IndependentMarkovClassifierPotentialFunctionTest.sequences2;
            int[]        labels       = IndependentMarkovClassifierPotentialFunctionTest.labels2;

            foreach (double[][] x in observations)
            {
                foreach (int y in labels)
                {
                    double[,] actual = new double[x.Length, 5];
                    Accord.Statistics.Models.Fields.
                    ForwardBackwardAlgorithm.LogBackward(function.Factors[y], x, y, actual);

                    double[,] expected = new double[x.Length, 5];
                    Accord.Statistics.Models.Markov.
                    ForwardBackwardAlgorithm.LogBackward(hmm.Models[y], x, expected);

                    for (int i = 0; i < actual.GetLength(0); i++)
                    {
                        for (int j = 0; j < actual.GetLength(1); j++)
                        {
                            Assert.AreEqual(expected[i, j], actual[i, j], 1e-10);
                            Assert.IsFalse(Double.IsNaN(actual[i, j]));
                        }
                    }
                }
            }
        }
        public void LogForwardTest4()
        {
            var hmmc = Accord.Tests.Statistics.Models.Fields.
                       MultivariateNormalHiddenMarkovClassifierPotentialFunctionTest.CreateModel3();

            for (int c = 0; c < hmmc.Classes; c++)
            {
                var hmm = hmmc[c];

                var function = new MarkovMultivariateFunction(hmm);

                var sequences = Accord.Tests.Statistics.Models.Fields.
                                MultivariateNormalHiddenMarkovClassifierPotentialFunctionTest.inputTest;

                for (int i = 0; i < sequences.Length; i++)
                {
                    var observations = sequences[i];

                    double expectedLogLikelihood;
                    double[,] expected = Accord.Statistics.Models.Markov
                                         .ForwardBackwardAlgorithm.LogForward(hmm, observations, out expectedLogLikelihood);

                    double actualLogLikelihood;
                    double[,] actual = Accord.Statistics.Models.Fields.
                                       ForwardBackwardAlgorithm.LogForward(function.Factors[0], observations, 0, out actualLogLikelihood);


                    Assert.IsTrue(expected.IsEqual(actual, 1e-10));

                    Assert.AreEqual(expectedLogLikelihood, actualLogLikelihood, 1e-6);
                    Assert.IsFalse(Double.IsNaN(actualLogLikelihood));
                }
            }
        }
Beispiel #6
0
        public void LogForwardTest()
        {
            double[][][] observations;
            int[]        labels;
            var          hmm = IndependentMarkovFunctionTest.CreateModel2(out observations, out labels);

            MarkovMultivariateFunction function = new MarkovMultivariateFunction(hmm, includePriors: false);

            foreach (double[][] x in observations)
            {
                foreach (int y in labels)
                {
                    double[,] actual = new double[5, 2];
                    Accord.Statistics.Models.Fields.
                    ForwardBackwardAlgorithm.LogForward(function.Factors[y], x, y, actual);

                    double[,] expected = new double[5, 2];
                    Accord.Statistics.Models.Markov.
                    ForwardBackwardAlgorithm.LogForward(hmm.Models[y], x, expected);

                    for (int i = 0; i < actual.GetLength(0); i++)
                    {
                        for (int j = 0; j < actual.GetLength(1); j++)
                        {
                            Assert.AreEqual(expected[i, j], actual[i, j], 1e-10);
                        }
                    }
                }
            }
        }
        public void NumberOfFeaturesTest()
        {
            Independent initial = new Independent(
                new GeneralDiscreteDistribution(46),       // output,
                new NormalDistribution(0, 1),              // headAngle,
                new NormalDistribution(0, 1),              // handAngle,
                new NormalDistribution(0, 1),              // relHandX,
                new NormalDistribution(0, 1)               // relHandY,
                );



            var model = new HiddenMarkovClassifier <Independent>(
                classes: 13, topology: new Forward(5), initial: initial);

            var function = new MarkovMultivariateFunction(model);
            var field    = new HiddenConditionalRandomField <double[]>(function);



            int discreteDistributions   = 1;
            int continuousDistributions = 4;
            int symbols  = 46;
            int states   = 5;
            int classes  = 13;
            int expected = classes *
                           (1 + states + states * states +
                            states * discreteDistributions * symbols +
                            states * continuousDistributions * 3);

            Assert.AreEqual(expected, field.Function.Features.Length);
            Assert.AreEqual(expected, field.Function.Weights.Length);
            Assert.AreEqual(4173, expected);
        }
        public void ForwardTest4()
        {
            var hmmc = Accord.Tests.Statistics.Models.Fields.
                       MultivariateMarkovFunctionTest.CreateModel3();

            var hmm = hmmc[0];

            var function = new MarkovMultivariateFunction(hmm);

            var observations = Accord.Tests.Statistics.Models.Fields.
                               MultivariateMarkovFunctionTest.inputTest[3];

            double expectedLogLikelihood;

            double[,] expected = Accord.Statistics.Models.Markov
                                 .ForwardBackwardAlgorithm.Forward(hmm, observations, out expectedLogLikelihood);

            double actualLogLikelihood;

            double[,] actual = Accord.Statistics.Models.Fields.
                               ForwardBackwardAlgorithm.Forward(function.Factors[0], observations, 0, out actualLogLikelihood);


            Assert.IsTrue(expected.IsEqual(actual, 1e-10));


            Assert.AreEqual(expectedLogLikelihood, actualLogLikelihood, 1e-6);
            Assert.IsFalse(Double.IsNaN(actualLogLikelihood));
        }
Beispiel #9
0
        public void GradientTest3()
        {
            var hmm      = MultivariateNormalHiddenMarkovClassifierPotentialFunctionTest.CreateModel1();
            var function = new MarkovMultivariateFunction(hmm);

            var model  = new HiddenConditionalRandomField <double[]>(function);
            var target = new ForwardBackwardGradient <double[]>(model);

            target.Regularization = 2;

            var inputs  = inputs1;
            var outputs = outputs1;



            FiniteDifferences diff = new FiniteDifferences(function.Weights.Length);

            diff.Function = parameters => func(model, parameters, inputs, outputs, target.Regularization);

            double[] expected = diff.Compute(function.Weights);
            double[] actual   = target.Gradient(function.Weights, inputs, outputs);


            for (int i = 0; i < actual.Length; i++)
            {
                Assert.AreEqual(expected[i], actual[i], 1e-3);

                Assert.IsFalse(double.IsNaN(actual[i]));
                Assert.IsFalse(double.IsNaN(expected[i]));
            }
        }
Beispiel #10
0
        public void LogForwardGesturesDeoptimizedTest()
        {
            int[]        labels;
            double[][][] words;
            var          classifier = IndependentMarkovFunctionTest.CreateModel4(out words, out labels, false);

            var function = new MarkovMultivariateFunction(classifier);

            function.Deoptimize();

            var target = new HiddenConditionalRandomField <double[]>(function);

            foreach (var word in words)
            {
                for (int c = 0; c < 3; c++)
                {
                    var actual = Accord.Statistics.Models.Fields.ForwardBackwardAlgorithm.LogForward(
                        target.Function.Factors[c], word, c);

                    var expected = Accord.Statistics.Models.Markov.ForwardBackwardAlgorithm.LogForward(
                        classifier[c], word);

                    for (int i = 0; i < actual.GetLength(0); i++)
                    {
                        for (int j = 0; j < actual.GetLength(1); j++)
                        {
                            double a = actual[i, j];
                            double e = expected[i, j];
                            Assert.IsTrue(e.IsRelativelyEqual(a, 0.1));
                        }
                    }
                }
            }
        }
        public void GradientDeoptimizeTest2()
        {
            double[][][] sequences2;
            int[]        labels2;

            var hmm      = CreateModel3(out sequences2, out labels2);
            var function = new MarkovMultivariateFunction(hmm);

#pragma warning disable 0618
            function.Deoptimize();
#pragma warning restore 0618

            var model  = new HiddenConditionalRandomField <double[]>(function);
            var target = new ForwardBackwardGradient <double[]>(model);

            var inputs  = sequences2;
            var outputs = labels2;

            double[] actual = target.Gradient(function.Weights, inputs, outputs);

            FiniteDifferences diff = new FiniteDifferences(function.Weights.Length);
            diff.Function = parameters => func(model, parameters, inputs, outputs);
            double[] expected = diff.Compute(function.Weights);


            for (int i = 0; i < actual.Length; i++)
            {
                Assert.AreEqual(expected[i], actual[i], 1e-3);
                Assert.IsFalse(double.IsNaN(actual[i]));
                Assert.IsFalse(double.IsNaN(expected[i]));
            }
        }
Beispiel #12
0
        public void RunTest()
        {
            var hmm      = MultivariateNormalHiddenMarkovClassifierPotentialFunctionTest.CreateModel1();
            var function = new MarkovMultivariateFunction(hmm);

            var model  = new HiddenConditionalRandomField <double[]>(function);
            var target = new HiddenQuasiNewtonLearning <double[]>(model);

            var inputs  = inputs1;
            var outputs = outputs1;

            double[] actual   = new double[inputs.Length];
            double[] expected = new double[inputs.Length];

            for (int i = 0; i < inputs.Length; i++)
            {
                actual[i]   = model.Compute(inputs[i]);
                expected[i] = outputs[i];
            }

            for (int i = 0; i < inputs.Length; i++)
            {
                Assert.AreEqual(expected[i], actual[i]);
            }

            double llm = hmm.LogLikelihood(inputs, outputs);
            double ll0 = model.LogLikelihood(inputs, outputs);

            Assert.AreEqual(llm, ll0, 1e-10);
            Assert.IsFalse(double.IsNaN(llm));
            Assert.IsFalse(double.IsNaN(ll0));

            double error = target.Run(inputs, outputs);
            double ll1   = model.LogLikelihood(inputs, outputs);

            Assert.AreEqual(-ll1, error, 1e-10);
            Assert.IsFalse(double.IsNaN(ll1));
            Assert.IsFalse(double.IsNaN(error));


            for (int i = 0; i < inputs.Length; i++)
            {
                actual[i]   = model.Compute(inputs[i]);
                expected[i] = outputs[i];
            }

            Assert.AreEqual(-0.0000041736023117522336, ll0, 1e-10);

            Assert.AreEqual(error, -ll1);
            Assert.IsFalse(Double.IsNaN(ll0));
            Assert.IsFalse(Double.IsNaN(error));

            for (int i = 0; i < inputs.Length; i++)
            {
                Assert.AreEqual(expected[i], actual[i]);
            }

            Assert.IsTrue(ll1 > ll0);
        }
Beispiel #13
0
        public void ComputeTest3()
        {
            var hmm = MultivariateMarkovFunctionTest.CreateModel1();

            var owner = new MarkovMultivariateFunction(hmm);


            double[][] x = 
            { 
                new double[] { 0 },
                new double[] { 1 },
                new double[] { 3 },
                new double[] { 1 },
                new double[] { 2 },
                new double[] { 8 },
                new double[] { 0 },
                new double[] { 10 },
                new double[] { System.Math.PI },
            };

            foreach (var factor in owner.Factors)
            {
                for (int y = 0; y < owner.Outputs; y++)
                {
                    double[,] fwd = Accord.Statistics.Models.Fields
                        .ForwardBackwardAlgorithm.Forward(factor, x, y);

                    double[,] bwd = Accord.Statistics.Models.Fields
                        .ForwardBackwardAlgorithm.Backward(factor, x, y);

                    double[,] lnfwd = Accord.Statistics.Models.Fields
                        .ForwardBackwardAlgorithm.LogForward(factor, x, y);

                    double[,] lnbwd = Accord.Statistics.Models.Fields
                        .ForwardBackwardAlgorithm.LogBackward(factor, x, y);


                    for (int i = 0; i < fwd.GetLength(0); i++)
                        for (int j = 0; j < fwd.GetLength(1); j++)
                            Assert.AreEqual(System.Math.Log(fwd[i, j]), lnfwd[i, j], 1e-10);

                    for (int i = 0; i < bwd.GetLength(0); i++)
                        for (int j = 0; j < bwd.GetLength(1); j++)
                            Assert.AreEqual(System.Math.Log(bwd[i, j]), lnbwd[i, j], 1e-10);


                    foreach (var feature in factor)
                    {
                        double expected = System.Math.Log(feature.Marginal(fwd, bwd, x, y));
                        double actual = feature.LogMarginal(lnfwd, lnbwd, x, y);

                        Assert.AreEqual(expected, actual, 1e-10);
                        Assert.IsFalse(Double.IsNaN(actual));
                    }

                }
            }
        }
        public void ComputeTestPriors4()
        {
            int[]        labels;
            double[][][] words;
            var          model = CreateModel4(out words, out labels, true);

            var target = new MarkovMultivariateFunction(model);

            var hcrf = new HiddenConditionalRandomField <double[]>(target);

            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-5));
                        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-6));
                                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 RunTest()
        {
            var hmm = MultivariateNormalHiddenMarkovClassifierPotentialFunctionTest.CreateModel1();
            var function = new MarkovMultivariateFunction(hmm);

            var model = new HiddenConditionalRandomField<double[]>(function);
            var target = new HiddenQuasiNewtonLearning<double[]>(model);

            var inputs = inputs1;
            var outputs = outputs1;

            double[] actual = new double[inputs.Length];
            double[] expected = new double[inputs.Length];

            for (int i = 0; i < inputs.Length; i++)
            {
                actual[i] = model.Compute(inputs[i]);
                expected[i] = outputs[i];
            }

            for (int i = 0; i < inputs.Length; i++)
                Assert.AreEqual(expected[i], actual[i]);

            double llm = hmm.LogLikelihood(inputs, outputs);
            double ll0 = model.LogLikelihood(inputs, outputs);
            Assert.AreEqual(llm, ll0, 1e-10);
            Assert.IsFalse(double.IsNaN(llm));
            Assert.IsFalse(double.IsNaN(ll0));

            double error = target.Run(inputs, outputs);
            double ll1 = model.LogLikelihood(inputs, outputs);
            Assert.AreEqual(-ll1, error, 1e-10);
            Assert.IsFalse(double.IsNaN(ll1));
            Assert.IsFalse(double.IsNaN(error));


            for (int i = 0; i < inputs.Length; i++)
            {
                actual[i] = model.Compute(inputs[i]);
                expected[i] = outputs[i];
            }

            Assert.AreEqual(-0.0000041736023117522336, ll0, 1e-10);
            
            Assert.AreEqual(error, -ll1);
            Assert.IsFalse(Double.IsNaN(ll0));
            Assert.IsFalse(Double.IsNaN(error));

            for (int i = 0; i < inputs.Length; i++)
                Assert.AreEqual(expected[i], actual[i]);

            Assert.IsTrue(ll1 > ll0);
        }
        public void learn_test()
        {
            double[][][] sequences;
            int[]        labels;
            HiddenMarkovClassifier <Independent, double[]> model =
                CreateModel2_learn(out sequences, out labels);

            var target = new MarkovMultivariateFunction(model);
            var hcrf   = new HiddenConditionalRandomField <double[]>(target);


            double actual;
            double expected;

            double[][] x = { new double[] { 0, 1.7 }, new double[] { 2, 2.1 } };

            for (int c = 0; c < model.Classes; c++)
            {
                for (int i = 0; i < model[c].States; i++)
                {
                    // Check initial state transitions
                    expected = model.Priors[c] * Math.Exp(model[c].LogInitial[i]) * model[c].Emissions[i].ProbabilityDensityFunction(x[0]);
                    actual   = Math.Exp(target.Factors[c].Compute(-1, i, x, 0, c));
                    Assert.AreEqual(expected, actual, 1e-6);
                    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].LogTransitions[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.AreEqual(expected, actual, 1e-6);
                            Assert.IsFalse(double.IsNaN(actual));
                        }
                    }
                }

                actual   = model.LogLikelihood(x, c);
                expected = hcrf.LogLikelihood(x, c);
                Assert.AreEqual(expected, actual);
                Assert.IsFalse(double.IsNaN(actual));
            }
        }
        public void ComputeTest()
        {
            var model = CreateModel1();

            var target = new MarkovMultivariateFunction(model);

            var hcrf = new HiddenConditionalRandomField <double[]>(target);

            double actual;
            double expected;

            double[][] x = { new double[] { 0 }, new double[] { 1 } };

            for (int c = 0; c < model.Classes; c++)
            {
                for (int i = 0; i < model[c].States; i++)
                {
                    // Check initial state transitions
                    expected = model.Priors[c] * Math.Exp(model[c].Probabilities[i]) * model[c].Emissions[i].ProbabilityDensityFunction(x[0]);
                    actual   = Math.Exp(target.Factors[c].Compute(-1, i, x, 0, c));
                    Assert.AreEqual(expected, actual, 1e-6);
                    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.AreEqual(expected, actual, 1e-6);
                            Assert.IsFalse(double.IsNaN(actual));
                        }
                    }
                }

                actual   = model.LogLikelihood(x, c);
                expected = hcrf.LogLikelihood(x, c);
                Assert.AreEqual(expected, actual, 1e-8);
                Assert.IsFalse(double.IsNaN(actual));
            }
        }
Beispiel #18
0
        public void ForwardTest2()
        {
            double[][][] observations;
            int[]        labels;

            var hmm = IndependentMarkovFunctionTest.CreateModel3(out observations, out labels);

            var function = new MarkovMultivariateFunction(hmm, includePriors: false);


            foreach (double[][] x in observations)
            {
                foreach (int y in labels)
                {
                    double[] scaling1;
                    double   logLikelihood1;

                    double[,] actual = Accord.Statistics.Models.Fields.
                                       ForwardBackwardAlgorithm.Forward(function.Factors[y], x, y, out scaling1, out logLikelihood1);

                    double[] scaling2;
                    double   logLikelihood2;
                    double[,] expected = Accord.Statistics.Models.Markov.
                                         ForwardBackwardAlgorithm.Forward(hmm.Models[y], x, out scaling2, out logLikelihood2);

                    for (int i = 0; i < actual.GetLength(0); i++)
                    {
                        for (int j = 0; j < actual.GetLength(1); j++)
                        {
                            Assert.AreEqual(expected[i, j], actual[i, j], 1e-10);
                            Assert.IsFalse(Double.IsNaN(actual[i, j]));
                        }
                    }

                    Assert.AreEqual(logLikelihood1, logLikelihood2, 1e-10);

                    for (int i = 0; i < scaling1.Length; i++)
                    {
                        Assert.IsTrue(scaling1[i].IsRelativelyEqual(scaling2[i], 1e-10));
                        Assert.IsFalse(Double.IsNaN(scaling1[i]));
                        Assert.IsFalse(Double.IsNaN(scaling2[i]));
                    }
                }
            }
        }
        public void ComputeTest4()
        {
            int[]        labels;
            double[][][] words;
            HiddenMarkovClassifier <Independent <NormalDistribution> > model =
                CreateModel4(out words, out labels, false);

            var target = new MarkovMultivariateFunction(model);

            var hcrf = new HiddenConditionalRandomField <double[]>(target);


            Assert.AreEqual(3, model.Priors.Length);
            Assert.AreEqual(1 / 3.0, model.Priors[0]);
            Assert.AreEqual(1 / 3.0, model.Priors[1]);
            Assert.AreEqual(1 / 3.0, model.Priors[2]);

            check4(words, model, target, hcrf);
        }
        public void GradientTest_MarkovMultivariate()
        {
            // Creates a sequence classifier containing 2 hidden Markov Models
            //  with 2 states and an underlying Normal distribution as density.
            MultivariateNormalDistribution density = new MultivariateNormalDistribution(3);
            var hmm = new HiddenMarkovClassifier <MultivariateNormalDistribution>(2, new Ergodic(2), density);

            double[][][] inputs =
            {
                new [] { new double[] { 0, 1, 0 }, new double[] { 0, 1, 0 }, new double[] { 0, 1, 0 } },
                new [] { new double[] { 1, 6, 2 }, new double[] { 2, 1, 6 }, new double[] { 1, 1, 0 } },
                new [] { new double[] { 9, 1, 0 }, new double[] { 0, 1, 5 }, new double[] { 0, 0, 0 } },
            };

            int[] outputs =
            {
                0, 0, 1
            };

            var function = new MarkovMultivariateFunction(hmm);

            var model  = new HiddenConditionalRandomField <double[]>(function);
            var target = new ForwardBackwardGradient <double[]>(model);

            FiniteDifferences diff = new FiniteDifferences(function.Weights.Length)
            {
                StepSize = 1e-5
            };

            diff.Function = parameters => func(model, parameters, inputs, outputs);

            double[] expected = diff.Compute(function.Weights);
            double[] actual   = target.Gradient(function.Weights, inputs, outputs);


            for (int i = 0; i < actual.Length; i++)
            {
                Assert.AreEqual(expected[i], actual[i], 0.05);
                Assert.IsFalse(double.IsNaN(actual[i]));
                Assert.IsFalse(double.IsNaN(expected[i]));
            }
        }
        public void LogForwardTest3()
        {
            MultivariateNormalDistribution density = new MultivariateNormalDistribution(3);
            var hmm = new HiddenMarkovClassifier <MultivariateNormalDistribution>(2, new Ergodic(2), density);

            double[][][] inputs =
            {
                new [] { new double[] { 0, 1, 0 }, new double[] { 0, 1, 0 }, new double[] { 0, 1, 0 } },
                new [] { new double[] { 1, 6, 2 }, new double[] { 2, 1, 6 }, new double[] { 1, 1, 0 } },
                new [] { new double[] { 9, 1, 0 }, new double[] { 0, 1, 5 }, new double[] { 0, 0, 0 } },
            };

            int[] outputs =
            {
                0, 0, 1
            };

            var function = new MarkovMultivariateFunction(hmm);

            var observations = inputs[0];

            double[,] expected = Matrix.Log(Accord.Statistics.Models.Fields.
                                            ForwardBackwardAlgorithm.Forward(function.Factors[0], observations, 0));

            double logLikelihood;

            double[,] actual = Accord.Statistics.Models.Fields.
                               ForwardBackwardAlgorithm.LogForward(function.Factors[0], observations, 0, out logLikelihood);

            Assert.IsTrue(expected.IsEqual(actual, 1e-10));

            double p = 0;

            for (int i = 0; i < hmm[0].States; i++)
            {
                p += Math.Exp(actual[observations.Length - 1, i]);
            }

            Assert.AreEqual(Math.Exp(logLikelihood), p, 1e-8);
            Assert.IsFalse(double.IsNaN(p));
        }
        public void ComputeDeoptimizeTest3()
        {
            double[][][] sequences;
            int[]        labels;
            var          model = CreateModel3(out sequences, out labels);

            var target = new MarkovMultivariateFunction(model);

#pragma warning disable 0618
            target.Deoptimize();
#pragma warning restore 0618

            var hcrf = new HiddenConditionalRandomField <double[]>(target);


            Assert.AreEqual(2, model.Priors.Length);
            Assert.AreEqual(1 / 2.0, model.Priors[0]);
            Assert.AreEqual(1 / 2.0, model.Priors[1]);

            check4(sequences, model, target, hcrf);
        }
        public void ComputeDeoptimizeTest4()
        {
            int[]        labels;
            double[][][] words;
            var          model = CreateModel4(out words, out labels, false);

            var target = new MarkovMultivariateFunction(model);

#pragma warning disable 0618
            target.Deoptimize();
#pragma warning restore 0618

            var hcrf = new HiddenConditionalRandomField <double[]>(target);


            Assert.AreEqual(3, model.Priors.Length);
            Assert.AreEqual(1 / 3.0, model.Priors[0]);
            Assert.AreEqual(1 / 3.0, model.Priors[1]);
            Assert.AreEqual(1 / 3.0, model.Priors[2]);

            check4(words, model, target, hcrf);
        }
        public void ForwardTest()
        {
            double[][][] observations;
            int[] labels;

            var hmm = IndependentMarkovFunctionTest.CreateModel2(out observations, out labels);

            var function = new MarkovMultivariateFunction(hmm, includePriors: false);


            foreach (double[][] x in observations)
            {
                foreach (int y in labels)
                {
                    double[] scaling1;
                    double logLikelihood1;

                    double[,] actual = Accord.Statistics.Models.Fields.
                        ForwardBackwardAlgorithm.Forward(function.Factors[y], x, y, out scaling1, out logLikelihood1);

                    double[] scaling2;
                    double logLikelihood2;
                    double[,] expected = Accord.Statistics.Models.Markov.
                        ForwardBackwardAlgorithm.Forward(hmm.Models[y], x, out scaling2, out logLikelihood2);

                    for (int i = 0; i < actual.GetLength(0); i++)
                        for (int j = 0; j < actual.GetLength(1); j++)
                        {
                            Assert.AreEqual(expected[i, j], actual[i, j], 1e-10);
                            Assert.IsFalse(Double.IsNaN(actual[i, j]));
                        }

                    Assert.AreEqual(logLikelihood1, logLikelihood2, 1e-10);

                    for (int i = 0; i < scaling1.Length; i++)
                        Assert.AreEqual(scaling1[i], scaling2[i], 1e-10);
                }
            }
        }
        public void LogForwardTest4()
        {
            var hmmc = Accord.Tests.Statistics.Models.Fields.
                MultivariateMarkovFunctionTest.CreateModel3();

            for (int c = 0; c < hmmc.Classes; c++)
            {
                var hmm = hmmc[c];

                var function = new MarkovMultivariateFunction(hmm);

                var sequences = Accord.Tests.Statistics.Models.Fields.
                    MultivariateMarkovFunctionTest.inputTest;

                for (int i = 0; i < sequences.Length; i++)
                {
                    var observations = sequences[i];

                    double expectedLogLikelihood;
                    double[,] expected = Accord.Statistics.Models.Markov
                        .ForwardBackwardAlgorithm.LogForward(hmm, observations, out expectedLogLikelihood);

                    double actualLogLikelihood;
                    double[,] actual = Accord.Statistics.Models.Fields
                        .ForwardBackwardAlgorithm.LogForward(function.Factors[0], observations, 0, out actualLogLikelihood);


                    Assert.IsTrue(expected.IsEqual(actual, 1e-10));

                    Assert.AreEqual(expectedLogLikelihood, actualLogLikelihood, 1e-6);
                    Assert.IsFalse(Double.IsNaN(actualLogLikelihood));
                }
            }
        }
        public void ForwardTest4()
        {
            var hmmc = Accord.Tests.Statistics.Models.Fields.
                MultivariateMarkovFunctionTest.CreateModel3();

            var hmm = hmmc[0];

            var function = new MarkovMultivariateFunction(hmm);

            var observations = Accord.Tests.Statistics.Models.Fields.
                MultivariateMarkovFunctionTest.inputTest[3];

            double expectedLogLikelihood;
            double[,] expected = Accord.Statistics.Models.Markov
                .ForwardBackwardAlgorithm.Forward(hmm, observations, out expectedLogLikelihood);

            double actualLogLikelihood;
            double[,] actual = Accord.Statistics.Models.Fields.
                ForwardBackwardAlgorithm.Forward(function.Factors[0], observations, 0, out actualLogLikelihood);


            Assert.IsTrue(expected.IsEqual(actual, 1e-10));


            Assert.AreEqual(expectedLogLikelihood, actualLogLikelihood, 1e-6);
            Assert.IsFalse(Double.IsNaN(actualLogLikelihood));

        }
        public void LogForwardTest3()
        {
            MultivariateNormalDistribution density = new MultivariateNormalDistribution(3);
            var hmm = new HiddenMarkovClassifier<MultivariateNormalDistribution>(2, new Ergodic(2), density);

            double[][][] inputs =
            {
                new [] { new double[] { 0, 1, 0 }, new double[] { 0, 1, 0 }, new double[] { 0, 1, 0 } },
                new [] { new double[] { 1, 6, 2 }, new double[] { 2, 1, 6 }, new double[] { 1, 1, 0 } },
                new [] { new double[] { 9, 1, 0 }, new double[] { 0, 1, 5 }, new double[] { 0, 0, 0 } },
            };

            int[] outputs = 
            {
                0, 0, 1
            };

            var function = new MarkovMultivariateFunction(hmm);

            var observations = inputs[0];

            double[,] expected = Matrix.Log(Accord.Statistics.Models.Fields.
                ForwardBackwardAlgorithm.Forward(function.Factors[0], observations, 0));

            double logLikelihood;
            double[,] actual = Accord.Statistics.Models.Fields.
                ForwardBackwardAlgorithm.LogForward(function.Factors[0], observations, 0, out logLikelihood);

            Assert.IsTrue(expected.IsEqual(actual, 1e-10));

            double p = 0;
            for (int i = 0; i < hmm[0].States; i++)
                p += Math.Exp(actual[observations.Length - 1, i]);

            Assert.AreEqual(Math.Exp(logLikelihood), p, 1e-8);
            Assert.IsFalse(double.IsNaN(p));
        }
        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);
        }
        public void GradientTest3()
        {
            var hmm = MultivariateNormalHiddenMarkovClassifierPotentialFunctionTest.CreateModel1();
            var function = new MarkovMultivariateFunction(hmm);

            var model = new HiddenConditionalRandomField<double[]>(function);
            var target = new ForwardBackwardGradient<double[]>(model);
            target.Regularization = 2;

            var inputs = inputs1;
            var outputs = outputs1;



            FiniteDifferences diff = new FiniteDifferences(function.Weights.Length);

            diff.Function = parameters => func(model, parameters, inputs, outputs, target.Regularization);

            double[] expected = diff.Compute(function.Weights);
            double[] actual = target.Gradient(function.Weights, inputs, outputs);


            for (int i = 0; i < actual.Length; i++)
            {
                Assert.AreEqual(expected[i], actual[i], 1e-3);

                Assert.IsFalse(double.IsNaN(actual[i]));
                Assert.IsFalse(double.IsNaN(expected[i]));
            }
        }
        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 SaveLoadTest()
        {
            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 },
            };

            double[][][] words = { hello, car, wardrobe };

            int[] labels = { 0, 1, 2 };

            var initial = new Independent
                          (
                new NormalDistribution(0, 1),
                new NormalDistribution(0, 1),
                new NormalDistribution(0, 1),
                new NormalDistribution(0, 1)
                          );

            int numberOfWords  = 3;
            int numberOfStates = 5;

            var classifier = new HiddenMarkovClassifier <Independent>
                             (
                classes: numberOfWords,
                topology: new Forward(numberOfStates),
                initial: initial
                             );

            var teacher = new HiddenMarkovClassifierLearning <Independent>(classifier,
                                                                           modelIndex => new BaumWelchLearning <Independent>(classifier.Models[modelIndex])
            {
                Tolerance      = 0.001,
                Iterations     = 100,
                FittingOptions = new IndependentOptions()
                {
                    InnerOption = new NormalOptions()
                    {
                        Regularization = 1e-5
                    }
                }
            }
                                                                           );

            double logLikelihood = teacher.Run(words, labels);

            var function = new MarkovMultivariateFunction(classifier);
            var hcrf     = new HiddenConditionalRandomField <double[]>(function);


            MemoryStream stream = new MemoryStream();

            hcrf.Save(stream);

            stream.Seek(0, SeekOrigin.Begin);

            var target = HiddenConditionalRandomField <double[]> .Load(stream);

            Assert.AreEqual(hcrf.Function.Factors.Length, target.Function.Factors.Length);
            for (int i = 0; i < hcrf.Function.Factors.Length; i++)
            {
                var e = hcrf.Function.Factors[i];
                var a = target.Function.Factors[i];
                Assert.AreEqual(e.Index, target.Function.Factors[i].Index);
                Assert.AreEqual(e.States, target.Function.Factors[i].States);

                Assert.AreEqual(e.EdgeParameters.Count, a.EdgeParameters.Count);
                Assert.AreEqual(e.EdgeParameters.Offset, a.EdgeParameters.Offset);
                Assert.AreEqual(e.FactorParameters.Count, a.FactorParameters.Count);
                Assert.AreEqual(e.FactorParameters.Offset, a.FactorParameters.Offset);

                Assert.AreEqual(e.OutputParameters.Count, a.OutputParameters.Count);
                Assert.AreEqual(e.OutputParameters.Offset, a.OutputParameters.Offset);
                Assert.AreEqual(e.StateParameters.Count, a.StateParameters.Count);
                Assert.AreEqual(e.StateParameters.Offset, a.StateParameters.Offset);

                Assert.AreEqual(target.Function, a.Owner);
                Assert.AreEqual(hcrf.Function, e.Owner);
            }

            Assert.AreEqual(hcrf.Function.Features.Length, target.Function.Features.Length);
            for (int i = 0; i < hcrf.Function.Factors.Length; i++)
            {
                Assert.AreEqual(hcrf.Function.Features[i].GetType(), target.Function.Features[i].GetType());
            }

            Assert.AreEqual(hcrf.Function.Outputs, target.Function.Outputs);

            for (int i = 0; i < hcrf.Function.Weights.Length; i++)
            {
                Assert.AreEqual(hcrf.Function.Weights[i], target.Function.Weights[i]);
            }
        }
        public void ComputeTest3()
        {
            var model = CreateModel3();

            var target = new MarkovMultivariateFunction(model);

            var hcrf = new HiddenConditionalRandomField<double[]>(target);


            double actual;
            double expected;

            for (int k = 0; k < 5; k++)
            {
                foreach (var x in sequences2)
                {
                    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.AreEqual(expected, actual, 1e-6);
                            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++)
                                {
                                    expected = Math.Exp(model[c].Transitions[i, j]) * model[c].Emissions[j].ProbabilityDensityFunction(x[t]);
                                    actual = Math.Exp(target.Factors[c].Compute(i, j, x, t, c));
                                    Assert.AreEqual(expected, actual, 1e-6);
                                    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 ComputeTest5()
        {
            var model = CreateModel3(states: 7);

            var target = new MarkovMultivariateFunction(model);

            double actual;
            double expected;

            double[][] x = { new double[] { 0, 1 }, new double[] { 3, 2 } };

            for (int c = 0; c < model.Classes; c++)
            {
                for (int i = 0; i < model[c].States; i++)
                {
                    // Check initial state transitions
                    expected = model.Priors[c] * Math.Exp(model[c].Probabilities[i]) * model[c].Emissions[i].ProbabilityDensityFunction(x[0]);
                    actual = Math.Exp(target.Factors[c].Compute(-1, i, x, 0, c));
                    Assert.AreEqual(expected, actual, 1e-6);
                    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++)
                        {
                            expected = Math.Exp(model[c].Transitions[i, j]) * model[c].Emissions[j].ProbabilityDensityFunction(x[t]);
                            actual = Math.Exp(target.Factors[c].Compute(i, j, x, t, c));
                            Assert.AreEqual(expected, actual, 1e-6);
                            Assert.IsFalse(double.IsNaN(actual));
                        }
                    }
                }
            }

            var hcrf = new HiddenConditionalRandomField<double[]>(target);

            for (int i = 0; i < inputTest.Length; i++)
            {
                int h = model.Compute(inputTest[i]);
                int c = hcrf.Compute(inputTest[i]);
                Assert.AreEqual(h, c);
            }
        }
        public void HiddenMarkovHiddenPotentialFunctionConstructorTest2()
        {
            var model = CreateModel2();

            var target = new MarkovMultivariateFunction(model);

            var features = target.Features;
            double[] weights = target.Weights;

            Assert.AreEqual(38, features.Length);
            Assert.AreEqual(38, weights.Length);

            int k = 0;
            for (int c = 0; c < model.Classes; c++)
            {
                Assert.AreEqual(Math.Log(model.Priors[c]), weights[k++]);

                for (int i = 0; i < model[c].States; i++)
                    Assert.AreEqual(model[c].Probabilities[i], weights[k++]);

                for (int i = 0; i < model[c].States; i++)
                    for (int j = 0; j < model[c].States; j++)
                        Assert.AreEqual(model[c].Transitions[i, j], weights[k++]);

                for (int i = 0; i < model[c].States; i++)
                    for (int j = 0; j < model[c].Dimension; j++)
                    {
                        double mean = model[c].Emissions[i].Mean[j];
                        double var = model[c].Emissions[i].Variance[j];

                        double l2ps = System.Math.Log(2 * System.Math.PI * var);

                        Assert.AreEqual(-0.5 * (l2ps + (mean * mean) / var), weights[k++]);
                        Assert.AreEqual(mean / var, weights[k++]);
                        Assert.AreEqual(-1.0 / (2 * var), weights[k++]);
                    }
            }

        }
        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 GradientDeoptimizeTest3()
        {
            double[][][] sequences2;
            int[] labels2;
            var hmm = CreateModel3(out sequences2, out labels2);
            var function = new MarkovMultivariateFunction(hmm);

#pragma warning disable 0618
            function.Deoptimize();
#pragma warning restore 0618

            var model = new HiddenConditionalRandomField<double[]>(function);
            var target = new ForwardBackwardGradient<double[]>(model);
            target.Regularization = 2;

            var inputs = sequences2;
            var outputs = labels2;


            FiniteDifferences diff = new FiniteDifferences(function.Weights.Length);

            diff.Function = parameters => func(model, parameters, inputs, outputs, target.Regularization);

            double[] expected = diff.Compute(function.Weights);
            double[] actual = target.Gradient(function.Weights, inputs, outputs);


            for (int i = 0; i < actual.Length; i++)
            {
                double e = expected[i];
                double a = actual[i];
                Assert.AreEqual(e, a, 1e-3);

                Assert.IsFalse(double.IsNaN(actual[i]));
                Assert.IsFalse(double.IsNaN(expected[i]));
            }
        }
        public void ComputeTest2()
        {
            double[][][] sequences;
            int[] labels;
            var model = CreateModel2(out sequences, out labels);

            var target = new MarkovMultivariateFunction(model);
            var hcrf = new HiddenConditionalRandomField<double[]>(target);


            double actual;
            double expected;

            double[][] x = { new double[] { 0, 1.7 }, new double[] { 2, 2.1 } };

            for (int c = 0; c < model.Classes; c++)
            {
                for (int i = 0; i < model[c].States; i++)
                {
                    // Check initial state transitions
                    expected = model.Priors[c] * Math.Exp(model[c].Probabilities[i]) * model[c].Emissions[i].ProbabilityDensityFunction(x[0]);
                    actual = Math.Exp(target.Factors[c].Compute(-1, i, x, 0, c));
                    Assert.AreEqual(expected, actual, 1e-6);
                    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.AreEqual(expected, actual, 1e-6);
                            Assert.IsFalse(double.IsNaN(actual));
                        }
                    }
                }

                actual = model.LogLikelihood(x, c);
                expected = hcrf.LogLikelihood(x, c);
                Assert.AreEqual(expected, actual);
                Assert.IsFalse(double.IsNaN(actual));
            }
        }
        public void LogBackwardTest2()
        {
            HiddenMarkovClassifier<Independent> hmm = IndependentMarkovClassifierPotentialFunctionTest
                .CreateModel3();

            MarkovMultivariateFunction function = new MarkovMultivariateFunction(hmm);

            double[][][] observations = IndependentMarkovClassifierPotentialFunctionTest.sequences2;
            int[] labels = IndependentMarkovClassifierPotentialFunctionTest.labels2;

            foreach (double[][] x in observations)
            {
                foreach (int y in labels)
                {
                    double[,] actual = new double[x.Length, 5];
                    Accord.Statistics.Models.Fields.
                        ForwardBackwardAlgorithm.LogBackward(function.Factors[y], x, y, actual);

                    double[,] expected = new double[x.Length, 5];
                    Accord.Statistics.Models.Markov.
                        ForwardBackwardAlgorithm.LogBackward(hmm.Models[y], x, expected);

                    for (int i = 0; i < actual.GetLength(0); i++)
                        for (int j = 0; j < actual.GetLength(1); j++)
                        {
                            Assert.AreEqual(expected[i, j], actual[i, j], 1e-10);
                            Assert.IsFalse(Double.IsNaN(actual[i, j]));
                        }
                }
            }
        }
        public void GradientTest()
        {
            // Creates a sequence classifier containing 2 hidden Markov Models
            //  with 2 states and an underlying Normal distribution as density.
            MultivariateNormalDistribution density = new MultivariateNormalDistribution(3);
            var hmm = new HiddenMarkovClassifier<MultivariateNormalDistribution>(2, new Ergodic(2), density);

            double[][][] inputs =
            {
                new [] { new double[] { 0, 1, 0 }, new double[] { 0, 1, 0 }, new double[] { 0, 1, 0 } },
                new [] { new double[] { 1, 6, 2 }, new double[] { 2, 1, 6 }, new double[] { 1, 1, 0 } },
                new [] { new double[] { 9, 1, 0 }, new double[] { 0, 1, 5 }, new double[] { 0, 0, 0 } },
            };

            int[] outputs = 
            {
                0, 0, 1
            };

            var function = new MarkovMultivariateFunction(hmm);

            var model = new HiddenConditionalRandomField<double[]>(function);
            var target = new ForwardBackwardGradient<double[]>(model);

            FiniteDifferences diff = new FiniteDifferences(function.Weights.Length);

            diff.Function = parameters => func(model, parameters, inputs, outputs);

            double[] expected = diff.Compute(function.Weights);
            double[] actual = target.Gradient(function.Weights, inputs, outputs);


            for (int i = 0; i < actual.Length; i++)
            {
                Assert.AreEqual(expected[i], actual[i], 0.05);
                Assert.IsFalse(double.IsNaN(actual[i]));
                Assert.IsFalse(double.IsNaN(expected[i]));
            }
        }
        public void ComputeDeoptimizeTest3()
        {
            double[][][] sequences;
            int[] labels;
            var model = CreateModel3(out sequences, out labels);

            var target = new MarkovMultivariateFunction(model);

#pragma warning disable 0618
            target.Deoptimize();
#pragma warning restore 0618

            var hcrf = new HiddenConditionalRandomField<double[]>(target);


            Assert.AreEqual(2, model.Priors.Length);
            Assert.AreEqual(1 / 2.0, model.Priors[0]);
            Assert.AreEqual(1 / 2.0, model.Priors[1]);

            check4(sequences, model, target, hcrf);
        }
        public void ComputeDeoptimizeTest4()
        {
            int[] labels;
            double[][][] words;
            var model = CreateModel4(out words, out labels, false);

            var target = new MarkovMultivariateFunction(model);

#pragma warning disable 0618
            target.Deoptimize();
#pragma warning restore 0618

            var hcrf = new HiddenConditionalRandomField<double[]>(target);


            Assert.AreEqual(3, model.Priors.Length);
            Assert.AreEqual(1 / 3.0, model.Priors[0]);
            Assert.AreEqual(1 / 3.0, model.Priors[1]);
            Assert.AreEqual(1 / 3.0, model.Priors[2]);

            check4(words, model, target, hcrf);
        }
        public void LogForwardTest()
        {
            double[][][] observations;
            int[] labels;
            var hmm = IndependentMarkovFunctionTest.CreateModel2(out observations, out labels);

            MarkovMultivariateFunction function = new MarkovMultivariateFunction(hmm, includePriors: false);

            foreach (double[][] x in observations)
            {
                foreach (int y in labels)
                {
                    double[,] actual = new double[5, 2];
                    Accord.Statistics.Models.Fields.
                        ForwardBackwardAlgorithm.LogForward(function.Factors[y], x, y, actual);

                    double[,] expected = new double[5, 2];
                    Accord.Statistics.Models.Markov.
                        ForwardBackwardAlgorithm.LogForward(hmm.Models[y], x, expected);

                    for (int i = 0; i < actual.GetLength(0); i++)
                        for (int j = 0; j < actual.GetLength(1); j++)
                            Assert.AreEqual(expected[i, j], actual[i, j], 1e-10);
                }
            }
        }
        public void GradientTest4()
        {
            var hmm = IndependentMarkovClassifierPotentialFunctionTest.CreateModel2();
            var function = new MarkovMultivariateFunction(hmm);

            var model = new HiddenConditionalRandomField<double[]>(function);
            var target = new ForwardBackwardGradient<double[]>(model);
            target.Regularization = 0;

            FiniteDifferences diff = new FiniteDifferences(function.Weights.Length);

            diff.Function = parameters => func(model, parameters,
                IndependentMarkovClassifierPotentialFunctionTest.sequences,
                IndependentMarkovClassifierPotentialFunctionTest.labels);

            double[] expected = diff.Compute(function.Weights);
            double[] actual = target.Gradient(function.Weights,
                IndependentMarkovClassifierPotentialFunctionTest.sequences,
                IndependentMarkovClassifierPotentialFunctionTest.labels);


            for (int i = 0; i < actual.Length; i++)
            {
                if (double.IsNaN(expected[i]))
                    continue;

                Assert.AreEqual(expected[i], actual[i], 1e-5);
                Assert.IsFalse(double.IsNaN(actual[i]));
            }
        }
        public void GradientTest2()
        {
            var hmm = CreateModel3();
            var function = new MarkovMultivariateFunction(hmm);

            var model = new HiddenConditionalRandomField<double[]>(function);
            var target = new ForwardBackwardGradient<double[]>(model);

            var inputs = sequences2;
            var outputs = labels2;

            double[] actual = target.Gradient(function.Weights, inputs, outputs);

            FiniteDifferences diff = new FiniteDifferences(function.Weights.Length);
            diff.Function = parameters => func(model, parameters, inputs, outputs);
            double[] expected = diff.Compute(function.Weights);


            for (int i = 0; i < actual.Length; i++)
            {
                Assert.AreEqual(expected[i], actual[i], 1e-3);
                Assert.IsFalse(double.IsNaN(actual[i]));
                Assert.IsFalse(double.IsNaN(expected[i]));
            }
        }
Beispiel #45
0
        public void ComputeTest3()
        {
            var hmm = MultivariateMarkovFunctionTest.CreateModel1();

            var owner = new MarkovMultivariateFunction(hmm);


            double[][] x = 
            { 
                new double[] { 0 },
                new double[] { 1 },
                new double[] { 3 },
                new double[] { 1 },
                new double[] { 2 },
                new double[] { 8 },
                new double[] { 0 },
                new double[] { 10 },
                new double[] { System.Math.PI },
            };

            foreach (var factor in owner.Factors)
            {
                for (int y = 0; y < owner.Outputs; y++)
                {
                    double[,] fwd = Accord.Statistics.Models.Fields
                        .ForwardBackwardAlgorithm.Forward(factor, x, y);

                    double[,] bwd = Accord.Statistics.Models.Fields
                        .ForwardBackwardAlgorithm.Backward(factor, x, y);

                    double[,] lnfwd = Accord.Statistics.Models.Fields
                        .ForwardBackwardAlgorithm.LogForward(factor, x, y);

                    double[,] lnbwd = Accord.Statistics.Models.Fields
                        .ForwardBackwardAlgorithm.LogBackward(factor, x, y);


                    for (int i = 0; i < fwd.GetLength(0); i++)
                        for (int j = 0; j < fwd.GetLength(1); j++)
                            Assert.AreEqual(System.Math.Log(fwd[i, j]), lnfwd[i, j], 1e-10);

                    for (int i = 0; i < bwd.GetLength(0); i++)
                        for (int j = 0; j < bwd.GetLength(1); j++)
                            Assert.AreEqual(System.Math.Log(bwd[i, j]), lnbwd[i, j], 1e-10);


                    foreach (var feature in factor)
                    {
                        double expected = System.Math.Log(feature.Marginal(fwd, bwd, x, y));
                        double actual = feature.LogMarginal(lnfwd, lnbwd, x, y);

                        Assert.AreEqual(expected, actual, 1e-10);
                        Assert.IsFalse(Double.IsNaN(actual));
                    }

                }
            }
        }
        public void LogForwardGesturesPriorsTest()
        {
            int[] labels;
            double[][][] words;
            var classifier = IndependentMarkovFunctionTest.CreateModel4(out words, out labels, true);

            var function = new MarkovMultivariateFunction(classifier);
            var target = new HiddenConditionalRandomField<double[]>(function);

            foreach (var word in words)
            {
                for (int c = 0; c < 3; c++)
                {
                    var actual = Accord.Statistics.Models.Fields.ForwardBackwardAlgorithm.LogForward(
                        target.Function.Factors[c], word, c);

                    var expected = Accord.Statistics.Models.Markov.ForwardBackwardAlgorithm.LogForward(
                        classifier[c], word);

                    for (int i = 0; i < actual.GetLength(0); i++)
                    {
                        for (int j = 0; j < actual.GetLength(1); j++)
                        {
                            double a = actual[i, j];
                            double e = expected[i, j];

                            // TODO: Verify if is possible to reduce this tolerance
                            Assert.IsTrue(e.IsRelativelyEqual(a, 0.1));
                        }
                    }
                }
            }
        }
        public void LogForwardGesturesPriorsDeoptimizedTest()
        {
            int[] labels;
            double[][][] words;
            var classifier = IndependentMarkovFunctionTest.CreateModel4(out words, out labels, true);

            var deopFun = new MarkovMultivariateFunction(classifier);
            deopFun.Deoptimize();
            var target1 = new HiddenConditionalRandomField<double[]>(deopFun);

            var function = new MarkovMultivariateFunction(classifier);
            var target2 = new HiddenConditionalRandomField<double[]>(function);

            foreach (var word in words)
            {
                for (int c = 0; c < 3; c++)
                {
                    for (int y = 0; y < 3; y++)
                    {
                        var actual = Accord.Statistics.Models.Fields.ForwardBackwardAlgorithm
                            .LogForward(target1.Function.Factors[c], word, y);

                        var expected = Accord.Statistics.Models.Fields.ForwardBackwardAlgorithm
                            .LogForward(target2.Function.Factors[c], word, y);

                        for (int i = 0; i < actual.GetLength(0); i++)
                        {
                            for (int j = 0; j < actual.GetLength(1); j++)
                            {
                                double a = actual[i, j];
                                double e = expected[i, j];
                                Assert.IsTrue(e.IsRelativelyEqual(a, 0.1));
                            }

                        }
                    }
                }
            }
        }
        public void ComputeTest4()
        {
            int[] labels;
            double[][][] words;
            HiddenMarkovClassifier<Independent<NormalDistribution>> model =
                CreateModel4(out words, out labels, false);

            var target = new MarkovMultivariateFunction(model);

            var hcrf = new HiddenConditionalRandomField<double[]>(target);


            Assert.AreEqual(3, model.Priors.Length);
            Assert.AreEqual(1 / 3.0, model.Priors[0]);
            Assert.AreEqual(1 / 3.0, model.Priors[1]);
            Assert.AreEqual(1 / 3.0, model.Priors[2]);

            check4(words, model, target, hcrf);
        }
        public void ComputeTest()
        {
            var model = CreateModel1();

            var target = new MarkovMultivariateFunction(model);

            double actual;
            double expected;

            double[][] x = { new double[] { 0 }, new double[] { 1 } };

            for (int c = 0; c < model.Classes; c++)
            {
                for (int i = 0; i < model[c].States; i++)
                {
                    // Check initial state transitions
                    expected = model.Priors[c] * Math.Exp(model[c].Probabilities[i]) * model[c].Emissions[i].ProbabilityDensityFunction(x[0]);
                    actual = Math.Exp(target.Factors[c].Compute(-1, i, x, 0, c));
                    Assert.AreEqual(expected, actual, 1e-6);
                    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++)
                        {
                            expected = Math.Exp(model[c].Transitions[i, j]) * model[c].Emissions[j].ProbabilityDensityFunction(x[t]);
                            actual = Math.Exp(target.Factors[c].Compute(i, j, x, t, c));
                            Assert.AreEqual(expected, actual, 1e-6);
                            Assert.IsFalse(double.IsNaN(actual));
                        }
                    }
                }
            }
        }
        public void SaveLoadTest()
        {
            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 },
            };

            double[][][] words = { hello, car, wardrobe };

            int[] labels = { 0, 1, 2 };

            var initial = new Independent
            (
                new NormalDistribution(0, 1),
                new NormalDistribution(0, 1),
                new NormalDistribution(0, 1),
                new NormalDistribution(0, 1)
            );

            int numberOfWords = 3;
            int numberOfStates = 5;

            var classifier = new HiddenMarkovClassifier<Independent>
            (
               classes: numberOfWords,
               topology: new Forward(numberOfStates),
               initial: initial
            );

            var teacher = new HiddenMarkovClassifierLearning<Independent>(classifier,
                modelIndex => new BaumWelchLearning<Independent>(classifier.Models[modelIndex])
                {
                    Tolerance = 0.001,
                    Iterations = 100,
                    FittingOptions = new IndependentOptions()
                    {
                        InnerOption = new NormalOptions() { Regularization = 1e-5 }
                    }
                }
            );

            double logLikelihood = teacher.Run(words, labels);

            var function = new MarkovMultivariateFunction(classifier);
            var hcrf = new HiddenConditionalRandomField<double[]>(function);


            MemoryStream stream = new MemoryStream();

            hcrf.Save(stream);

            stream.Seek(0, SeekOrigin.Begin);

            var target = HiddenConditionalRandomField<double[]>.Load(stream);

            Assert.AreEqual(hcrf.Function.Factors.Length, target.Function.Factors.Length);
            for (int i = 0; i < hcrf.Function.Factors.Length; i++)
            {
                var e = hcrf.Function.Factors[i];
                var a = target.Function.Factors[i];
                Assert.AreEqual(e.Index, target.Function.Factors[i].Index);
                Assert.AreEqual(e.States, target.Function.Factors[i].States);

                Assert.AreEqual(e.EdgeParameters.Count, a.EdgeParameters.Count);
                Assert.AreEqual(e.EdgeParameters.Offset, a.EdgeParameters.Offset);
                Assert.AreEqual(e.FactorParameters.Count, a.FactorParameters.Count);
                Assert.AreEqual(e.FactorParameters.Offset, a.FactorParameters.Offset);

                Assert.AreEqual(e.OutputParameters.Count, a.OutputParameters.Count);
                Assert.AreEqual(e.OutputParameters.Offset, a.OutputParameters.Offset);
                Assert.AreEqual(e.StateParameters.Count, a.StateParameters.Count);
                Assert.AreEqual(e.StateParameters.Offset, a.StateParameters.Offset);

                Assert.AreEqual(target.Function, a.Owner);
                Assert.AreEqual(hcrf.Function, e.Owner);    
            }
            
            Assert.AreEqual(hcrf.Function.Features.Length, target.Function.Features.Length);
            for (int i = 0; i < hcrf.Function.Factors.Length; i++)
                Assert.AreEqual(hcrf.Function.Features[i].GetType(), target.Function.Features[i].GetType());

            Assert.AreEqual(hcrf.Function.Outputs, target.Function.Outputs);

            for (int i = 0; i < hcrf.Function.Weights.Length; i++)
                Assert.AreEqual(hcrf.Function.Weights[i], target.Function.Weights[i]);    
        }
        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);
        }
        public void NumberOfFeaturesTest()
        {
            Independent initial = new Independent(
                      new GeneralDiscreteDistribution(46), // output,
                      new NormalDistribution(0, 1),        // headAngle, 
                      new NormalDistribution(0, 1),        // handAngle, 
                      new NormalDistribution(0, 1),        // relHandX, 
                      new NormalDistribution(0, 1)         // relHandY, 
            );



            var model = new HiddenMarkovClassifier<Independent>(
                classes: 13, topology: new Forward(5), initial: initial);

            var function = new MarkovMultivariateFunction(model);
            var field = new HiddenConditionalRandomField<double[]>(function);



            int discreteDistributions = 1;
            int continuousDistributions = 4;
            int symbols = 46;
            int states = 5;
            int classes = 13;
            int expected = classes *
                (1 + states + states * states +
                states * discreteDistributions * symbols +
                states * continuousDistributions * 3);

            Assert.AreEqual(expected, field.Function.Features.Length);
            Assert.AreEqual(expected, field.Function.Weights.Length);
            Assert.AreEqual(4173, expected);
        }