BotSharp/BotSharp.Algorithm/HiddenMarkovModel/Viterbi.Log.cs
2018-09-17 07:31:54 -05:00

86 lines
2.4 KiB
C#

using BotSharp.Algorithm.HiddenMarkovModel.Helpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BotSharp.Algorithm.HiddenMarkovModel
{
public partial class Viterbi
{
public int[] LogForward(double[,] logA, double[,] logB, double[] logPi, int[] observations)
{
double logLikelihood = 0;
return LogForward(logA, logB, logPi, observations, out logLikelihood);
}
public static int[] LogForward(double[,] logA, double[,] logB, double[] logPi, int[] observations, out double logLikelihood)
{
int T = observations.Length;
int N = logPi.Length;
DiagnosticsHelper.Assert(logA.GetLength(0) == N);
DiagnosticsHelper.Assert(logA.GetLength(1) == N);
DiagnosticsHelper.Assert(logB.GetLength(0) == N);
int[,] V = new int[T, N];
double[,] fwd = new double[T, N];
for (int i = 0; i < N; ++i)
{
fwd[0, i] = logPi[i] + logB[i, observations[0]];
}
double maxWeight = 0;
int maxState = 0;
for (int t = 1; t < T; ++t)
{
for (int i = 0; i < N; ++i)
{
maxWeight = fwd[t - 1, 0] + logA[0, i];
maxState = 0;
double weight = 0;
for (int j = 1; j < N; ++j)
{
weight = fwd[t - 1, j] + logA[j, i];
if (maxWeight < weight)
{
maxWeight = weight;
maxState = j;
}
}
fwd[t, i] = maxWeight + logB[i, observations[t]];
V[t, i] = maxState;
}
}
maxState = 0;
maxWeight = fwd[T - 1, 0];
for (int i = 0; i < N; ++i)
{
if (fwd[T - 1, i] > maxWeight)
{
maxWeight = fwd[T - 1, i];
maxState = i;
}
}
int[] path = new int[T];
path[T - 1] = maxState;
for (int t = T - 2; t >= 0; --t)
{
path[t] = V[t + 1, path[t + 1]];
}
logLikelihood = maxWeight;
return path;
}
}
}