public void LogBackwardTest() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. ForwardBackwardAlgorithmTest.CreateModel2(); int[] observations = { 0, 1, 1, 0 }; double logLikelihood; double[,] expected = Matrix.Log( ForwardBackwardAlgorithm.Backward(hmm, observations)); double[,] actual = ForwardBackwardAlgorithm.LogBackward(hmm, observations, out logLikelihood); Assert.IsTrue(expected.IsEqual(actual, 1e-10)); foreach (double e in actual) { Assert.IsFalse(double.IsNaN(e)); } double p = System.Math.Exp(logLikelihood); Assert.AreEqual(0.054814695, p, 1e-8); Assert.IsFalse(double.IsNaN(p)); }
public void BackwardTest2() { HiddenMarkovModel hmm = CreateModel3(); // L L R R int[] observations = { 0, 0, 1, 1 }; double[,] actual = ForwardBackwardAlgorithm.Backward(hmm, observations); // Backward matrices from R's HMM package are // transposed in relation to the framework's: Assert.AreEqual(4, actual.GetLength(0)); Assert.AreEqual(2, actual.GetLength(1)); Assert.AreEqual(0.128982144, actual[0, 0], 1e-10); Assert.AreEqual(0.082407504, actual[0, 1], 1e-10); Assert.AreEqual(0.196816, actual[1, 0], 1e-10); Assert.AreEqual(0.453856, actual[1, 1], 1e-10); Assert.AreEqual(0.376, actual[2, 0], 1e-10); Assert.AreEqual(0.691, actual[2, 1], 1e-10); Assert.AreEqual(1, actual[3, 0]); Assert.AreEqual(1, actual[3, 1]); foreach (double p in actual) { Assert.IsFalse(double.IsNaN(p)); } }
public void BackwardTest() { HiddenMarkovModel hmm = CreateModel2(); // A B B A int[] observations = { 0, 1, 1, 0 }; double logLikelihood; double[,] actual = ForwardBackwardAlgorithm.Backward(hmm, observations, out logLikelihood); var A = Matrix.Exp(hmm.Transitions); var B = Matrix.Exp(hmm.Emissions); var P = Matrix.Exp(hmm.Probabilities); double a30 = 1; double a31 = 1; double a20 = A[0, 0] * B[0, 0] * a30 + A[0, 1] * B[1, 0] * a31; double a21 = A[1, 0] * B[0, 0] * a30 + A[1, 1] * B[1, 0] * a31; double a10 = A[0, 0] * B[0, 1] * a20 + A[0, 1] * B[1, 1] * a21; double a11 = A[1, 0] * B[0, 1] * a20 + A[1, 1] * B[1, 1] * a21; double a00 = A[0, 0] * B[0, 1] * a10 + A[0, 1] * B[1, 1] * a11; double a01 = A[1, 0] * B[0, 1] * a10 + A[1, 1] * B[1, 1] * a11; Assert.AreEqual(actual[0, 0], a00); Assert.AreEqual(actual[0, 1], a01); Assert.AreEqual(actual[1, 0], a10); Assert.AreEqual(actual[1, 1], a11); Assert.AreEqual(actual[2, 0], a20); Assert.AreEqual(actual[2, 1], a21); Assert.AreEqual(actual[3, 0], a30); Assert.AreEqual(actual[3, 1], a31); double p = 0; for (int i = 0; i < hmm.States; i++) { p += actual[0, i] * P[i] * B[i, observations[0]]; } Assert.AreEqual(0.054814695, p, 1e-8); Assert.IsFalse(double.IsNaN(p)); p = System.Math.Exp(logLikelihood); Assert.AreEqual(0.054814695, p, 1e-8); Assert.IsFalse(double.IsNaN(p)); }
public void ForwardBackwardTest() { HiddenMarkovModel hmm = CreateModel1(); // G G C A int[] observations = { 2, 2, 1, 0 }; double fwdLogLikelihood; double[,] fwd = ForwardBackwardAlgorithm.Forward(hmm, observations, out fwdLogLikelihood); double bwdLogLikelihood; double[,] bwd = ForwardBackwardAlgorithm.Backward(hmm, observations, out bwdLogLikelihood); Assert.AreEqual(fwdLogLikelihood, bwdLogLikelihood, 1e-10); // -5.5614629361549142 }
public void LogBackwardTest2() { HiddenMarkovModel hmm = Accord.Tests.Statistics.Models.Markov. ForwardBackwardAlgorithmTest.CreateModel3(); int[] observations = { 0, 0, 1, 1 }; double[,] expected = Matrix.Log( ForwardBackwardAlgorithm.Backward(hmm, observations)); double[,] actual = ForwardBackwardAlgorithm.LogBackward(hmm, observations); Assert.IsTrue(expected.IsEqual(actual, 1e-10)); foreach (double p in actual) { Assert.IsFalse(double.IsNaN(p)); } }
public void ForwardBackwardGenericTest() { var discreteModel = CreateModel1(); var genericModel = CreateModel4(); int[] discreteObservations = { 2, 2, 1, 0 }; double[][] genericObservations = { new double[] { 2 }, new double[] { 2 }, new double[] { 1 }, new double[] { 0 } }; double[] scaling = new double[3]; double discreteFwdLogLikelihood; double[,] discreteFwd = ForwardBackwardAlgorithm.Forward(discreteModel, discreteObservations, out scaling, out discreteFwdLogLikelihood); double[,] discreteBwd = ForwardBackwardAlgorithm.Backward(discreteModel, discreteObservations, scaling); double genericFwdLogLikelihood; double[,] genericFwd = ForwardBackwardAlgorithm.Forward(genericModel, genericObservations, out scaling, out genericFwdLogLikelihood); double[,] genericBwd = ForwardBackwardAlgorithm.Backward(genericModel, genericObservations, scaling); Assert.AreEqual(discreteFwdLogLikelihood, genericFwdLogLikelihood); for (int i = 0; i < discreteFwd.GetLength(0); i++) { for (int j = 0; j < discreteFwd.GetLength(1); j++) { Assert.AreEqual(discreteFwd[i, j], genericFwd[i, j]); Assert.AreEqual(discreteBwd[i, j], genericBwd[i, j]); } } }
private double[] gradient(T[][] observations, int[][] labels) { int N = observations.Length; var function = model.Function; var states = model.States; double[] g = new double[function.Weights.Length]; // Compute sequence probabilities var P = new double[N][, ][]; for (int i = 0; i < N; i++) { var Pi = P[i] = new double[states + 1, states][]; T[] x = observations[i]; var fwd = ForwardBackwardAlgorithm.Forward(function.Factors[0], x, 0); var bwd = ForwardBackwardAlgorithm.Backward(function.Factors[0], x, 0); double z = partition(fwd, x); for (int prev = -1; prev < states; prev++) { for (int next = 0; next < states; next++) { double[] Pis = new double[x.Length]; for (int t = 0; t < x.Length; t++) { Pis[t] = p(prev, next, x, t, fwd, bwd, function) / z; } Pi[prev + 1, next] = Pis; } } } // Compute the gradient w.r.t. each feature // function in the model's potential function. for (int k = 0; k < g.Length; k++) { var feature = function.Features[k]; double sum1 = 0.0, sum2 = 0.0; for (int i = 0; i < N; i++) { T[] x = observations[i]; int[] y = labels[i]; var Pi = P[i]; // Compute first term of the partial derivative sum1 += feature.Compute(-1, y[0], x, 0); for (int t = 1; t < x.Length; t++) { sum1 += feature.Compute(y[t - 1], y[t], x, t); } // Compute second term of the partial derivative for (int prev = -1; prev < states; prev++) { for (int next = 0; next < states; next++) { double[] Pis = Pi[prev + 1, next]; for (int t = 0; t < Pis.Length; t++) { sum2 += feature.Compute(prev, next, x, t) * Pis[t]; } } } } g[k] = -(sum1 - sum2); } return(g); }
/// <summary> /// Computes the forward and backward probabilities matrices /// for a given observation referenced by its index in the /// input training data. /// </summary> /// <param name="index">The index of the observation in the input training data.</param> /// <param name="fwd">Returns the computed forward probabilities matrix.</param> /// <param name="bwd">Returns the computed backward probabilities matrix.</param> /// <param name="scaling">Returns the scaling parameters used during calculations.</param> protected override void ComputeForwardBackward(int index, out double[,] fwd, out double[,] bwd, out double[] scaling) { fwd = ForwardBackwardAlgorithm.Forward(model, continuousObservations[index], out scaling); bwd = ForwardBackwardAlgorithm.Backward(model, continuousObservations[index], scaling); }
private double[] gradient(T[][] observations, int[][] labels, double[] g) { var model = Model; var function = model.Function; int states = model.States; int n = observations.Length; int d = Model.Function.Weights.Length; int Tmax = observations.Max(x => x.Length); int progress = 0; g.Clear(); // Compute sequence probabilities Parallel.For(0, observations.Length, ParallelOptions, () => { // Create thread-local storage var work = new double[states + 1, states][]; for (int j = 0; j < states + 1; j++) { for (int k = 0; k < states; k++) { work[j, k] = new double[Tmax]; } } return(new { bwd = new double[Tmax, states], fwd = new double[Tmax, states], sum1 = new double[d], sum2 = new double[d], work = work, count = new int[] { 0 } }); }, (i, state, local) => { T[] x = observations[i]; var fwd = local.fwd; var bwd = local.bwd; var sum1 = local.sum1; var sum2 = local.sum2; var work = local.work; ForwardBackwardAlgorithm.Forward(function.Factors[0], x, fwd); ForwardBackwardAlgorithm.Backward(function.Factors[0], x, bwd); double z = partition(fwd, x); for (int prev = -1; prev < states; prev++) { for (int next = 0; next < states; next++) { double[] Pis = work[prev + 1, next]; for (int t = 0; t < x.Length; t++) { Pis[t] = p(prev, next, x, t, fwd, bwd, function) / z; } } } // Compute the gradient w.r.t. each feature // function in the model's potential function. int[] y = labels[i]; Parallel.For(0, g.Length, ParallelOptions, k => { IFeature <T> feature = function.Features[k]; // Compute first term of the partial derivative sum1[k] += feature.Compute(-1, y[0], x, 0); for (int t = 1; t < x.Length; t++) { sum1[k] += feature.Compute(y[t - 1], y[t], x, t); } // Compute second term of the partial derivative for (int prev = -1; prev < states; prev++) { for (int next = 0; next < states; next++) { double[] Pis = work[prev + 1, next]; for (int t = 0; t < Pis.Length; t++) { sum2[k] += feature.Compute(prev, next, x, t) * Pis[t]; } } } }); local.count[0]++; return(local); }, (local) => { lock (g) { for (int k = 0; k < g.Length; k++) { g[k] -= (local.sum1[k] - local.sum2[k]); } progress += local.count[0]; } } ); return(g); }