/// <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); }
/// <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)); }
/// <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; } }
/// <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); }