Forward-Backward algorithms for Hidden Markov Models.
        /// <summary>
        ///   Computes Forward probabilities for a given hidden Markov model and a set of observations.
        /// </summary>
        public static double[,] LogForward <TDistribution>(HiddenMarkovModel <TDistribution> model, double[][] observations, out double logLikelihood)
        where TDistribution : IDistribution
        {
            int T      = observations.Length;
            int states = model.States;

            double[,] lnFwd = new double[T, states];

            ForwardBackwardAlgorithm.LogForward <TDistribution>(model, observations, lnFwd);

            logLikelihood = Double.NegativeInfinity;
            for (int i = 0; i < states; i++)
            {
                logLikelihood = Special.LogSum(logLikelihood, lnFwd[observations.Length - 1, i]);
            }

            return(lnFwd);
        }
        /// <summary>
        ///   Computes Forward probabilities for a given hidden Markov model and a set of observations.
        /// </summary>
        public static double[,] Forward <TDistribution>(HiddenMarkovModel <TDistribution> model, double[][] observations, out double logLikelihood)
        where TDistribution : IDistribution
        {
            int T = observations.Length;

            double[] coefficients = new double[T];
            double[,] fwd = new double[T, model.States];

            ForwardBackwardAlgorithm.Forward <TDistribution>(model, observations, coefficients, fwd);

            logLikelihood = 0;
            for (int i = 0; i < coefficients.Length; i++)
            {
                logLikelihood += Math.Log(coefficients[i]);
            }

            return(fwd);
        }
Beispiel #3
0
        /// <summary>
        ///   Calculates the log-likelihood that this model has generated the given sequence.
        /// </summary>
        ///
        /// <remarks>
        ///   Evaluation problem. Given the HMM  M = (A, B, pi) and  the observation
        ///   sequence O = {o1, o2, ..., oK}, calculate the probability that model
        ///   M has generated sequence O. This can be computed efficiently using the
        ///   either the Viterbi or the Forward algorithms.
        /// </remarks>
        ///
        /// <param name="observations">
        ///   A sequence of observations.
        /// </param>
        ///
        /// <returns>
        ///   The log-likelihood that the given sequence has been generated by this model.
        /// </returns>
        ///
        public double Evaluate(int[] observations)
        {
            if (observations == null)
            {
                throw new ArgumentNullException("observations");
            }

            if (observations.Length == 0)
            {
                return(Double.NegativeInfinity);
            }

            // Forward algorithm
            double logLikelihood;

            // Compute forward probabilities
            ForwardBackwardAlgorithm.LogForward(this, observations, out logLikelihood);

            // Return the sequence probability
            return(logLikelihood);
        }
        /// <summary>
        ///   Calculates the probability that this model has generated the given sequence.
        /// </summary>
        /// <remarks>
        ///   Evaluation problem. Given the HMM  M = (A, B, pi) and  the observation
        ///   sequence O = {o1, o2, ..., oK}, calculate the probability that model
        ///   M has generated sequence O. This can be computed efficiently using the
        ///   either the Viterbi or the Forward algorithms.
        /// </remarks>
        /// <param name="observations">
        ///   A sequence of observations.
        /// </param>
        /// <param name="logarithm">
        ///   True to return the log-likelihood, false to return
        ///   the likelihood. Default is false.
        /// </param>
        /// <returns>
        ///   The probability that the given sequence has been generated by this model.
        /// </returns>
        public double Evaluate(int[] observations, bool logarithm)
        {
            if (observations == null)
            {
                throw new ArgumentNullException("observations");
            }

            if (observations.Length == 0)
            {
                return(0.0);
            }

            // Forward algorithm
            double logLikelihood;

            // Compute forward probabilities
            ForwardBackwardAlgorithm.Forward(this, observations, out logLikelihood);

            // Return the sequence probability
            return(logarithm ? logLikelihood : System.Math.Exp(logLikelihood));
        }
Beispiel #5
0
        /// <summary>
        ///   Predicts the next observations occurring after a given observation sequence.
        /// </summary>
        ///
        /// <param name="observations">A sequence of observations. Predictions will be made regarding
        ///   the next observations that should be coming after the last observation in this sequence.</param>
        /// <param name="next">The number of observations to be predicted. Default is 1.</param>
        /// <param name="logLikelihoods">The log-likelihood of the different symbols for each predicted
        ///   next observations. In order to convert those values to probabilities, exponentiate the
        ///   values in the vectors (using the Exp function) and divide each value by their vector's sum.</param>
        /// <param name="logLikelihood">The log-likelihood of the given sequence, plus the predicted
        ///   next observations. Exponentiate this value (use the System.Math.Exp function) to obtain
        ///   a <c>likelihood</c> value.</param>
        ///
        /// <example>
        /// <code source="Unit Tests\Accord.Tests.Statistics\Models\Markov\HiddenMarkovModelTest.cs" region="doc_predict"/>
        /// </example>
        ///
        public int[] Predict(int[] observations, int next, out double logLikelihood, out double[][] logLikelihoods)
        {
            int states = States;
            int T      = next;

            double[][] lnA = LogTransitions;

            int[] prediction = new int[next];
            logLikelihoods = new double[next][];

            try
            {
                // Compute forward probabilities for the given observation sequence.
                double[,] lnFw0 = ForwardBackwardAlgorithm.LogForward(this, observations, out logLikelihood);

                // Create a matrix to store the future probabilities for the prediction
                // sequence and copy the latest forward probabilities on its first row.
                double[,] lnFwd = new double[T + 1, states];


                // 1. Initialization
                for (int i = 0; i < states; i++)
                {
                    lnFwd[0, i] = lnFw0[observations.Length - 1, i];
                }

                // 2. Induction
                for (int t = 0; t < T; t++)
                {
                    double[] weights = new double[symbols];
                    for (int s = 0; s < symbols; s++)
                    {
                        weights[s] = Double.NegativeInfinity;

                        for (int i = 0; i < states; i++)
                        {
                            double sum = Double.NegativeInfinity;
                            for (int j = 0; j < states; j++)
                            {
                                sum = Special.LogSum(sum, lnFwd[t, j] + lnA[j][i]);
                            }
                            lnFwd[t + 1, i] = sum + logB[i][s];

                            weights[s] = Special.LogSum(weights[s], lnFwd[t + 1, i]);
                        }
                    }

                    double sumWeight = Double.NegativeInfinity;
                    for (int i = 0; i < weights.Length; i++)
                    {
                        sumWeight = Special.LogSum(sumWeight, weights[i]);
                    }
                    for (int i = 0; i < weights.Length; i++)
                    {
                        weights[i] -= sumWeight;
                    }


                    // Select most probable symbol
                    double maxWeight = weights[0];
                    prediction[t] = 0;
                    for (int i = 1; i < weights.Length; i++)
                    {
                        if (weights[i] > maxWeight)
                        {
                            maxWeight     = weights[i];
                            prediction[t] = i;
                        }
                    }

                    // Recompute log-likelihood
                    logLikelihoods[t] = weights;
                    logLikelihood     = maxWeight;
                }


                return(prediction);
            }
            catch (IndexOutOfRangeException ex)
            {
                checkObservations(ex, observations);
                throw;
            }
        }
Beispiel #6
0
        /// <summary>
        ///   Predicts the next observation occurring after a given observation sequence.
        /// </summary>
        ///
        private double[][] predict(double[][] observations, int next,
                                   out double probability, out double[][] future)
        {
            int states = States;
            int T      = next;

            double[,] A = Transitions;
            double logLikelihood;

            double[][] prediction  = new double[next][];
            double[][] expectation = new double[states][];

            // Compute expectations for each state
            for (int i = 0; i < states; i++)
            {
                expectation[i] = getMode(B[i]);
            }


            // Compute forward probabilities for the given observation sequence.
            double[,] fw0 = ForwardBackwardAlgorithm.Forward(this, observations, out logLikelihood);

            // Create a matrix to store the future probabilities for the prediction
            // sequence and copy the latest forward probabilities on its first row.
            double[][] fwd = new double[T + 1][];
            for (int i = 0; i < fwd.Length; i++)
            {
                fwd[i] = new double[States];
            }


            // 1. Initialization
            for (int i = 0; i < States; i++)
            {
                fwd[0][i] = fw0[observations.Length - 1, i];
            }


            // 2. Induction
            for (int t = 0; t < T; t++)
            {
                double[] weights = fwd[t + 1];

                double scale = 0;
                for (int i = 0; i < weights.Length; i++)
                {
                    double sum = 0.0;
                    for (int j = 0; j < states; j++)
                    {
                        sum += fwd[t][j] * A[j, i];
                    }

                    scale += weights[i] = sum * B[i].ProbabilityFunction(expectation[i]);
                }

                scale /= Math.Exp(logLikelihood);

                if (scale != 0) // Scaling
                {
                    for (int i = 0; i < weights.Length; i++)
                    {
                        weights[i] /= scale;
                    }
                }


                // Select most probable value
                double maxWeight = weights[0];
                double sumWeight = maxWeight;
                prediction[t] = expectation[0];
                for (int i = 1; i < states; i++)
                {
                    if (weights[i] > maxWeight)
                    {
                        maxWeight     = weights[i];
                        prediction[t] = expectation[i];
                    }
                }

                // Recompute log-likelihood
                logLikelihood = Math.Log(maxWeight);
            }

            // Returns the sequence probability as an out parameter
            probability = Math.Exp(logLikelihood);

            // Returns the future-forward probabilities
            future = fwd;

            return(prediction);
        }
        /// <summary>
        ///   Predicts the next observation occurring after a given observation sequence.
        /// </summary>
        ///
        private TObservation[] predict(TObservation[] observations, int next, out double logLikelihood, out double[][] lnFuture)
        {
            int states = States;
            int T      = next;

            double[][] lnA = LogTransitions;

            TObservation[] prediction  = new TObservation[next];
            TObservation[] expectation = new TObservation[states];

            // Compute expectations for each state
            for (int i = 0; i < states; i++)
            {
                expectation[i] = getMode(B[i]);
            }


            // Compute forward probabilities for the given observation sequence.
            double[,] lnFw0 = ForwardBackwardAlgorithm.LogForward(this, observations, out logLikelihood);

            // Create a matrix to store the future probabilities for the prediction
            // sequence and copy the latest forward probabilities on its first row.
            double[][] lnFwd = new double[T + 1][];
            for (int i = 0; i < lnFwd.Length; i++)
            {
                lnFwd[i] = new double[States];
            }


            // 1. Initialization
            for (int i = 0; i < States; i++)
            {
                lnFwd[0][i] = lnFw0[observations.Length - 1, i];
            }


            // 2. Induction
            for (int t = 0; t < T; t++)
            {
                double[] weights = lnFwd[t + 1];

                for (int i = 0; i < weights.Length; i++)
                {
                    double sum = Double.NegativeInfinity;
                    for (int j = 0; j < states; j++)
                    {
                        sum = Special.LogSum(sum, lnFwd[t][j] + lnA[j][i]);
                    }

                    weights[i] = sum + B[i].LogProbabilityFunction(expectation[i]);
                }

                double sumWeight = Double.NegativeInfinity;
                for (int i = 0; i < weights.Length; i++)
                {
                    sumWeight = Special.LogSum(sumWeight, weights[i]);
                }
                for (int i = 0; i < weights.Length; i++)
                {
                    weights[i] -= sumWeight;
                }

                // Select most probable value
                double maxWeight = weights[0];
                prediction[t] = expectation[0];
                for (int i = 1; i < states; i++)
                {
                    if (weights[i] > maxWeight)
                    {
                        maxWeight     = weights[i];
                        prediction[t] = expectation[i];
                    }
                }

                // Recompute log-likelihood
                logLikelihood = maxWeight;
            }

            // Returns the future-forward probabilities
            lnFuture = lnFwd;

            return(prediction);
        }
        /// <summary>
        ///   Predicts the next observations occurring after a given observation sequence.
        /// </summary>
        public int[] Predict(int[] observations, int next, bool logarithm,
                             out double probability, out double[][] probabilities)
        {
            int states = States;
            int T      = next;

            double[,] A = Transitions;

            double logLikelihood;
            var    prediction = new int[next];

            probabilities = new double[next][];


            // Compute forward probabilities for the given observation sequence.
            double[,] fw0 = ForwardBackwardAlgorithm.Forward(this, observations, out logLikelihood);

            // Create a matrix to store the future probabilities for the prediction
            // sequence and copy the latest forward probabilities on its first row.
            var fwd = new double[T + 1, States];


            // 1. Initialization
            for (int i = 0; i < States; i++)
            {
                fwd[0, i] = fw0[observations.Length - 1, i];
            }


            // 2. Induction
            for (int t = 0; t < T; t++)
            {
                var weights = new double[Symbols];
                for (int s = 0; s < Symbols; s++)
                {
                    for (int i = 0; i < states; i++)
                    {
                        double sum = 0.0;
                        for (int j = 0; j < states; j++)
                        {
                            sum += fwd[t, j] * A[j, i];
                        }
                        fwd[t + 1, i] = sum * B[i, s];

                        weights[s] += fwd[t + 1, i];
                    }

                    weights[s] /= System.Math.Exp(logLikelihood);

                    if (weights[s] != 0) // Scaling
                    {
                        for (int i = 0; i < states; i++)
                        {
                            fwd[t + 1, i] /= weights[s];
                        }
                    }
                }

                // Select most probable symbol
                double maxWeight = weights[0];
                double sumWeight = maxWeight;
                for (int i = 1; i < weights.Length; i++)
                {
                    if (weights[i] > maxWeight)
                    {
                        maxWeight     = weights[i];
                        prediction[t] = i;
                    }

                    sumWeight += weights[i];
                }

                // Compute and save symbol probabilities
                for (int i = 0; i < weights.Length; i++)
                {
                    weights[i] /= sumWeight;
                }
                probabilities[t] = weights;

                // Recompute log-likelihood
                logLikelihood = System.Math.Log(maxWeight);
            }

            // Returns the sequence probability as an out parameter
            probability = logarithm ? logLikelihood : System.Math.Exp(logLikelihood);

            return(prediction);
        }