Click here to Skip to main content
Click here to Skip to main content

Hidden Markov Models in C#

By , 5 Dec 2010
 

Hidden Markov Models (HMM) are stochastic methods to model temporal and sequence data. They are especially known for their application in temporal pattern recognition such as speech, handwriting, gesture recognition, part-of-speech tagging, musical score following, partial discharges and bioinformatics.

This code has also been incorporated in Accord.NET Framework, which includes the latest version of this code plus many other statistics and machine learning tools.

Contents

  1. Introduction
  2. Definition
    1. Notation
    2. Canonical problems
    3. Choosing the structure
  3. Algorithms
    1. Evaluation
    2. Decoding
    3. Learning
  4. Using the code
  5. Remarks
    1. Known issues
  6. Acknowledgements
  7. See also
  8. References

Introduction

Hidden Markov Models were first described in a series of statistical papers by Leonard E. Baum and other authors in the second half of the 1960s. One of the first applications of HMMs was speech recognition, starting in the mid-1970s. Indeed, one of the most comprehensive explanations on the topic was published in “A Tutorial On Hidden Markov Models And Selected Applications in Speech Recognition”, by Lawrence R. Rabiner in 1989. In the second half of the 1980s, HMMs began to be applied to the analysis of biological sequences, in particular DNA. Since then, they have become ubiquitous in the field of bioinformatics.

Dynamical systems of discrete nature assumed to be governed by a Markov chain emits a sequence of observable outputs. Under the Markov assumption, it is also assumed that the latest output depends only on the current state of the system. Such states are often not known from the observer when only the output values are observable.

Example of a hidden Markov model Hidden Markov Models attempt to model such systems and allow, among other things, (1) to infer the most likely sequence of states that produced a given output sequence, to (2) infer which will be the most likely next state (and thus predicting the next output) and (3) calculate the probability that a given sequence of outputs originated from the system (allowing the use of hidden Markov models for sequence classification).

The “hidden” in Hidden Markov Models comes from the fact that the observer does not know in which state the system may be in, but has only a probabilistic insight on where it should be.

Definition

Hidden Markov Models can be seem as finite state machines where for each sequence unit observation there is a state transition and, for each state, there is a output symbol emission.

Notation

Traditionally, HMMs have been defined by the following quintuple:

\lambda = (N, M, A, B, \pi)

where

  • N is the number of states for the model
  • M is the number of distinct observations symbols per state, i.e. the discrete alphabet size.
  • A is the NxN state transition probability distribution given in the form of a matrix A = {aij}
  • B is the NxM observation symbol probability distribution given in the form of a matrix B = {bj(k)}
  • π is the initial state distribution vector π = {πi}

Note that, if we opt out the structure parameters M and N we have the more often used compact notation

\lambda = (A, B, \pi)

Canonical problems

There are three canonical problems associated with hidden Markov models, which I'll quote from Wikipedia:

  1. Given the parameters of the model, compute the probability of a particular output sequence. This requires summation over all possible state sequences, but can be done efficiently using the Forward algorithm, which is a form of dynamic programming.
  2. Given the parameters of the model and a particular output sequence, find the state sequence that is most likely to have generated that output sequence. This requires finding a maximum over all possible state sequences, but can similarly be solved efficiently by the Viterbi algorithm.
  3. Given an output sequence or a set of such sequences, find the most likely set of state transition and output probabilities. In other words, derive the maximum likelihood estimate of the parameters of the HMM given a dataset of output sequences. No tractable algorithm is known for solving this problem exactly, but a local maximum likelihood can be derived efficiently using the Baum-Welch algorithm or the Baldi-Chauvin algorithm. The Baum-Welch algorithm is an example of a forward-backward algorithm, and is a special case of the Expectation-maximization algorithm.

The solution for those problems are exactly what makes Hidden Markov Models useful. The ability to learn from the data (using the solution of problem 3) and then become able to make predictions (solution to problem 2) and able to classify sequences (solution of problem 2) is nothing but applied machine learning. From this perspective, HMMs can just be seem as supervisioned sequence classifiers and sequence predictors with some other useful interesting properties.

Choosing the structure

Choosing the structure for a hidden Markov model is not always obvious. The number of states depend on the application and to what interpretation one is willing to give to the hidden states. Some domain knowledge is required to build a suitable model and also to choose the initial parameters that an HMM can take. There is also some trial and error involved, and there are sometimes complex tradeoffs that have to be made between model complexity and difficulty of learning, just as is the case with most machine learning techniques.

Additional information can be found on http://www.cse.unsw.edu.au/~waleed/phd/tr9806/node12.html.

Algorithms

The solution to the three canonical problems are the algorithms that makes HMMs useful. Each of the three problems are described in the three subsections below.

Evaluation

The first canonical problem is the evaluation of the probability of a particular output sequence. It can be efficiently computed using either the Viterbi-forward or the Forward algorithms, both of which are forms of dynamic programming.

The Viterbi algorithm originally computes the most likely sequence of states which has originated a sequence of observations. In doing so, it is also able to return the probability of traversing this particular sequence of states. So to obtain Viterbi probabilities, please refer to the Decoding problem referred below.

The Forward algorithm, unlike the Viterbi algorithm, does not find a particular sequence of states; instead it computes the probability that any sequence of states has produced the sequence of observations. In both algorithms, a matrix is used to store computations about the possible state sequence paths that the model can assume. The forward algorithm also plays a key role in the Learning problem, and is thus implemented as a separate method.

/// <span class="code-SummaryComment"><summary>
</span>///   Calculates the probability that this model has generated the given sequence.
/// <span class="code-SummaryComment"></summary>
</span>/// <span class="code-SummaryComment"><remarks>
</span>///   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.
/// <span class="code-SummaryComment"></remarks>
</span>/// <span class="code-SummaryComment"><param name="observations" />
</span>///   A sequence of observations.
/// 
/// <span class="code-SummaryComment"><param name="logarithm" />
</span>///   True to return the log-likelihood, false to return
///   the likelihood. Default is false.
/// 
/// <span class="code-SummaryComment"><returns>
</span>///   The probability that the given sequence has been generated by this model.
/// <span class="code-SummaryComment"></returns>
</span>public double Evaluate(int[] observations, bool logarithm)
{
    if (observations == null)
        throw new ArgumentNullException("observations");

    if (observations.Length == 0)
        return 0.0;


    // Forward algorithm
    double likelihood = 0;
    double[] coefficients;

    // Compute forward probabilities
    forward(observations, out coefficients);

    for (int i = 0; i < coefficients.Length; i++)
        likelihood += Math.Log(coefficients[i]);

    // Return the sequence probability
    return logarithm ? likelihood : Math.Exp(likelihood);
}

/// <span class="code-SummaryComment"><summary>
</span>///   Baum-Welch forward pass (with scaling)
/// <span class="code-SummaryComment"></summary>
</span>/// <span class="code-SummaryComment"><remarks>
</span>///   Reference: http://courses.media.mit.edu/2010fall/mas622j/ProblemSets/ps4/tutorial.pdf
/// <span class="code-SummaryComment"></remarks>
</span>private double[,] forward(int[] observations, out double[] c)
{
    int T = observations.Length;
    double[] pi = Probabilities;
    double[,] A = Transitions;

    double[,] fwd = new double[T, States];
    c = new double[T];


    // 1. Initialization
    for (int i = 0; i < States; i++)
        c[0] += fwd[0, i] = pi[i] * B[i, observations[0]];

    if (c[0] != 0) // Scaling
    {
        for (int i = 0; i < States; i++)
            fwd[0, i] = fwd[0, i] / c[0];
    }


    // 2. Induction
    for (int t = 1; t < T; t++)
    {
        for (int i = 0; i < States; i++)
        {
            double p = B[i, observations[t]];

            double sum = 0.0;
            for (int j = 0; j < States; j++)
                sum += fwd[t - 1, j] * A[j, i];
            fwd[t, i] = sum * p;

            c[t] += fwd[t, i]; // scaling coefficient
        }

        if (c[t] != 0) // Scaling
        {
            for (int i = 0; i < States; i++)
                fwd[t, i] = fwd[t, i] / c[t];
        }
    }

    return fwd;
}

Decoding

The second canonical problem is the discovery of the most likely sequence of states that generated a given output sequence. This can be computed efficiently using the Viterbi algorithm. A trackback is used to detect the maximum probability path travelled by the algorithm. The probability of travelling such sequence is also computed in the process.

/// <span class="code-SummaryComment"><summary>
</span>///   Calculates the most likely sequence of hidden states
///   that produced the given observation sequence.
/// <span class="code-SummaryComment"></summary>
</span>/// <span class="code-SummaryComment"><remarks>
</span>///   Decoding problem. Given the HMM M = (A, B, pi) and  the observation sequence 
///   O = {o1,o2, ..., oK}, calculate the most likely sequence of hidden states Si
///   that produced this observation sequence O. This can be computed efficiently
///   using the Viterbi algorithm.
/// <span class="code-SummaryComment"></remarks>
</span>/// <span class="code-SummaryComment"><param name="observations" />A sequence of observations.
</span>/// <span class="code-SummaryComment"><param name="probability" />The state optimized probability.
</span>/// <span class="code-SummaryComment"><returns>The sequence of states that most likely produced the sequence.</returns>
</span>public int[] Decode(int[] observations, out double probability)
{
    // Viterbi algorithm.

    int T = observations.Length;
    int states = States;
    int minState;
    double minWeight;
    double weight;

    int[,] s = new int[states, T];
    double[,] a = new double[states, T];


    // Base
    for (int i = 0; i < states; i++)
    {
        a[i, 0] = (-1.0 * System.Math.Log(pi[i])) - System.Math.Log(B[i, observations[0]]);
    }

    // Induction
    for (int t = 1; t < T; t++)
    {
        for (int j = 0; j < states; j++)
        {
            minState = 0;
            minWeight = a[0, t - 1] - System.Math.Log(A[0, j]);

            for (int i = 1; i < states; i++)
            {
                weight = a[i, t - 1] - System.Math.Log(A[i, j]);

                if (weight < minWeight)
                {
                    minState = i;
                    minWeight = weight;
                }
            }

            a[j, t] = minWeight - System.Math.Log(B[j, observations[t]]);
            s[j, t] = minState;
        }
    }


    // Find minimum value for time T-1
    minState = 0;
    minWeight = a[0, T - 1];

    for (int i = 1; i < states; i++)
    {
        if (a[i, T - 1] < minWeight)
        {
            minState = i;
            minWeight = a[i, T - 1];
        }
    }

    // Trackback
    int[] path = new int[T];
    path[T - 1] = minState;

    for (int t = T - 2; t >= 0; t--)
        path[t] = s[path[t + 1], t + 1];


    probability = System.Math.Exp(-minWeight);
    return path;
}

Learning

The third and last problem is the problem of learning the most likely parameters that best models a system given a set of sequences originated from this system. Most implementations I've seem did not consider the problem of learning from a set of sequences, but only from a single sequence at a time. The algorithm below, however, is fully suitable to learn from a set of sequences and also uses scaling, which is another thing I have not seem in other implementations.

The source code follows the original algorithm by Rabiner (1989). There are, however, some known issues with the algorithms detailed in Rabiner's paper. More information about those issues is available in a next section of this article entitled “Remarks”.

/// <span class="code-SummaryComment"><summary>
</span>///   Runs the Baum-Welch learning algorithm for hidden Markov models.
/// <span class="code-SummaryComment"></summary>
</span>/// <span class="code-SummaryComment"><remarks>
</span>///   Learning problem. Given some training observation sequences O = {o1, o2, ..., oK}
///   and general structure of HMM (numbers of hidden and visible states), determine
///   HMM parameters M = (A, B, pi) that best fit training data. 
/// <span class="code-SummaryComment"></remarks>
</span>/// <span class="code-SummaryComment"><param name="iterations" />
</span>///   The maximum number of iterations to be performed by the learning algorithm. If
///   specified as zero, the algorithm will learn until convergence of the model average
///   likelihood respecting the desired limit.
/// 
/// <span class="code-SummaryComment"><param name="observations" />
</span>///   An array of observation sequences to be used to train the model.
/// 
/// <span class="code-SummaryComment"><param name="tolerance" />
</span>///   The likelihood convergence limit L between two iterations of the algorithm. The
///   algorithm will stop when the change in the likelihood for two consecutive iterations
///   has not changed by more than L percent of the likelihood. If left as zero, the
///   algorithm will ignore this parameter and iterates over a number of fixed iterations
///   specified by the previous parameter.
/// 
/// <span class="code-SummaryComment"><returns>
</span>///   The average log-likelihood for the observations after the model has been trained.
/// <span class="code-SummaryComment"></returns>
</span>public double Learn(int[][] observations, int iterations, double tolerance)
{
    if (iterations == 0 && tolerance == 0)
        throw new ArgumentException("Iterations and limit cannot be both zero.");

    // Baum-Welch algorithm.

    // The Baum–Welch algorithm is a particular case of a generalized expectation-maximization
    // (GEM) algorithm. It can compute maximum likelihood estimates and posterior mode estimates
    // for the parameters (transition and emission probabilities) of an HMM, when given only
    // emissions as training data.

    // The algorithm has two steps:
    //  - Calculating the forward probability and the backward probability for each HMM state;
    //  - On the basis of this, determining the frequency of the transition-emission pair values
    //    and dividing it by the probability of the entire string. This amounts to calculating
    //    the expected count of the particular transition-emission pair. Each time a particular
    //    transition is found, the value of the quotient of the transition divided by the probability
    //    of the entire string goes up, and this value can then be made the new value of the transition.


    int N = observations.Length;
    int currentIteration = 1;
    bool stop = false;

    double[] pi = Probabilities;
    double[,] A = Transitions;


    // Initialization
    double[][, ,] epsilon = new double[N][, ,]; // also referred as ksi or psi
    double[][,] gamma = new double[N][,];

    for (int i = 0; i < N; i++)
    {
        int T = observations[i].Length;
        epsilon[i] = new double[T, States, States];
        gamma[i] = new double[T, States];
    }


    // Calculate initial model log-likelihood
    double oldLikelihood = Double.MinValue;
    double newLikelihood = 0;


    do // Until convergence or max iterations is reached
    {
        // For each sequence in the observations input
        for (int i = 0; i < N; i++)
        {
            var sequence = observations[i];
            int T = sequence.Length;
            double[] scaling;

            // 1st step - Calculating the forward probability and the
            //            backward probability for each HMM state.
            double[,] fwd = forward(observations[i], out scaling);
            double[,] bwd = backward(observations[i], scaling);


            // 2nd step - Determining the frequency of the transition-emission pair values
            //            and dividing it by the probability of the entire string.


            // Calculate gamma values for next computations
            for (int t = 0; t < T; t++)
            {
                double s = 0;

                for (int k = 0; k < States; k++)
                    s += gamma[i][t, k] = fwd[t, k] * bwd[t, k];

                if (s != 0) // Scaling
                {
                    for (int k = 0; k < States; k++)
                        gamma[i][t, k] /= s;
                }
            }

            // Calculate epsilon values for next computations
            for (int t = 0; t < T - 1; t++)
            {
                double s = 0;

                for (int k = 0; k < States; k++)
                    for (int l = 0; l < States; l++)
                        s += epsilon[i][t, k, l] = fwd[t, k] * A[k, l] * bwd[t + 1, l] * B[l, sequence[t + 1]];

                if (s != 0) // Scaling
                {
                    for (int k = 0; k < States; k++)
                        for (int l = 0; l < States; l++)
                            epsilon[i][t, k, l] /= s;
                }
            }

            // Compute log-likelihood for the given sequence
            for (int t = 0; t < scaling.Length; t++)
                newLikelihood += Math.Log(scaling[t]);
        }


        // Average the likelihood for all sequences
        newLikelihood /= observations.Length;


        // Check if the model has converged or we should stop
        if (checkConvergence(oldLikelihood, newLikelihood,
            currentIteration, iterations, tolerance))
        {
            stop = true;
        }

        else
        {
            // 3. Continue with parameter re-estimation
            currentIteration++;
            oldLikelihood = newLikelihood;
            newLikelihood = 0.0;


            // 3.1 Re-estimation of initial state probabilities 
            for (int k = 0; k < States; k++)
            {
                double sum = 0;
                for (int i = 0; i < N; i++)
                    sum += gamma[i][0, k];
                pi[k] = sum / N;
            }

            // 3.2 Re-estimation of transition probabilities 
            for (int i = 0; i < States; i++)
            {
                for (int j = 0; j < States; j++)
                {
                    double den = 0, num = 0;

                    for (int k = 0; k < N; k++)
                    {
                        int T = observations[k].Length;

                        for (int l = 0; l < T - 1; l++)
                            num += epsilon[k][l, i, j];

                        for (int l = 0; l < T - 1; l++)
                            den += gamma[k][l, i];
                    }

                    A[i, j] = (den != 0) ? num / den : 0.0;
                }
            }

            // 3.3 Re-estimation of emission probabilities
            for (int i = 0; i < States; i++)
            {
                for (int j = 0; j < Symbols; j++)
                {
                    double den = 0, num = 0;

                    for (int k = 0; k < N; k++)
                    {
                        int T = observations[k].Length;

                        for (int l = 0; l < T; l++)
                        {
                            if (observations[k][l] == j)
                                num += gamma[k][l, i];
                        }

                        for (int l = 0; l < T; l++)
                            den += gamma[k][l, i];
                    }

                    // avoid locking a parameter in zero.
                    B[i, j] = (num == 0) ? 1e-10 : num / den;
                }
            }

        }

    } while (!stop);


    // Returns the model average log-likelihood
    return newLikelihood;
}

Using the code

Lets suppose we have gathered some sequences from a system we wish to model. The sequences are expressed as a integer array such as:

int[][] sequences = new int[][] 
{
    new int[] { 0,1,1,1,1,1,1 },
    new int[] { 0,1,1,1 },
    new int[] { 0,1,1,1,1 },
    new int[] { 0,1, },
    new int[] { 0,1,1 },
};

For us, it can be obvious to see that the system is outputting sequences that always start with a zero and have one or more ones at the end. But lets try to fit a Hidden Markov Model to predict those sequences.
// Creates a new Hidden Markov Model with 2 states for
//  an output alphabet of two characters (zero and one)
HiddenMarkovModel hmm = new HiddenMarkovModel(2, 2);

// Try to fit the model to the data until the difference in
//  the average likelihood changes only by as little as 0.01
hmm.Learn(sequences, 0.01);

Once the model is trained, lets test to see if it recognizes some sequences:
// Calculate the probability that the given
//  sequences originated from the model
double l1 = hmm.Evaluate(new int[] { 0, 1 });       // l1 = 0.9999
double l2 = hmm.Evaluate(new int[] { 0, 1, 1, 1 }); // l2 = 0.9999

double l3 = hmm.Evaluate(new int[] { 1, 1 });       // l3 = 0.0000
double l4 = hmm.Evaluate(new int[] { 1, 0, 0, 0 }); // l4 = 0.0000

Of course the model performs well as this a rather simple example. A more useful test case would consist of allowing for some errors in the input sequences in the hope that the model will become more tolerant to measurement errors.
int[][] sequences = new int[][] 
{
    new int[] { 0,1,1,1,1,0,1,1,1,1 },
    new int[] { 0,1,1,1,0,1,1,1,1,1 },
    new int[] { 0,1,1,1,1,1,1,1,1,1 },
    new int[] { 0,1,1,1,1,1         },
    new int[] { 0,1,1,1,1,1,1       },
    new int[] { 0,1,1,1,1,1,1,1,1,1 },
    new int[] { 0,1,1,1,1,1,1,1,1,1 },
};

// Creates a new Hidden Markov Model with 3 states for
//  an output alphabet of two characters (zero and one)
HiddenMarkovModel hmm = new HiddenMarkovModel(2, 3);

// Try to fit the model to the data until the difference in
//  the average likelihood changes only by as little as 0.0001
hmm.Learn(sequences, 0.0001);

// Calculate the probability that the given
//  sequences originated from the model
double l1 = hmm.Evaluate(new int[] { 0,1 });      // 0.9999  
double l2 = hmm.Evaluate(new int[] { 0,1,1,1 });  // 0.9166

double l3 = hmm.Evaluate(new int[] { 1,1 });      // 0.0000
double l4 = hmm.Evaluate(new int[] { 1,0,0,0 });  // 0.0000

double l5 = hmm.Evaluate(new int[] { 0,1,0,1,1,1,1,1,1 }); // 0.0342
double l6 = hmm.Evaluate(new int[] { 0,1,1,1,1,1,1,0,1 }); // 0.0342

We can see that, despite having a very low probability, the likelihood values for the sequences containing a simulated measurement error are greater than the likelihoods for the sequences which do not follow the sequence structure at all.

In a subsequent article, we will see that those low values for the likelihoods will not be a problem because HMMs are often used in sets to form sequence classifiers. When used in such configurations, what really matters is which HMM returns the highest probability among others in the set.

Remarks

A practical issue in the use of Hidden Markov Models to model long sequences is the numerical scaling of conditional probabilities. The probability of observing a long sequence given most models is extremely small, and the use of these extremely small numbers in computations often leads to numerical instability, making application of HMMs to genome length sequences quite challenging.

There are two common approaches to dealing with small conditional probabilities. One approach is to rescale the conditional probabilities using carefully designed scaling factors, and the other approach is to work with the logarithms of the conditional probabilities. For more information on using logarithms please see the work entitled “Numerically Stable Hidden Markov Model Implementation”, by Tobias P. Mann.

Known issues

The code on this article is based on the Tutorial by Rabiner. There are, however, some problems with the scaling and other algorithms. An errata depicting all issues is available in the website “An Erratum for ‘A Tutorial on Hidden Markov Models and Selected Applications in Speech Recognition’” and is maintained by Ali Rahimi. I have not yet verified if the implementation presented here also suffers from the same mistakes explained there. This code has worked well under many situations, but I cannot guarantee its perfectness. Please use at your own risk.

Acknowledgements

Thanks to Guilherme C. Pedroso, for the help with the Baum-Welch generalization for multiple input sequences. He has also co-written a very interesting article using hidden Markov models for gesture recognition, entitled “Automatic Recognition of Finger Spelling for LIBRAS based on a Two-Layer Architecture” published in the 25th Symposium On Applied Computing (ACM SAC 2010).

See also

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

César de Souza
Software Developer
Brazil Brazil
Computer and technology enthusiast, interested in artificial intelligence and image processing. Has a Master's degree on Computer Science specialized on Image and Signal Processing, with expertise on Machine Learning, Computer Vision, Pattern Recognition and Data Mining systems.
 
Author of the Accord.NET Framework for developing scientific computing applications. Can also be hired through DaitanGroup for reliable software development.
Follow on   Twitter   Google+

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionHMM without librarymemberervin yohannes29-Mar-13 23:12 
Hi Cesar!
 
I search Hidden markov model in C# and I found in code project. Is it using library ?
I need hidden markov model in C# without library. Can you help me explain concept hidden markov model and Is it must using more algorithm ? (i.e backward-forward, viterbi and baum-welch algorithm)
Thank you. Smile | :)
 
regards,
ervin
QuestionGreat Work! But Help Neededmemberkeevinkong22-Mar-13 8:49 
Hi Cesar!
 
Great work. I am new to the whole .net thing and im kind of lost on how to get it working.
 
I installed the Accord.Net, Forge.Net and also SharpDevelop. So im wondering how can i import this in and get it to work? Sorry to bother u on such a simple question. But HMM has been around for a very long time. I did it during my school days using matlab but this is really intriguing.
 
Hope to hear from you soon.
 
Cheers,
Keevin
AnswerRe: Great Work! But Help NeededmemberCésar de Souza22-Mar-13 9:15 
Hi Keevin!
 
Perhaps you could take a look on Accord.NET's getting started guide[^]. It shows how to add references to some projects. For HMMs, please take a look on the newer article, Sequence Classifiers in C# - Part I: Hidden Markov Models[^]. The assemblies you are looking for are Accord.Statistics and Accord.Math.
 
You can also download the sample project, which should come with an already working project configuration!
 
Hope it helps!
Cesar
Interested in Machine Learning in .NET? Check the Accord.NET Framework.
See also Sequence Classifiers in C# with Hidden Conditional Random Fields.

QuestionI can't understand how to interpretate the result [modified]memberFixus6-Jan-13 5:40 
Hello,
first of all. Thank you. Your code and article helps me a lot.
 
But I need to ask you something. How to interpreate the result ?
 
double l1 = hmm.Evaluate(new int[] { 0,1 });      // 0.9999
double l2 = hmm.Evaluate(new int[] { 0,1,1,1 });  // 0.9166
 
Why l1 has higher score than l2 ? l2 is much longer and same as l1 it fits to every sequence from sequences
What the result mean ? Is that 99% vs ~92% ?
 
Second thing I'm checking something and I've created 2 models. Each for diffrent sequence and I want to evaluate a squence and fit it to one of 2 models so I did this
 
int[][] sequences = new int[][] 
{
    new int[] { 1,1,1,1,1 },
    new int[] { 1,1,1,1,0 },
    new int[] { 1,1,1,1,1 },
    new int[] { 1,1,1,1,1 },
};
 
            int[][] sequences2 = new int[][] 
{
    new int[] { 0,0,0,0,0 },
    new int[] { 0,0,0,0,0 },
    new int[] { 0,0,0,0,1 },
    new int[] { 0,0,0,0,0 },
};
 
            HiddenMarkovModel hmm = new HiddenMarkovModel(2, 5, HiddenMarkovModelType.Forward);
            HiddenMarkovModel hmm2 = new HiddenMarkovModel(2, 5, HiddenMarkovModelType.Forward);
 
            hmm.Learn(sequences, 0.0001);
            hmm2.Learn(sequences, 0.0001);
 
            // Calculate the probability that the given
            //  sequences originated from the model
            double l11 = hmm.Evaluate(new int[] { 0, 0, 0, 1, 1 });
            double l21 = hmm2.Evaluate(new int[] { 0, 0, 0, 0, 0 });
 
            Console.WriteLine("1) {0} | {1}", l11, l21);
 
funny thing is that l21 is rly small
1) 1,97215247536716E-198 | 1,11546110202783E-197
 
And I don't get why. The given sequence is like the one from sequnces2. So why isn't it near 1 ?
 
I hope i wrote is in a clear way Smile | :)
 
Best regards,
Dawid Pacholczyk

modified 6-Jan-13 11:48am.

QuestionEEG signalmemberhebaallasaad27-Dec-12 16:39 
hi,
i have problem i have the 6 signal for each action like thinking ,move,calculate
for 3 subject and each signal has 2500 sampling   how to implement learing and clasification for action
QuestionHMM and gesture recognitionmemberMember 808920412-Dec-12 8:09 
Hi all, I'm a student. I've never used before HMM and I need an help.
I'm working on a project for gesture recognition, this is my application's video:
 
http://www.youtube.com/watch?v=PDkfgxEV8TI
 
I'm using DTW (dynamic time warping) for recognition, but this is very slow.
I have ten sequence of movements, I post here an example:
 

<?xml version="1.0" encoding="utf-8"?>
<!--Questo file contiene le sequenze regitrate dal Kinect.-->
<Sequence ID_sequence="10">
  <Observation ID_observation="0">
    <Joint joint_element="Head">
      <X>-0,0681642160598825</X>
      <Y>-0,829331295395237</Y>
    </Joint>
    <Joint joint_element="HandLeft">
      <X>-0,704363565952119</X>
      <Y>1,60185907740724</Y>
    </Joint>
    <Joint joint_element="HandRight">
      <X>0,681642160598825</X>
      <Y>1,67002329346712</Y>
    </Joint>
    <Joint joint_element="Spine">
      <X>0</X>
      <Y>0,727084971305413</Y>
    </Joint>
    <Joint joint_element="FootLeft">
      <X>-0,261296161562883</X>
      <Y>3,73767118061689</Y>
    </Joint>
    <Joint joint_element="FootRight">
      <X>0,261296161562883</X>
      <Y>3,70358907258695</Y>
    </Joint>
  </Observation>
  <Observation ID_observation="1">
    .......
 
I work with positive and negative numbers (double) .
Can I create a HMM for these value?
How much states and characters I should use?
(HiddenMarkovModel hmm = new HiddenMarkovModel(2, 2);)
For test I use only the sequence of points for HandLeft (X and Y).
AnswerRe: HMM and gesture recognitionmemberCésar de Souza12-Dec-12 8:22 
Hi there,
 
Yes, you can; but you have to create a continuous model based on a multivarate continuous distribution. Please take a look on the second example on the Accord.NET documentation for the Hidden Markov Classifier Learning class[^]. I hope it helps in accomplishing your task!
 
Best regards,
Cesar
Interested in Machine Learning in .NET? Check the Accord.NET Framework.
See also Handwriting Recognition Revisited: Kernel Support Vector Machines

GeneralRe: HMM and gesture recognitionmemberMember 808920412-Dec-12 9:07 
Thanks you very much! I'm reading Hidden Markov Classifier Learning. There are a lots of interesting information. Big Grin | :-D Smile | :)
QuestionRe: HMM and gesture recognition [modified]memberMember 808920415-Dec-12 7:20 
Hi all! I go back to writing for another question.
I have read your link HiddenMarkovClassifierLearning but I have got a problem.

 
First, I created the sequence for the motion examples with my body points (Head, Hand Left, Hand Right, Spine, Foot Left, Foot Right)
 
I have a struct with type double[][][]
 

double[] Head 		//contains all points X and Y for Head motion (Es. -1,2,3,-0.1,...)
double[] HandLeft
...
double[] FootRight
 
After, I put these double array in another double array
 

double[][] action = new double[][]{
 Head, 		//contains all points X and Y for Head motion (Es. -1,2,3,-0.1,...)
 HandLeft,
 ...
 FootRight,
};
 
Finally, I have put this double[][] array in double[][][] for create my library sequences.
 
double[][][] sequences = new double[][][]
{
    new double[][] 
    { 
        // This is the sequence with label = 0 
        Head,   //this's a double[]
        ....
	FootRight,
    }, 
 
    .......
    .......
    .......
 
    new double[][]
    {
        // This is the sequence with label = N
        Head,
        ....
	FootRight,
    }
};
 
I have wrote this code for HMM's learning.

 
int size = sequences.Count;
 
// Labels for the sequences 
int[] num_labels = { 0, 1, 2, 3, 4,...., sequence.Count-1 };
 

MultivariateNormalDistribution initialDensity = new MultivariateNormalDistribution(size);
 
// Creates a sequence classifier containing 2 hidden Markov Models with 2 states 
// and an underlying multivariate mixture of Normal distributions as density. 
HiddenMarkovClassifier<MultivariateNormalDistribution> classifier = new HiddenMarkovClassifier<MultivariateNormalDistribution>(
    classes: size, topology: new Forward(size), initial: initialDensity);
 
// Configure the learning algorithms to train the sequence classifier 
HiddenMarkovClassifierLearning<MultivariateNormalDistribution> teacher = new HiddenMarkovClassifierLearning<MultivariateNormalDistribution>(
    classifier,
 
    // Train each model until the log-likelihood changes less than 0.0001
    modelIndex => new BaumWelchLearning<MultivariateNormalDistribution>(
        classifier.Models[modelIndex])
    {
        Tolerance = 0.0001,
        Iterations = 0,
 
        FittingOptions = new NormalOptions()
        {
            Diagonal = true,      // only diagonal covariance matrices
            Regularization = 1e-5 // avoid non-positive definite errors
        }
    }
);
 
but when I go to launch the Run method I have a problem
 
// Train the sequence classifier using the algorithm 
logLikelihood = teacher.Run(sequences, num_labels);
 
where do I have wrong?
Somebody can help me please? Thanks

modified 15-Dec-12 13:30pm.

AnswerRe: HMM and gesture recognitionmemberCésar de Souza15-Dec-12 8:29 
Hi there,
 
I think you are misunderstanding the concept of a feature vector. Each double[] observation should have the form <Head, Hand Left, Hand Right, Spine, Foot Left, Foot Right>. At a given instant t, your observation should be initialized something like
double[] observation = new double[] { Head[t], HandLeft[t], HandRight[t], Spine[t], FootLeft[t], FootRight[t] };
Besides, you have not told what problem do you have when you are calling the method "Run". If it is giving something like a DimensionMismatchException or an IndexOutOfRange, then it means you are not passing the sequences of observations in the expected form.
 
Please see if it helps.
 
Best regards,
Cesar
Interested in Machine Learning in .NET? Check the Accord.NET Framework.
See also Handwriting Recognition Revisited: Kernel Support Vector Machines

GeneralRe: HMM and gesture recognitionmemberMember 808920415-Dec-12 9:10 
I have a
 
An unhandled exception of type 'System.AggregateException' occurred in mscorlib.dll
 
Additional information: There have been one or more errors
.
 
D'Oh! | :doh: Frown | :( Mad | :mad:
 

What can you tell me about
 
classifier = new HiddenMarkovClassifier<MultivariateNormalDistribution>(
                classes: size, topology: new Forward(size), initial: initialDensity);

GeneralRe: HMM and gesture recognitionmemberCésar de Souza15-Dec-12 10:50 
Hi,
 
The AggregateException usually shows the actual exception which caused the issue in the InnerExceptions public property. Please take a look at it to see what it reports. But in any case, the problem should likely be the specification of the feature vectors as I mentioned. Did you try changing it to the way I suggested?
 
Best Regards,
Cesar
Interested in Machine Learning in .NET? Check the Accord.NET Framework.
See also Handwriting Recognition Revisited: Kernel Support Vector Machines

GeneralRe: HMM and gesture recognition [modified]memberMember 808920415-Dec-12 11:53 
I don't understand who I should do with double[] observation... Frown | :(
Cesar, thank you very much for precious advice.
 
Maybe these can help for understand my structure:
Screen1
Screen2
screen3

modified 15-Dec-12 18:55pm.

GeneralRe: HMM and gesture recognitionmemberCésar de Souza15-Dec-12 12:32 
If I understood the example you gave, you were transforming your arrays of head, hands and etc positions as double[][] by doing:
double[][] sequence = 
{
   Head,
   HandLeft,
   HandRight,
   etc
};
But what you really need to do is to build the feature vectors like this:
double[][] sequence = new double[numberOfObservationsInYourSequence];
for (int i = 0; i < sequence.Length; i++)
   sequence[i] = new double[] { Observation[i].Head.X, Observation[i].Head.Y, Observation[i].HandLeft.X, Observation[i].HandLeft.Y, ... };
 
I hope this makes it more clear.
Interested in Machine Learning in .NET? Check the Accord.NET Framework.
See also Handwriting Recognition Revisited: Kernel Support Vector Machines

GeneralRe: HMM and gesture recognition [modified]memberMember 808920415-Dec-12 13:01 
Yes, this is very more clear. Thanks
I have modified my old post with photo of my double[][][] structure.
 
screen1
screen2
screen3
 

Now i try to modify my code, I hope it work.

modified 15-Dec-12 19:25pm.

QuestionRe: HMM and gesture recognition [modified]memberMember 808920416-Dec-12 4:10 
Cesar, with your advices, HMM is working. But the recognition is wrong.
HMM recognizes wrong movements, (es drink instead of walk ecc..)
Is this a problem with constructor of the classifier or for a small number of examples?
 

NormalDistribution density = new NormalDistribution();
            var classifier = new HiddenMarkovClassifier<NormalDistribution>(library.Length, new Ergodic(2), density);
 
            // Create a new learning algorithm to train the sequence classifier 
            var teacher = new HiddenMarkovClassifierLearning<NormalDistribution>(classifier,
 
                // Train each model until the log-likelihood changes less than 0.001
                modelIndex => new BaumWelchLearning<NormalDistribution>(classifier.Models[modelIndex])
                {
                    Tolerance = 0.0001,
                    Iterations = 0
                }
            );
 

library.Length = //number of action how walk, drink, ecc...

modified 16-Dec-12 11:31am.

AnswerRe: HMM and gesture recognitionmemberCésar de Souza16-Dec-12 5:50 
The first argument of the constructor is the number of classes. It should be the number of different actions you are trying to classify, i.e. if you are trying to distinguish between walking and drinking the number of classes would be 2.
 
For gesture classification, it would also be better to change from using a Ergodic topology to a Forward one. Just use "new Forward(2)" instead.
 
And finally, to learn an HMM correctly you need several examples of each class. If you have just a single example of each class it won't work well.
 
Hope it helps!
Cesar
Interested in Machine Learning in .NET? Check the Accord.NET Framework.
See also Handwriting Recognition Revisited: Kernel Support Vector Machines

QuestionRe: HMM and gesture recognition [modified]memberMember 808920419-Dec-12 10:57 
mmmmm Unsure | :~ I tested Forward and Ergodic but the better is Ergodic with my data.
I have create a cycle of training, but the result is wrong
 
 
int size = learningSequence.Length;
 
for(int i = 0; i < size; i++)
{
  // Train the sequence classifier using the algorithm 
  logLikelihood = teacher.Run(learningSequence[i], labels);
}
 
for (int j = 0; j < size; j++)
{ 
Console.WriteLine("c1 (0) = "+ classifier.Compute(learningSequence[j][0], out logLikelihood));
 
Console.WriteLine("c2 (1) = "+ classifier.Compute(learningSequence[j][1], out logLikelihood));
 
Console.WriteLine("c3 (2) = "+ classifier.Compute(learningSequence[j][2], out logLikelihood));
 
}
            
Console.WriteLine("c= " + c);
 
 

This is the result:
 
c1 (0) = 1  // (0) standing
c2 (1) = 1  // (1) sit
c3 (2) = 2  // (2) get up my arms
 
c1 (0) = 1  
c2 (1) = 0  
c3 (2) = 2  
 
c1 (0) = 1
c2 (1) = 0
c3 (2) = 2
 
c1 (0) = 1
c2 (1) = 1
c3 (2) = 2
 
c1 (0) = 0
c2 (1) = 1
c3 (2) = 2
 
I use five examples for each movement.
My teaching is wrong or I need more examples? Dead | X| Confused | :confused: Mad | :mad:
 

Ps. Sorry for Email

modified 20-Dec-12 8:38am.

AnswerRe: HMM and gesture recognitionmemberCésar de Souza19-Dec-12 15:18 
You really should be using Forward instead of Ergodic. But in any case, this is not how you train the model; you should pass all sequence/label pairs at once, not in batches. Besides, I am not sure why but you seem to be swapping indices i and j, and it is not clear where the i comes from in the first loop, and the j comes from in the second loop.
 
So, in short, just call the teacher.Run(learningSequence, labels) once, and if your sequences are correctly structured it should do the trick.
 
Regards,
Cesar
Interested in Machine Learning in .NET? Check the Accord.NET Framework.
See also Handwriting Recognition Revisited: Kernel Support Vector Machines

GeneralMy vote of 5memberprasaducsc27-Nov-12 1:42 
It's help me lot
QuestionHand motion tracking Using HMMmemberprasaducsc5-Nov-12 3:57 
Hi, I'm a final year university student and currently doing my final year project. It is basically gesture recognition system. I want to track dynamic hand motions and identify hand gestures. I had try to implement that using HMM. But I couldn't identify starting and end points of the gesture. is any one know how I can track the stating and end points of the gesture. are there any implementations for achieve this. Please help me to short out this problem and it was a great help for me...
 
Thank you.. Smile | :)
AnswerRe: Hand motion tracking Using HMMmemberCésar de Souza5-Nov-12 4:13 
Hi there,
 
Detecting the start and end points of a gesture is another problem altogether. This problem is known as gesture spotting, and I don't think there is a definite and default answer for solving it yet. One possible approach is to use Lee and Kim's gesture spotter[^] based on threshold models. Please let me know if you have found something that works better.
 
Best regards,
Cesar
Interested in Machine Learning in .NET? Check the Accord.NET Framework.
See also Handwriting Recognition Revisited: Kernel Support Vector Machines

GeneralRe: Hand motion tracking Using HMMmemberprasaducsc22-Nov-12 13:05 
Thank you very much Cesar for your guidance. I tried to implement Lee and Kim's gesture spotter. but I couldn't do it. Did you have any implementation for gesture spotter ?
 
Regards,
Prasad
QuestionNicememberLe Trung Kien23-Oct-12 8:16 
This is a very readable code. Thanks!
I myself have been writing HMM in C++. Take a look if you are interested.
http://letrungkien7.wordpress.com/2012/10/21/hidden-markov-model/
QuestionThanks!memberantilon30-Sep-12 13:08 
Thank you for this great tutorial and code example!
 
Really helped me a lot with understanding hidden markov models.
QuestionNoob Question: Will not compile on MonoDevelop on OSXmemberuwnanopore20-Aug-12 11:42 
Hi,
Completely new to C#. Programmed in c/c++ 6 years ago, then matlab since. Need faster hmming, so came across this, and c# as a good language. However, this does not compile, giving the error: Error CS0246: The type or namespace name `OleDbConnectionStringBuilder' could not be found. Are you missing a using directive or an assembly reference? (CS0246) (HMM)
 
What am I doing wrong? Any help would be great. Thanks.
-Ian
AnswerRe: Noob Question: Will not compile on MonoDevelop on OSXmemberCésar de Souza20-Aug-12 12:12 
Hi Ian,
 
The OleDb* classes are only required to read Excel files. If you are using it under OSX, it would be understandable there would be no support for it. To fix this error, you could remove the OleDb dependences and insert your data another way (such as using .csv files). In any case, I would recommend using the latest version of this code available in the Accord.NET Framework. However, the problem is that it most likely won't compile under Mono as well. But you could try loading the assemblies directly, without recompiling.
 
If you really need it I could try working on the Mono support again. At some time the framework did compile on Mono, but since there wasn't much interest on this feature it gradually faded away after some releases.
 
Best regards,
Cesar
Interested in Machine Learning in .NET? Check the Accord.NET Framework.
See also Handwriting Recognition Revisited: Kernel Support Vector Machines

GeneralRe: Noob Question: Will not compile on MonoDevelop on OSXmemberuwnanopore21-Aug-12 11:15 
Hi Cesar,
I kinda figured as much, but hoped that it was something really dumb that I was doing. I'll have to do a bunch more learning to implement .csv or other data type input so that It will work with your function, but I suppose that that will do me well... Unless its quite trivial for you to implement mono support, I'll (continue to) work more to see if I can get it to work via other input routes. Thanks!
-Ian
Questionautoregressive HMMmemberssamson23-Jul-12 3:55 
Hi Cesar
 
Thank you very much for you previous answers.
 
Could you please comment if your code implements autoregressive HMM (regime switching is another name) as described in Rabiner 1989 tutorial. Would it be difficult to add it if it is not implemented?
 
Thank you,
Sergey.
AnswerRe: autoregressive HMMmemberCésar de Souza15-Aug-12 16:04 
Hi,
 
Sorry for noticing the question this late. I have heard about autoregressive HMMs but I don't know much about them. I can't really say if it would be difficult or not because I haven't tried, but since the framework already contains codes for many related algorithms such as the Forward, Backward, learning and etc I suspect it would be easier to achieve something starting with the framework than from scratch.
 
Best regards,
Cesar
Interested in Machine Learning in .NET? Check the Accord.NET Framework.
See also Handwriting Recognition Revisited: Kernel Support Vector Machines

Questiona few questionsmemberssamson13-Jul-12 7:14 
Hello César
 
Thank you for sharing your code. I am a new C# programmer and new to HMM but have some knowledge of C++.
 
I have the following question:
 
Using this code how do I make prediction for the next symbol. Let's say I have very long single sequence (10000 samples) with about 2^k symbols (64 is common) and a few hidden states (may be 4-10). Given the current state I want to calculate probaility of the next symbol. In your example you have more than one sequences, I have only one but very long. In your example you look for proability of the particular sequence but I would like to get only probability of single symbol but from current location.
 
Thank you very much!
AnswerRe: a few questionsmemberCésar de Souza13-Jul-12 7:26 
Hi ssamson,
 
The latest version is this code, available in the Accord.NET Framework[^], has a "Predict"[^] method which can be used to predict the next observation in a sequence.
 
It works by calculating the likelihood of the sequence you gave, plus all possible variations for the next symbol, then selecting the one with the highest likelihood. You can browse the specific source code for the prediction method here[^], if you would like to.
 
Please keep in mind, however, this isn't always a very useful prediction due the limitations of the Markov assumption.
 
Best regards,
Cesar
Interested in Machine Learning in .NET? Check the Accord.NET Framework.
See also Handwriting Recognition Revisited: Kernel Support Vector Machines

GeneralRe: a few questionsmemberssamson13-Jul-12 7:39 
Thank you Cesar. I was confused because all your sequences starting from 0 have high probability but all sequences starting from 1 have low probability, so in your example why sequence 11 have low probability, it can be just a part of your HMM, for example, starting from the middle (0111 sequence).
 
Could you please give me a more general recomendation. In my example I have descrete symbols and in reality I have continuous that I discretized. This symbols are derived from wavelet coeficients. Is there a more general approach that will be able to process contunuous symbols to produce prediction. These are not ARMA time series so Markov approach seems the best.
GeneralRe: a few questionsmemberCésar de Souza13-Jul-12 7:58 
Hi ssamson,
 
It isn't part of the HMM because, by default, the HMMs were created with forward-only topologies. I just realized the code in this article was a bit outdated and this wasn't entirely clear. In the supported framework version you are able to specify different topologies[^] in the model constructor.
 
And about your data, instead of discretizing your samples you could instead use continuous-density hidden Markov models[^]. Those HMMs are able to work directly with continuous observations. The drawback, however, is that you can't anymore predict an observation by testing all possible symbol combinations, since those are now continuous. The framework has a version of the "Predict[^]" method for continuous distributions based on the mode for the next state distribution.
 
But again, this isn't always useful. There are more complex schemes for finding predictions based on sequence alignment which may work better, such as the ones shown in this thesis[^] or this paper[^]
Interested in Machine Learning in .NET? Check the Accord.NET Framework.
See also Handwriting Recognition Revisited: Kernel Support Vector Machines

GeneralMy vote of 5memberMember 917670328-Jun-12 4:38 
Its nice... Very helpful..
QuestionSource codememberMember 917670328-Jun-12 2:34 
Its nice tutorial for beginners.I have downloaded source code from given link. But I didn't get how to run this program.
Can you help me with this problem?
waiting for your reply..
AnswerRe: Source codememberCésar de Souza28-Jun-12 3:25 
Hi,
 
The latest version of the downloadable executable can be found in Google Code[^]. If you would just like to run it, you can download the .rar, then open the HMM.exe executable. You can load some test data by clicking File->Open. By default, it will open a folder with an "example.xls" file. Now, you can press "create" to create the classifier for the file loaded. On the second tab you can press "start training" to train the just created models. Then, finally, on the last tab, you can test the model in your own data by clicking "Evaluate". Please note this is just a sample application, to demonstrate how the code can be used.
 
If you would rather develop your own application with this software, please take a look on the full Accord.NET Framework[^]. It includes the most up-to-date version of this code, with the latest fixes and enhancements. Plus it has a getting started guide[^] which can help creating your own applications.
 
Best regards,
Cesar
Interested in Machine Learning in .NET? Check the Accord.NET Framework.
See also Handwriting Recognition Revisited: Kernel Support Vector Machines

GeneralRe: Source codememberMember 917670328-Jun-12 4:39 
Thank You so much...
GeneralMy vote of 5memberVietdungiitb11-Jun-12 15:14 
Excellent, I am studying HMM. Your article helps me so much. Thank you.
Questionhelp about code markov [modified]memberMAJIDBAGHERI16-Apr-12 9:18 
hi
I want write the crawler with hmm in link paper below:
http://web.cs.dal.ca/~eem/cvWeb/pubs/Hongyu-Data-Knowledge-Eng-2006.pdf[^]
but also How can I use this code to "predict" future combinations in the sequence?
and what do you mean about sequence word?i read example your code but for crawler
what is sequence?
pleas help me?

modified 17-Apr-12 14:56pm.

QuestionHave you tried to use this algorithm for POS taggingmemberIrtiza Ahmed4-Dec-11 13:02 
Hi, I am using similar algorithm for unsupervised POS tagging.
In my case, I define the following
there are 20 different states
a fixed number of word tokens may be 2000
 
and the initial probabilities are randomly assigned.
 
But apparently, when the algorithm converges, the Viterbi Algorithm produces tag sequences from a specific two or three tags. I am assuming I am doing something wrong.
 
Any suggestion?
Questionprediction of urlsmembergreeshmag24-Nov-11 22:03 
Can this model be used for predicting urls?
GeneralMy vote of 5memberFilip D'haene26-May-11 0:36 
Excellent work!
 
Thanks for sharing. Wink | ;)
QuestionHi! How can I use this code to "predict" future combinations in the sequence?memberyuriythebest13-Jan-11 6:02 
Hi! How can I use this code to "predict" future combinations in the sequence?
AnswerRe: Hi! How can I use this code to "predict" future combinations in the sequence?memberCésar de Souza27-Jan-11 15:08 
Hi there,
 
At this time, this code does not offer any method to perform sequence prediction. But this is something which will be added soon. The next version of Accord.NET[^] will introduce many changes in the Hidden Markov Model package, including the addition of a Predict() method to predict the next observation in a sequence.
 
Best regards,
César
Interested in Machine Learning in .NET? Check the Accord.NET Framework.
See also Handwriting Recognition Revisited: Kernel Support Vector Machines

Questionwhat compiler should I use?memberyuriythebest12-Jan-11 4:36 
Hi! stupid question, but I tried opening it in Visual Studio 2005 and it didn't work- what compiler should I use?
AnswerRe: what compiler should I use?memberCésar de Souza12-Jan-11 5:02 
Hi there,
 
The version of Visual Studio used for development was VS2008.
 
Best regards,
César
Interested in Machine Learning in .NET? Check the Accord.NET Framework.
See also Handwriting Recognition Revisited: Kernel Support Vector Machines

GeneralRe: what compiler should I use?memberyuriythebest12-Jan-11 10:54 
cool thanks!
GeneralMy vote of 5memberEdex12324-Dec-10 1:33 
Thank you! I needed a working Viterbi implementation in C# and this one WORKS! There is another one referenced on Wikipedia, but that one is sh*t (it completely discards the emission matrix when searching for the most probable path).
 
THANK YOU very much! Smile | :)
GeneralMy vote of 5memberRick Dean14-Dec-10 3:31 
A great intro to subject matter with code for experimentation. Thanks so much.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130617.1 | Last Updated 5 Dec 2010
Article Copyright 2010 by César de Souza
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid