Question about 3.2.0 API for HiddenMarkovClassifier

148 views
Skip to first unread message

Craig

unread,
Sep 10, 2016, 9:16:01 AM9/10/16
to Accord.NET Framework
Is there an API for the new code that will eliminate the errors below:

When I upgrade to Accord Framework 3.2.0 and run software I get 2 'obsolete' errors:

Warning 1 'HiddenMarkovClassifier'<'MultivariateNormalDistribution'>'' is obsolete: 'Please use HiddenMarkovClassifier'<'TDistribution, TObservation'>' instead.'

Warning 14 'BaumWelchLearning'<'MultivariateNormalDistribution'>' is obsolete: 'Please use BaumWelchLearning'<'TDistribution, TObservation'>' instead.'

There is no apparent API for the BaumWelchLearning'<'TDistribution, TObservation'>'. When I go to the new API for HiddenMarkovClassifier'<'TDistribution'>' and the relatively minor changes reflected on that documentation it does not fix the 2 issues above but does improve analysis run time.

César

unread,
Sep 17, 2016, 12:52:34 PM9/17/16
to Accord.NET Framework
Ops! Thanks for reporting this issue, it seems I forgot to update the documentation examples for the hidden Markov model classes. If you are using double-valued observations, please add ", double" to the end of the generic parameters of the Baum-Welch learning class.

For instance, please consider the example below:

// Create continuous sequences. In the sequences below, there
//  seems to be two states, one for values between 0 and 1 and
//  another for values between 5 and 7. The states seems to be
//  switched on every observation.
double[][] sequences = new double[][]
{
 new double[] { 0.1, 5.2, 0.3, 6.7, 0.1, 6.0 },
 new double[] { 0.2, 6.2, 0.3, 6.3, 0.1, 5.0 },
 new double[] { 0.1, 7.0, 0.1, 7.0, 0.2, 5.6 },
};

// Specify a initial normal distribution for the samples.
var density = new NormalDistribution();

// Creates a continuous hidden Markov Model with two states organized in a forward
//  topology and an underlying univariate Normal distribution as probability density.
var model = new HiddenMarkovModel<NormalDistribution, double>(new Ergodic(2), density);

// Configure the learning algorithms to train the sequence classifier until the
// difference in the average log-likelihood changes only by as little as 0.0001
var teacher = new BaumWelchLearning<NormalDistribution, double>(model)
{
 Tolerance = 0.0001,
 Iterations = 0,
};

// Fit the model
teacher.Learn(sequences);

// See the log-probability of the sequences learned
double a1 = model.Evaluate(new[] { 0.1, 5.2, 0.3, 6.7, 0.1, 6.0 }); // -0.12799388666109757
double a2 = model.Evaluate(new[] { 0.2, 6.2, 0.3, 6.3, 0.1, 5.0 }); // 0.01171157434400194

// See the probability of an unrelated sequence
double a3 = model.Evaluate(new[] { 1.1, 2.2, 1.3, 3.2, 4.2, 1.0 }); // -298.7465244473417
double likelihood = Math.Exp(logLikelihood);

a1 = Math.Exp(a1); // 0.879
a2 = Math.Exp(a2); // 1.011
a3 = Math.Exp(a3); // 0.000

// We can also ask the model to decode one of the sequences. After
// this step the resulting sequence will be: { 0, 1, 0, 1, 0, 1 }
int[] states = model.Decode(new[] { 0.1, 5.2, 0.3, 6.7, 0.1, 6.0 });

If you need more information, please let me know. Again sorry for the lack of updated documentation. I will update it in the following days.

Regards,
Cesar

Craig

unread,
Sep 18, 2016, 9:39:20 PM9/18/16
to Accord.NET Framework
HI Cesar,
I can't quite get to the new version, I am having problems finding the NormalDistribution interface.
I am using MultivariteNormalDistribution as in the current API.

Error 5:

The type 'Accord.Statistics.Distributions.Multivariate.MultivariateNormalDistribution' cannot be used as type parameter 'TDistribution' in the generic type or method 'Accord.Statistics.Models.Markov.HiddenMarkovClassifier<TDistribution,TObservation>'. There is no implicit reference conversion from 'Accord.Statistics.Distributions.Multivariate.MultivariateNormalDistribution' to 'Accord.Statistics.Distributions.IDistribution<double>'.


César

unread,
Sep 19, 2016, 1:42:08 PM9/19/16
to Accord.NET Framework
Hi Craig,

If you are using multivariate samples, then pass double[] as the second generic argument to BaumWelchLearning<NormalDistribution, double>(model) and HiddenMarkovModel<NormalDistribution, double> instead, i.e.:


    BaumWelchLearning<MultivariateNormalDistribution, double[]>

Sorry if the new API seems a bit messier. However, it should allow for much better performance in future releases. Also, using this new interface it should also become possible to create a hidden Markov model of any kind of observations, such as for example, strings, graphs or trees.

Regards,
Cesar

Craig

unread,
Sep 19, 2016, 9:41:46 PM9/19/16
to Accord.NET Framework
Cesar,  I'm excited to try it. I'm getting closer but it's not quite there.

<Sample Code..
                var initialDensity = new MultivariateNormalDistribution(4);

                HMM = new HiddenMarkovClassifier<MultivariateNormalDistribution, double[]>(classes.Count,      // this runs fine
                    topology: new Forward(states), initial: initialDensity);
                try
                {
                    var teacher = new HiddenMarkovClassifierLearning<MultivariateNormalDistribution, double[]>(HMM,
                        i => new BaumWelchLearning<MultivariateNormalDistribution, double[]>(HMM.Models[i])            // this throws an error invalid arguments
                           {
                               Iterations = iterations,
                               Tolerance = tolerance,

                               FittingOptions = new NormalOptions()
                               {
                                   Diagonal = true,
                                   Regularization = 1e-2
                               }
                           }
                       );

                    teacher.Empirical = true;
                    teacher.Rejection = rejection;
                    
                    double error = await Task.Run(() => { return teacher.Run(inputs, outputs); });     // teacher.Run() is not accessible
..Code >

The Errors are:  

....BaumWelchLearning has some invalid arguments
....teacher.Run(inputs, outputs) is inaccessible due to its protection level
....also Can not run HMM.Compute() 

César

unread,
Sep 20, 2016, 4:20:19 AM9/20/16
to Accord.NET Framework
Hi Craig,

Sorry about that again. Please call .Learn(inputs, outputs) instead of .Run(inputs, outputs). The main point of the new API was to provide a new pattern to learn machine learning models. Now, every learning algorithm provides a .Learn(x, y) method that produces a classifier/regression that you can use to classify/transform your data.

The classifiers also now offer standardized methods to perform each task. To decide a class/state label for each of your observations in your observation sequence, you can use the hmm.Decide() method. In order to evaluate the probability of a sequence, you can use hmm.LogLikelihood() or hmm.Probability().

An example can be found below:

     var density = new MultivariateNormalDistribution(3);
     
var model = new HiddenMarkovModel<MultivariateNormalDistribution, double[]>(new Forward(5), density);


     
var learning = new BaumWelchLearning<MultivariateNormalDistribution, double[]>(model)

     
{
         
Tolerance = 0.0001,
         
Iterations = 0,

         
FittingOptions = new NormalOptions() { Regularization = 0.0001 }
     
};


     learning
.Learn(observations);


     
int[] y = hmm.Decide(sequence_of_observations); // will provide a class label for each observation in the sequence

     
double ll = hmm.LogLikelihood(sequence_of_observations); // will provide the log-likelihood of the sequence




Regards,
Cesar

Craig

unread,
Sep 21, 2016, 8:09:52 PM9/21/16
to Accord.NET Framework
Cesar,

I'm stuck trying to figure out how learning.Learn(inputs) will train the model to recognize the outputs labels for each sequence.

double[] weights; // the weighting of importance for each sequence.

It does not accept learning.Learn(inputs, outputs).. Just learning.Learn(inputs, weights).

I really thank you for your help with this.

CS

               var initialDensity = new MultivariateNormalDistribution(4);  // this is the number of inputs in each sequence

                var model = new HiddenMarkovModel<MultivariateNormalDistribution, double[]>(new Forward(states), initialDensity);

                var learning = new BaumWelchLearning<MultivariateNormalDistribution, double[]>(model)
                {
                    Tolerance = tolerance,
                    Iterations = iterations,

                    FittingOptions = new NormalOptions() { Regularization = 0.0001 }
                };

                learning.Learn(inputs);    // the inputs[][][] are the sequences for learning

                int[][] ydec = model.Decide(inputs);   // will provide a class label for each observation in the sequence === ?  How does this occur with no output categories learned

                double[] resl = model.LogLikelihood(inputs); // will provide the log-likelihood of the sequence

César

unread,
Sep 22, 2016, 3:49:03 AM9/22/16
to Accord.NET Framework
Hi Craig,

What kind of classification problem you are trying to solve? Are you trying to solve sequence classification, or part-of-sequence tagging?

If you have a label for each observation for your sequence, then probably Baum-Welch wouldn't be the best candidate for learning that. Baum-Welch is an unsupervised learning algorithm, in the sense that it doesn't need the state labels to determine them. Let's say its a kind of temporal clustering. If you have the labels, it should be better to use MaximumLikelihoodLearning instead.

However, if you have a label for each of your sequences (in contrast to having for each observation in the sequence), then Baum-Welch is fine, but it has to be used from inside a HiddenMarkovClassifier. A Markov classifier is basically a group of Markov models where each model has been trained on each class of sequences.

For example, supposing you have two sequences in your dataset, one having label 0 and another having label 1, you could train a Markov classifier using:

 // Create a Continuous density Hidden Markov Model Sequence Classifier
 // to detect a univariate sequence and the same sequence backwards.

 double[][] sequences = new double[][]
 {
  new double[] { 0,1,2,3,4 }, // This is the first  sequence with label = 0
  new double[] { 4,3,2,1,0 }, // This is the second sequence with label = 1
 };

 // Labels for the sequences
 int[] labels = { 0, 1 };

 // Creates a sequence classifier containing 2 hidden Markov Models
 //  with 2 states and an underlying Normal distribution as density.

 var density = new NormalDistribution();
 var classifier = new HiddenMarkovClassifier<NormalDistribution, double>(2, new Ergodic(2), density);

 // Configure the learning algorithms to train the sequence classifier
 var teacher = new HiddenMarkovClassifierLearning<NormalDistribution, double>(classifier)
 {
  // Train each model until the log-likelihood changes less than 0.001
  Learner = modelIndex => new BaumWelchLearning<NormalDistribution, double>(classifier.Models[modelIndex])

  {
   Tolerance = 0.0001,
   Iterations = 0
  }
 };

 // Train the sequence classifier using the algorithm
 teacher.Learn(sequences, labels);

 double logLikelihood = teacher.LogLikelihood;

 // Calculate the probability that the given
 //  sequences originated from the model
 double likelihood1, likelihood2;

 // Try to classify the first sequence (output should be 0)
 int c1 = classifier.Decide(sequences[0]);
 likelihood1 = classifier.Probability(sequences[0]);
 
 // Try to classify the second sequence (output should be 1)
 int c2 = classifier.Decide(sequences[1]);
 likelihood2 = classifier.Probability(sequences[1]);



Regards,
Cesar

Craig

unread,
Sep 22, 2016, 8:03:06 AM9/22/16
to Accord.NET Framework
Thank you , Cesar,

I am solving a sequence of observations so I will use BaumWelch within HiddenMarkovClassifier.

But I am using a sequence of observations along with 3 other sets of data, so there are (4) data Inputs to use for learning; and there is a label for each set of data along with the observation sequence.  This will require a MultivariteNormalDistribution instead of a NormalDistribution, correct?  That leads me back to the initial questions where 'BaumWelchLearning'<'MultivariateNormalDistribution'>' is obsolete:  so I will try to use the same logic and coding but will use a MultivariteNormalDistibution instead of a NormalDistribution.
Thanks again !
Craig


Craig

unread,
Sep 24, 2016, 9:57:16 AM9/24/16
to Accord.NET Framework
Hi Cesar, 

Great improvements in accuracy and speed, I'll keep in touch on the progress.  Thank you for your work!

Craig

manish....@gmail.com

unread,
Jan 5, 2017, 12:24:57 AM1/5/17
to Accord.NET Framework
Hi Cesar,

Thank you for creating & supporting this wonderful library. I am working with "multivariate" model and have gotten to a point where I can train an HMM and use "Decode" to identify states and "Decide" to classify given the observations. Now I am trying to use predict (to predict next set of observations) but hitting a wall saying "System.NotSupportedException" occurred in Accord.Statistics.dll.....I am sure I am missing something here, by any chance do you have any insights or an example of usage for predict?

Dim density = New MultivariateNormalDistribution(10)
Dim model = New HiddenMarkovModel(Of MultivariateNormalDistribution, Double())(New Ergodic(4, True), density)

Dim learning = New BaumWelchLearning(Of MultivariateNormalDistribution, Double())(model) With { _
.Tolerance = 0.000001, _
.Iterations = 0, _
.FittingOptions = New NormalOptions() With { _
.Regularization = 0.000001 _
} _
}

' Fit the model
learning.Learn(sequences)

'test(0)(10)(10) <-last 10 observations with 10 variables.....
Dim test_states As Integer() = model.Decide(tests(0)) -> tests(0)
nextObservation = model.Predict(tests(0)) -> this is where I get error

Thanks,
Manish

Surya Kiran

unread,
Jan 29, 2017, 8:19:02 AM1/29/17
to Accord.NET Framework
Hi Manish, 

maybe you can try like this -

              var density = new MultivariateNormalDistribution(3);
              classifier = new HiddenMarkovClassifier<MultivariateNormalDistribution, double[]>(10, new Ergodic(3), density);
         
            // Configure the learning algorithms to train the sequence classifier
            var teacher = new HiddenMarkovClassifierLearning<MultivariateNormalDistribution, double[]>(classifier)
            {
                // Train each model until the log-likelihood changes less than 0.0001
                Learner = modelIndex => new BaumWelchLearning<MultivariateNormalDistribution, double[]>(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
                    }
                }

            };

         
            // Train the sequence classifier using the algorithm
            teacher.Learn(trainArray, labelArray);
           
Reply all
Reply to author
Forward
0 new messages