public void LogBackwardTest()
        {
            HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov.
                                    ForwardBackwardAlgorithmTest.CreateModel2();


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

            double logLikelihood;

            double[,] expected = Matrix.Log(
                ForwardBackwardAlgorithm.Backward(hmm, observations));

            double[,] actual =
                ForwardBackwardAlgorithm.LogBackward(hmm, observations, out logLikelihood);

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


            foreach (double e in actual)
            {
                Assert.IsFalse(double.IsNaN(e));
            }

            double p = System.Math.Exp(logLikelihood);

            Assert.AreEqual(0.054814695, p, 1e-8);
            Assert.IsFalse(double.IsNaN(p));
        }
        public void BackwardTest2()
        {
            HiddenMarkovModel hmm = CreateModel3();

            //                     L  L  R  R
            int[] observations = { 0, 0, 1, 1 };

            double[,] actual = ForwardBackwardAlgorithm.Backward(hmm, observations);

            // Backward matrices from R's HMM package are
            // transposed in relation to the framework's:

            Assert.AreEqual(4, actual.GetLength(0));
            Assert.AreEqual(2, actual.GetLength(1));

            Assert.AreEqual(0.128982144, actual[0, 0], 1e-10);
            Assert.AreEqual(0.082407504, actual[0, 1], 1e-10);

            Assert.AreEqual(0.196816, actual[1, 0], 1e-10);
            Assert.AreEqual(0.453856, actual[1, 1], 1e-10);

            Assert.AreEqual(0.376, actual[2, 0], 1e-10);
            Assert.AreEqual(0.691, actual[2, 1], 1e-10);

            Assert.AreEqual(1, actual[3, 0]);
            Assert.AreEqual(1, actual[3, 1]);

            foreach (double p in actual)
            {
                Assert.IsFalse(double.IsNaN(p));
            }
        }
        public void BackwardTest()
        {
            HiddenMarkovModel hmm = CreateModel2();

            //                     A  B  B  A
            int[] observations = { 0, 1, 1, 0 };

            double logLikelihood;

            double[,] actual = ForwardBackwardAlgorithm.Backward(hmm, observations, out logLikelihood);

            var A = Matrix.Exp(hmm.Transitions);
            var B = Matrix.Exp(hmm.Emissions);
            var P = Matrix.Exp(hmm.Probabilities);

            double a30 = 1;
            double a31 = 1;

            double a20 = A[0, 0] * B[0, 0] * a30 + A[0, 1] * B[1, 0] * a31;
            double a21 = A[1, 0] * B[0, 0] * a30 + A[1, 1] * B[1, 0] * a31;

            double a10 = A[0, 0] * B[0, 1] * a20 + A[0, 1] * B[1, 1] * a21;
            double a11 = A[1, 0] * B[0, 1] * a20 + A[1, 1] * B[1, 1] * a21;

            double a00 = A[0, 0] * B[0, 1] * a10 + A[0, 1] * B[1, 1] * a11;
            double a01 = A[1, 0] * B[0, 1] * a10 + A[1, 1] * B[1, 1] * a11;


            Assert.AreEqual(actual[0, 0], a00);
            Assert.AreEqual(actual[0, 1], a01);

            Assert.AreEqual(actual[1, 0], a10);
            Assert.AreEqual(actual[1, 1], a11);

            Assert.AreEqual(actual[2, 0], a20);
            Assert.AreEqual(actual[2, 1], a21);

            Assert.AreEqual(actual[3, 0], a30);
            Assert.AreEqual(actual[3, 1], a31);


            double p = 0;

            for (int i = 0; i < hmm.States; i++)
            {
                p += actual[0, i] * P[i] * B[i, observations[0]];
            }

            Assert.AreEqual(0.054814695, p, 1e-8);
            Assert.IsFalse(double.IsNaN(p));

            p = System.Math.Exp(logLikelihood);
            Assert.AreEqual(0.054814695, p, 1e-8);
            Assert.IsFalse(double.IsNaN(p));
        }
        public void ForwardBackwardTest()
        {
            HiddenMarkovModel hmm = CreateModel1();

            //                     G  G  C  A
            int[] observations = { 2, 2, 1, 0 };

            double fwdLogLikelihood;

            double[,] fwd = ForwardBackwardAlgorithm.Forward(hmm, observations, out fwdLogLikelihood);

            double bwdLogLikelihood;

            double[,] bwd = ForwardBackwardAlgorithm.Backward(hmm, observations, out bwdLogLikelihood);

            Assert.AreEqual(fwdLogLikelihood, bwdLogLikelihood, 1e-10); // -5.5614629361549142
        }
        public void LogBackwardTest2()
        {
            HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov.
                                    ForwardBackwardAlgorithmTest.CreateModel3();

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

            double[,] expected = Matrix.Log(
                ForwardBackwardAlgorithm.Backward(hmm, observations));

            double[,] actual =
                ForwardBackwardAlgorithm.LogBackward(hmm, observations);

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

            foreach (double p in actual)
            {
                Assert.IsFalse(double.IsNaN(p));
            }
        }
        public void ForwardBackwardGenericTest()
        {
            var discreteModel = CreateModel1();
            var genericModel  = CreateModel4();

            int[]      discreteObservations = { 2, 2, 1, 0 };
            double[][] genericObservations  =
            {
                new double[] { 2 }, new double[] { 2 },
                new double[] { 1 }, new double[] { 0 }
            };

            double[] scaling = new double[3];

            double discreteFwdLogLikelihood;

            double[,] discreteFwd = ForwardBackwardAlgorithm.Forward(discreteModel,
                                                                     discreteObservations, out scaling, out discreteFwdLogLikelihood);

            double[,] discreteBwd = ForwardBackwardAlgorithm.Backward(discreteModel,
                                                                      discreteObservations, scaling);

            double genericFwdLogLikelihood;

            double[,] genericFwd = ForwardBackwardAlgorithm.Forward(genericModel,
                                                                    genericObservations, out scaling, out genericFwdLogLikelihood);

            double[,] genericBwd = ForwardBackwardAlgorithm.Backward(genericModel,
                                                                     genericObservations, scaling);

            Assert.AreEqual(discreteFwdLogLikelihood, genericFwdLogLikelihood);

            for (int i = 0; i < discreteFwd.GetLength(0); i++)
            {
                for (int j = 0; j < discreteFwd.GetLength(1); j++)
                {
                    Assert.AreEqual(discreteFwd[i, j], genericFwd[i, j]);
                    Assert.AreEqual(discreteBwd[i, j], genericBwd[i, j]);
                }
            }
        }
예제 #7
0
        private double[] gradient(T[][] observations, int[][] labels)
        {
            int N = observations.Length;

            var function = model.Function;
            var states   = model.States;

            double[] g = new double[function.Weights.Length];


            // Compute sequence probabilities
            var P = new double[N][, ][];

            for (int i = 0; i < N; i++)
            {
                var Pi = P[i] = new double[states + 1, states][];

                T[]    x   = observations[i];
                var    fwd = ForwardBackwardAlgorithm.Forward(function.Factors[0], x, 0);
                var    bwd = ForwardBackwardAlgorithm.Backward(function.Factors[0], x, 0);
                double z   = partition(fwd, x);

                for (int prev = -1; prev < states; prev++)
                {
                    for (int next = 0; next < states; next++)
                    {
                        double[] Pis = new double[x.Length];
                        for (int t = 0; t < x.Length; t++)
                        {
                            Pis[t] = p(prev, next, x, t, fwd, bwd, function) / z;
                        }

                        Pi[prev + 1, next] = Pis;
                    }
                }
            }

            // Compute the gradient w.r.t. each feature
            //  function in the model's potential function.
            for (int k = 0; k < g.Length; k++)
            {
                var feature = function.Features[k];

                double sum1 = 0.0, sum2 = 0.0;
                for (int i = 0; i < N; i++)
                {
                    T[]   x  = observations[i];
                    int[] y  = labels[i];
                    var   Pi = P[i];

                    // Compute first term of the partial derivative
                    sum1 += feature.Compute(-1, y[0], x, 0);
                    for (int t = 1; t < x.Length; t++)
                    {
                        sum1 += feature.Compute(y[t - 1], y[t], x, t);
                    }

                    // Compute second term of the partial derivative
                    for (int prev = -1; prev < states; prev++)
                    {
                        for (int next = 0; next < states; next++)
                        {
                            double[] Pis = Pi[prev + 1, next];

                            for (int t = 0; t < Pis.Length; t++)
                            {
                                sum2 += feature.Compute(prev, next, x, t) * Pis[t];
                            }
                        }
                    }
                }

                g[k] = -(sum1 - sum2);
            }

            return(g);
        }
예제 #8
0
 /// <summary>
 ///   Computes the forward and backward probabilities matrices
 ///   for a given observation referenced by its index in the
 ///   input training data.
 /// </summary>
 /// <param name="index">The index of the observation in the input training data.</param>
 /// <param name="fwd">Returns the computed forward probabilities matrix.</param>
 /// <param name="bwd">Returns the computed backward probabilities matrix.</param>
 /// <param name="scaling">Returns the scaling parameters used during calculations.</param>
 protected override void ComputeForwardBackward(int index, out double[,] fwd, out double[,] bwd,
                                                out double[] scaling)
 {
     fwd = ForwardBackwardAlgorithm.Forward(model, continuousObservations[index], out scaling);
     bwd = ForwardBackwardAlgorithm.Backward(model, continuousObservations[index], scaling);
 }
예제 #9
0
        private double[] gradient(T[][] observations, int[][] labels, double[] g)
        {
            var model    = Model;
            var function = model.Function;
            int states   = model.States;
            int n        = observations.Length;
            int d        = Model.Function.Weights.Length;
            int Tmax     = observations.Max(x => x.Length);
            int progress = 0;

            g.Clear();


            // Compute sequence probabilities
            Parallel.For(0, observations.Length, ParallelOptions,

                         () =>
            {
                // Create thread-local storage
                var work = new double[states + 1, states][];
                for (int j = 0; j < states + 1; j++)
                {
                    for (int k = 0; k < states; k++)
                    {
                        work[j, k] = new double[Tmax];
                    }
                }

                return(new
                {
                    bwd = new double[Tmax, states],
                    fwd = new double[Tmax, states],
                    sum1 = new double[d],
                    sum2 = new double[d],
                    work = work,
                    count = new int[] { 0 }
                });
            },

                         (i, state, local) =>
            {
                T[] x    = observations[i];
                var fwd  = local.fwd;
                var bwd  = local.bwd;
                var sum1 = local.sum1;
                var sum2 = local.sum2;
                var work = local.work;
                ForwardBackwardAlgorithm.Forward(function.Factors[0], x, fwd);
                ForwardBackwardAlgorithm.Backward(function.Factors[0], x, bwd);
                double z = partition(fwd, x);

                for (int prev = -1; prev < states; prev++)
                {
                    for (int next = 0; next < states; next++)
                    {
                        double[] Pis = work[prev + 1, next];
                        for (int t = 0; t < x.Length; t++)
                        {
                            Pis[t] = p(prev, next, x, t, fwd, bwd, function) / z;
                        }
                    }
                }

                // Compute the gradient w.r.t. each feature
                //  function in the model's potential function.

                int[] y = labels[i];

                Parallel.For(0, g.Length, ParallelOptions, k =>
                {
                    IFeature <T> feature = function.Features[k];

                    // Compute first term of the partial derivative
                    sum1[k] += feature.Compute(-1, y[0], x, 0);
                    for (int t = 1; t < x.Length; t++)
                    {
                        sum1[k] += feature.Compute(y[t - 1], y[t], x, t);
                    }

                    // Compute second term of the partial derivative
                    for (int prev = -1; prev < states; prev++)
                    {
                        for (int next = 0; next < states; next++)
                        {
                            double[] Pis = work[prev + 1, next];
                            for (int t = 0; t < Pis.Length; t++)
                            {
                                sum2[k] += feature.Compute(prev, next, x, t) * Pis[t];
                            }
                        }
                    }
                });

                local.count[0]++;
                return(local);
            },

                         (local) =>
            {
                lock (g)
                {
                    for (int k = 0; k < g.Length; k++)
                    {
                        g[k] -= (local.sum1[k] - local.sum2[k]);
                    }
                    progress += local.count[0];
                }
            }
                         );

            return(g);
        }