コード例 #1
0
        /// <summary>
        ///   Predicts the next observations occurring after a given observation sequence (using Viterbi algorithm)
        /// </summary>
        public int[] Predict(int[] observations, int next, out double logLikelihood, out double[][] logLikelihoods)
        {
            int T = next;

            double[,] logA = LogTransitionMatrix;
            double[,] logB = LogEmissionMatrix;
            double[] logPi = LogProbabilityVector;

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


            // Compute forward probabilities for the given observation sequence.
            double[,] lnFw0 = ForwardBackwardAlgorithm.LogForward(logA, logB, logPi, 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, mStateCount];


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

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

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

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

                double sumWeight = Double.NegativeInfinity;
                for (int i = 0; i < weights.Length; i++)
                {
                    sumWeight = LogHelper.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);
        }