Exemple #1
0
        /// <summary>
        ///     Backward algorithm (without scaling)
        /// </summary>
        /// <param name="observations">A sequence of observations.</param>
        /// <returns></returns>
        private double backward(int[] observations)
        {
            if (observations == null)
            {
                throw new ArgumentNullException("observations");
            }

            if (tempInstancts == null)
            {
                throw new ArgumentNullException("tempInstancts");
            }

            int T = observations.Length;

            // For beta variables, I use the same scale factors
            //   for each time t as I used for alpha variables.

            // 1. Initialization
            for (int i = 0; i < States; i++)
            {
                tempInstancts[T - 1].Beta[i] = 1.0 / tempInstancts[T - 1].c;
            }

            // 2. Induction
            for (int t = T - 2; t >= 0; t--)
            {
                for (int i = 0; i < States; i++)
                {
                    double sum = 0.0;

                    for (int j = 0; j < States; j++)
                    {
                        sum += (Transitions.getValue(i, j) * Emissions.getValue(j, observations[t + 1]) * tempInstancts[t + 1].Beta[j]);
                    }

                    tempInstancts[t].Beta[i] += sum / tempInstancts[t].c;
                }
            }

            // 3. Termination
            double POGivenLambdaScaled = 0.0;

            for (int i = 0; i < Probabilities.Length; i++)
            {
                POGivenLambdaScaled += Probabilities[i] * Emissions.getValue(i, observations[0]) * tempInstancts[0].Beta[i];
            }

            double scaling = 1.0;

            for (int t = 0; t < T; t++)
            {
                scaling *= tempInstancts[t].c;
            }

            var POGivenLambda = POGivenLambdaScaled * scaling;

            return(POGivenLambda);
        }
Exemple #2
0
        /// <summary>
        ///     Determining the frequency of the transition-emission pair values
        ///     and dividing it by the probability of the entire string.
        ///
        ///     Using the scaled values, I don't need to divide it for the
        ///     probability of the entire string anymore
        /// </summary>
        /// <param name="t">Current time.</param>
        /// <param name="nextObservation">Observation at time t + 1.</param>
        /// <returns>Probability of transition from each state to any other at time t</returns>
        private MySparse2DMatrix calcXi(int t, int nextObservation)
        {
            if (tempInstancts == null)
            {
                throw new ArgumentNullException("tempInstancts");
            }

            if (tempInstancts[t].Alpha == null || tempInstancts[t].Beta == null)
            {
                throw new ArgumentNullException("Alpha and Beta aren't set");
            }

            MySparse2DMatrix currentXi = new MySparse2DMatrix();

            double s = 0;

            for (int i = 0; i < States; i++)
            {
                for (int j = 0; j < States; j++)
                {
                    double temp = tempInstancts[t].Alpha[i] * Transitions.getValue(i, j) * Emissions.getValue(j, nextObservation) * tempInstancts[t + 1].Beta[j];
                    s += temp;
                    if (temp != 0)
                    {
                        currentXi.setValue(i, j, temp);
                    }
                }
            }

            if (s != 0) // Scaling
            {
                for (int i = 0; i < States; i++)
                {
                    for (int j = 0; j < States; j++)
                    {
                        if (currentXi.getValue(i, j) != 0)
                        {
                            currentXi.setValue(i, j, currentXi.getValue(i, j) / s);
                        }
                    }
                }
            }

            return(currentXi);
        }
Exemple #3
0
        /// <summary>
        ///     Calculates the most likely sequence of hidden states
        ///     that produced the given observation sequence.
        /// </summary>
        /// <remarks>
        ///     Decoding problem. Given the HMM M = (A, B, pi) and  the observation sequence
        ///     O = {o1,o2, ..., oK}, calculate the most likely sequence of hidden states Si
        ///     that produced this observation sequence O. This can be computed efficiently
        ///     using the Viterbi algorithm.
        /// </remarks>
        /// <param name="observations">A sequence of observations.</param>
        /// <param name="probability">The state optimized probability.</param>
        /// <returns>The sequence of states that most likely produced the sequence.</returns>
        private int[] viterbi(int[] observations, out double probability)
        {
            if (observations == null)
            {
                throw new ArgumentNullException("observations");
            }

            if (tempInstancts == null)
            {
                throw new ArgumentNullException("tempInstancts");
            }

            if (observations.Length == 0)
            {
                probability = 0.0;
                return(new int[0]);
            }

            int    T = observations.Length;
            double maxWeight;
            int    maxState;

            // 1. Base
            for (int i = 0; i < States; i++)
            {
                tempInstancts[0].Delta[i] = Probabilities[i] * Emissions.getValue(i, observations[0]);
            }

            // 2. Induction
            for (int t = 1; t < T; t++)
            {
                for (int i = 0; i < States; i++)
                {
                    maxWeight = 0.0;
                    maxState  = 0;

                    for (int k = 0; k < States; k++)
                    {
                        double weight = tempInstancts[t - 1].Delta[k] * Transitions.getValue(k, i);

                        if (weight > maxWeight)
                        {
                            maxWeight = weight;
                            maxState  = k;
                        }
                    }

                    tempInstancts[t].Delta[i] = maxWeight * Emissions.getValue(i, observations[t]);
                    tempInstancts[t].State[i] = maxState;
                }
            }

            // Find maximum value for time T-1
            maxWeight = tempInstancts[T - 1].Delta[0];
            maxState  = 0;

            for (int k = 1; k < States; k++)
            {
                if (tempInstancts[T - 1].Delta[k] > maxWeight)
                {
                    maxWeight = tempInstancts[T - 1].Delta[k];
                    maxState  = k;
                }
            }

            // Trackback
            int[] path = new int[T];
            path[T - 1] = maxState;

            for (int t = T - 2; t >= 0; t--)
            {
                path[t] = tempInstancts[t + 1].State[path[t + 1]];
            }

            // Returns the sequence probability as an out parameter
            probability = maxWeight;

            // Returns the most likely (Viterbi path) for the given sequence
            return(path);
        }
Exemple #4
0
        /// <summary>
        ///     Forward algorithm (with scaling)
        /// </summary>
        /// <param name="observations">A sequence of observations.</param>
        /// <returns></returns>
        private double forward(int[] observations)
        {
            if (observations == null)
            {
                throw new ArgumentNullException("observations");
            }

            if (tempInstancts == null)
            {
                throw new ArgumentNullException("tempInstancts");
            }

            int T = observations.Length;

            // 1. Initialization
            for (int i = 0; i < States; i++)
            {
                tempInstancts[0].c += tempInstancts[0].Alpha[i] = Probabilities[i] * Emissions.getValue(i, observations[0]);
            }

            if (tempInstancts[0].c != 0) // Scaling CHECK
            {
                for (int i = 0; i < States; i++)
                {
                    tempInstancts[0].Alpha[i] = tempInstancts[0].Alpha[i] / tempInstancts[0].c;
                }
            }

            // 2. Induction
            for (int t = 1; t < T; t++)
            {
                for (int i = 0; i < States; i++)
                {
                    double sum = 0.0;

                    for (int k = 0; k < States; k++)
                    {
                        sum += (tempInstancts[t - 1].Alpha[k] * Transitions.getValue(k, i));
                    }

                    tempInstancts[t].Alpha[i] = sum * Emissions.getValue(i, observations[t]);

                    tempInstancts[t].c += tempInstancts[t].Alpha[i]; // Scaling coefficient
                }

                if (tempInstancts[t].c != 0) // Scaling
                {
                    for (int i = 0; i < States; i++)
                    {
                        tempInstancts[t].Alpha[i] = tempInstancts[t].Alpha[i] / tempInstancts[t].c;
                    }
                }
            }

            // 3. Termination
            double POGivenLambdaScaled = 0.0;

            for (int i = 0; i < Probabilities.Length; i++)
            {
                POGivenLambdaScaled += tempInstancts[T - 1].Alpha[i];
            }

            double scaling = 1.0;

            for (int t = 0; t < T; t++)
            {
                scaling *= tempInstancts[t].c;
            }

            var POGivenLambda = POGivenLambdaScaled * scaling;

            return(POGivenLambda);
        }