/// <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 : Math.Exp(logLikelihood)); }
/// <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; int[] 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. double[,] 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++) { double[] 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] /= 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 = Math.Log(maxWeight); } // Returns the sequence probability as an out parameter probability = logarithm ? logLikelihood : Math.Exp(logLikelihood); return(prediction); }