using System; using System.Collections.Generic; using System.Linq; using System.Text; using BotSharp.Algorithm.HiddenMarkovModel.Helpers; using BotSharp.Algorithm.HiddenMarkovModel.MathHelpers; namespace BotSharp.Algorithm.HiddenMarkovModel { public partial class ForwardBackwardAlgorithm { /// /// Compute forward probabilities for a given hidden Markov model and a set of observations with scaling /// /// Transition Matrix: logA[i, j] is the probability of transitioning state i to state j (in log term) /// Emission Matrix: logB[observation[t], i] is the probability that given the state at t is i, the observed state at t is observation[t] (in log term) /// State Vector: logPi[i] is the probability that a particular state is t at any time, this can be also interpreted as the probability of initial states (in log term) /// Observed time series /// Forward Probability Matrix: fwd[t, i] is the scaled probability that provides us with the probability of being in state i at time t. public static void LogForward(double[,] logA, double[,] logB, double[] logPi, int[] observations, double[,] lnfwd) { int T = observations.Length; // length of the observation int N = logPi.Length; // number of states DiagnosticsHelper.Assert(logA.GetLength(0) == N); DiagnosticsHelper.Assert(logA.GetLength(1) == N); DiagnosticsHelper.Assert(logB.GetLength(0) == N); DiagnosticsHelper.Assert(lnfwd.GetLength(0) >= T); DiagnosticsHelper.Assert(lnfwd.GetLength(1) == N); System.Array.Clear(lnfwd, 0, lnfwd.Length); for (int i = 0; i < N; ++i) { lnfwd[0, i] = logPi[i] + logB[i, observations[0]]; } for (int t = 1; t < T; ++t) { int obs_t = observations[t]; for (int i = 0; i < N; ++i) { double sum = double.NegativeInfinity; for(int j = 0; j < N; ++j) { sum = LogHelper.LogSum(sum, lnfwd[t - 1, j] + logA[j, i]); } lnfwd[t, i] = sum + logB[i, obs_t]; } } } /// /// Compute forward probabilities for a given hidden Markov model and a set of observations without scaling /// /// Transition Matrix: A[i, j] is the probability of transitioning state i to state j /// Emission Matrix: B[observation[t], i] is the probability that given the state at t is i, the observed state at t is observation[t] /// State Vector: pi[i] is the probability that a particular state is t at any time, this can be also interpreted as the probability of initial states /// Observed time series /// The likelihood of the observed time series based on the given hidden Markov model (in log term) /// Forward Probability Matrix: lnfwd[t, i] is the scaled probability that provides us with the probability of being in state i at time t (in log term) public static double[,] LogForward(double[,] logA, double[,] logB, double[] logPi, int[] observations, out double logLikelihood) { int T = observations.Length; // time series length int N = logPi.Length; // number of states double[,] lnfwd = new double[T, N]; LogForward(logA, logB, logPi, observations, lnfwd); logLikelihood = double.NegativeInfinity; for (int i = 0; i < N; ++i) { logLikelihood = LogHelper.LogSum(logLikelihood, lnfwd[T-1, i]); } return lnfwd; } /// /// Compute backward probabilities for a given hidden Markov model and a set of observations with scaling /// /// Transition Matrix: A[i, j] is the probability of transitioning state i to state j /// Emission Matrix: B[observation[t], i] is the probability that given the state at t is i, the observed state at t is observation[t] /// State Vector: pi[i] is the probability that a particular state is t at any time, this can be also interpreted as the probability of initial states /// Observed time series /// Backward Probability Matrix: fwd[t, i] is the scaled probability that provides us with the probability of being in state i at time t. public static void LogBackward(double[,] logA, double[,] logB, double[] logPi, int[] observations, double[,] lnbwd) { int T = observations.Length; //length of time series int N = logPi.Length; //number of states DiagnosticsHelper.Assert(logA.GetLength(0) == N); DiagnosticsHelper.Assert(logA.GetLength(1) == N); DiagnosticsHelper.Assert(logB.GetLength(0) == N); DiagnosticsHelper.Assert(lnbwd.GetLength(0) >= T); DiagnosticsHelper.Assert(lnbwd.GetLength(1) == N); Array.Clear(lnbwd, 0, lnbwd.Length); for (int i = 0; i < N; ++i) { lnbwd[T - 1, i] = 0; } for (int t = T - 2; t >= 0; t--) { for (int i = 0; i < N; ++i) { double sum = double.NegativeInfinity; for (int j = 0; j < N; ++j) { sum = LogHelper.LogSum(sum, logA[i, j] + logB[j, observations[t+1]] + lnbwd[t+1, j]); } lnbwd[t, i] += sum; } } } /// /// Compute backward probabilities for a given hidden Markov model and a set of observations without scaling /// /// Transition Matrix: A[i, j] is the probability of transitioning state i to state j (in log term) /// Emission Matrix: B[observation[t], i] is the probability that given the state at t is i, the observed state at t is observation[t] (in log term) /// State Vector: pi[i] is the probability that a particular state is t at any time, this can be also interpreted as the probability of initial states (in log term) /// Observed time series /// Backward Probability Matrix: lnbwd[t, i] is the scaled probability that provides us with the probability of being in state i at time t (in log term) public static double[,] LogBackward(double[,] logA, double[,] logB, double[] logPi, int[] observations) { int T = observations.Length; int N = logPi.Length; double[,] lnbwd=new double[T, N]; LogBackward(logA, logB, logPi, observations, lnbwd); return lnbwd; } /// /// Compute backward probabilities for a given hidden Markov model and a set of observations without scaling /// /// Transition Matrix: A[i, j] is the probability of transitioning state i to state j (in log term) /// Emission Matrix: B[observation[t], i] is the probability that given the state at t is i, the observed state at t is observation[t] (in log term) /// State Vector: pi[i] is the probability that a particular state is t at any time, this can be also interpreted as the probability of initial states (in log term) /// Observed time series /// The likelihood of the observed time series given the hidden Markov model (in log term) /// Backward Probability Matrix: bwd[t, i] is the scaled probability that provides us with the probability of being in state i at time t (in log term) public static double[,] LogBackward(double[,] logA, double[,] logB, double[] logPi, int[] observations, out double logLikelihood) { int T = observations.Length; // time series length int N = logPi.Length; // number of states double[,] lnbwd = LogBackward(logA, logB, logPi, observations); logLikelihood = double.NegativeInfinity; for (int i = 0; i < N; ++i) { logLikelihood = LogHelper.LogSum(logLikelihood, lnbwd[0, i] + logPi[i] + logB[i, observations[0]]); } return lnbwd; } } }