Exemple #1
0
        public static void Main(string[] args)
        {
            var data = new Sequences("nbt.1882-S6.txt");

            // Now we create a hidden Markov model with arbitrary probabilities
            var hmm = new HiddenMarkovModel(states: data.StateNum, symbols: data.SymbolNum);

            // Create a Baum-Welch learning algorithm to teach it
            var teacher = new BaumWelchLearning(hmm);

            // and call its Run method to start learning
            var    trainSamples = data.PartOfSequences(0, 2);
            double error        = teacher.Run(trainSamples);

            var testSamples = data.PartOfSequences(1, 2);

            // Let's now check the probability of some sequences:
            double prob1 = Math.Exp(hmm.Evaluate(trainSamples [0]));
            double prob2 = Math.Exp(hmm.Evaluate(trainSamples [1]));
            double prob3 = Math.Exp(hmm.Evaluate(trainSamples [2]));

            // Now those obviously violate the form of the training set:
            double prob4 = Math.Exp(hmm.Evaluate(testSamples [0]));
            double prob5 = Math.Exp(hmm.Evaluate(testSamples [1]));
        }
        static void runArbitraryDensityHiddenMarkovModelLearningExample()
        {
            // 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[][] observationSequences = 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 },
            };

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

            // 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 trainer = new BaumWelchLearning <NormalDistribution>(hmm)
            {
                Tolerance  = 0.0001,
                Iterations = 0,
            };

            // Fit the model.
            double averageLogLikelihood = trainer.Run(observationSequences);

            Console.WriteLine("average log-likelihood for the observations = {0}", averageLogLikelihood);

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

            // The log-probability of an unrelated sequence.
            double logLik3 = hmm.Evaluate(new[] { 1.1, 2.2, 1.3, 3.2, 4.2, 1.0 });  // -298.7465244473417.

            // Transform the log-probabilities to actual probabilities.
            Console.WriteLine("probability = {0}", Math.Exp(logLik1));  // 0.879.
            Console.WriteLine("probability = {0}", Math.Exp(logLik2));  // 1.011.
            Console.WriteLine("probability = {0}", Math.Exp(logLik3));  // 0.000.

            // Ask the model to decode one of the sequences.
            // The state variable will contain: { 0, 1, 0, 1, 0, 1 }.
            double logLikelihood = 0.0;

            int[] path = hmm.Decode(new[] { 0.1, 5.2, 0.3, 6.7, 0.1, 6.0 }, out logLikelihood);
            Console.Write("log-likelihood = {0}, Viterbi path = [", logLikelihood);
            foreach (int state in path)
            {
                Console.Write("{0},", state);
            }
            Console.WriteLine("]");
        }
        public static void Evaluate()
        {
            double[,] transition =
            {
                { 0.7, 0.3 },
                { 0.4, 0.6 }
            };

            double[,] emission =
            {
                { 0.1, 0.4, 0.5 },
                { 0.6, 0.3, 0.1 }
            };

            double[] initial = { 0.6, 0.4 };

            HiddenMarkovModel hmm = new HiddenMarkovModel(transition, emission, initial);

            int[] sequence = new int[] { 0, 1, 2 };

            double logLikeliHood = hmm.Evaluate(sequence);

            // At this point, the log-likelihood of the sequence
            // occurring within the model is -3.3928721329161653.
            Console.WriteLine("logLikeliHood: {0}", logLikeliHood);
        }
Exemple #4
0
        public static double BaumWelchLearning(double[][] data)
        {
            // Specify a initial normal distribution for the samples.
            NormalDistribution 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>(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>(model)
            {
                Tolerance  = 0.001,
                Iterations = 0,
            };

            // Fit the model
            double likelihood = teacher.Run(data);

            // See the log-probability of the sequences learned
            double a1 = model.Evaluate(new[] { 0.999999999999928, 0, 0.999999999999988, 0, 0.999999999999988 });    // -0.12799388666109757

            return(a1);
        }
        public void LikelihoodTest()
        {
            var hmm = DiscreteHiddenMarkovModelFunctionTest.CreateModel2();

            int states  = hmm.States;
            int symbols = hmm.Symbols;

            var hcrf = new ConditionalRandomField <int>(states,
                                                        new MarkovDiscreteFunction(hmm));

            var hmm0  = new HiddenMarkovModel(states, symbols);
            var hcrf0 = new ConditionalRandomField <int>(states,
                                                         new MarkovDiscreteFunction(hmm0));


            int[]  observations = new int[] { 0, 0, 1, 1, 1, 2 };
            double la           = hcrf.LogLikelihood(observations, observations);
            double lb           = hcrf0.LogLikelihood(observations, observations);

            Assert.IsTrue(la > lb);

            double lc = hmm.Evaluate(observations, observations);
            double ld = hmm0.Evaluate(observations, observations);

            Assert.IsTrue(lc > ld);

            double za = hcrf.LogPartition(observations);
            double zb = hcrf0.LogPartition(observations);

            la += za;
            lb += zb;

            Assert.AreEqual(la, lc, 1e-6);
            Assert.AreEqual(lb, ld, 1e-6);
        }
Exemple #6
0
        public void GenerateTest()
        {
            // Example taken from http://en.wikipedia.org/wiki/Viterbi_algorithm

            double[,] transition =
            {
                { 0.7, 0.3 },
                { 0.4, 0.6 }
            };

            double[,] emission =
            {
                { 0.1, 0.4, 0.5 },
                { 0.6, 0.3, 0.1 }
            };

            double[] initial =
            {
                0.6, 0.4
            };

            HiddenMarkovModel hmm = new HiddenMarkovModel(transition, emission, initial);

            double logLikelihood;

            int[] path;
            int[] samples = hmm.Generate(10, out path, out logLikelihood);

            double expected = hmm.Evaluate(samples, path);

            Assert.AreEqual(expected, logLikelihood);
        }
Exemple #7
0
        public double Run(int[][] observations_db)
        {
            int K = observations_db.Length;

            double currLogLikelihood = Double.NegativeInfinity;

            for (int k = 0; k < K; ++k)
            {
                currLogLikelihood = LogHelper.LogSum(currLogLikelihood, mModel.Evaluate(observations_db[k]));
            }

            double oldLogLikelihood   = -1;
            double deltaLogLikelihood = -1;
            int    iteration          = 0;

            do
            {
                oldLogLikelihood = currLogLikelihood;

                int[][] paths_db = new int[K][];
                for (int k = 0; k < K; ++k)
                {
                    paths_db[k] = mModel.Decode(observations_db[k]);
                }

                mMaximumLikelihoodLearner.Run(observations_db, paths_db);

                currLogLikelihood = double.NegativeInfinity;
                for (int k = 0; k < K; ++k)
                {
                    currLogLikelihood = LogHelper.LogSum(currLogLikelihood, mModel.Evaluate(observations_db[k]));
                }

                deltaLogLikelihood = System.Math.Abs(currLogLikelihood - oldLogLikelihood);
                iteration++;
            }while(!ShouldTerminate(deltaLogLikelihood, iteration));

            return(currLogLikelihood);
        }
Exemple #8
0
        public void DecodeTest()
        {
            // Example taken from http://en.wikipedia.org/wiki/Viterbi_algorithm

            // Create the transition matrix A
            double[,] transition =
            {
                { 0.7, 0.3 },
                { 0.4, 0.6 }
            };

            // Create the emission matrix B
            double[,] emission =
            {
                { 0.1, 0.4, 0.5 },
                { 0.6, 0.3, 0.1 }
            };

            // Create the initial probabilities pi
            double[] initial =
            {
                0.6, 0.4
            };

            // Create a new hidden Markov model
            HiddenMarkovModel hmm = new HiddenMarkovModel(transition, emission, initial);

            // After that, one could, for example, query the probability
            // of a sequence occurring. We will consider the sequence
            int[] sequence = new int[] { 0, 1, 2 };

            // And now we will evaluate its likelihood
            double logLikelihood = hmm.Evaluate(sequence);

            // At this point, the log-likelihood of the sequence
            // occurring within the model is -3.3928721329161653.

            // We can also get the Viterbi path of the sequence
            int[] path = hmm.Decode(sequence, out logLikelihood);

            // At this point, the state path will be 1-0-0 and the
            // log-likelihood will be -4.3095199438871337


            Assert.AreEqual(logLikelihood, Math.Log(0.01344), 1e-10);
            Assert.AreEqual(path[0], 1);
            Assert.AreEqual(path[1], 0);
            Assert.AreEqual(path[2], 0);
        }
Exemple #9
0
        /// <summary>
        /// Returns a dictionary of Markov probabilities for all supplied sequences
        /// </summary>
        /// <param name="sequences"></param>
        /// <returns></returns>
        public Dictionary <string, double> GetMarkovProbabilities(List <string> sequences)
        {
            Dictionary <string, double> probabilities = new Dictionary <string, double>();

            //determine probability for each sequence
            foreach (string sequence in sequences)
            {
                //each sequence is in the form "#-#-#...-#".  We need to conver this into an array of
                //integers for use in the markov model
                int[] sequenceNumbers = sequence.Split('_').Select(m => Convert.ToInt32(m)).ToArray();

                //store probability in dictionary for use elsewhere
                probabilities[sequence] = Math.Exp(_model.Evaluate(sequenceNumbers));
            }

            return(probabilities);
        }
        static void runDiscreteDensityHiddenMarkovModelExample()
        {
            // Create the transition matrix A.
            double[,] transition =
            {
                { 0.7, 0.3 },
                { 0.4, 0.6 }
            };

            // Create the emission matrix B.
            double[,] emission =
            {
                { 0.1, 0.4, 0.5 },
                { 0.6, 0.3, 0.1 }
            };

            // Create the initial probabilities pi.
            double[] initial =
            {
                0.6, 0.4
            };

            // Create a new hidden Markov model.
            HiddenMarkovModel hmm = new HiddenMarkovModel(transition, emission, initial);

            // Query the probability of a sequence occurring.
            int[] sequence = new int[] { 0, 1, 2 };

            // Evaluate its likelihood.
            double logLikelihood = hmm.Evaluate(sequence);

            // The log-likelihood of the sequence occurring within the model is -3.3928721329161653.
            Console.WriteLine("log-likelihood = {0}", logLikelihood);

            // Get the Viterbi path of the sequence.
            int[] path = hmm.Decode(sequence, out logLikelihood);

            // The state path will be 1-0-0 and the log-likelihood will be -4.3095199438871337.
            Console.Write("log-likelihood = {0}, Viterbi path = [", logLikelihood);
            foreach (int state in path)
            {
                Console.Write("{0},", state);
            }
            Console.WriteLine("]");
        }
        static void runArbitraryDensityHiddenMarkovModelExample()
        {
            // Create the transition matrix A.
            double[,] transitions =
            {
                { 0.7, 0.3 },
                { 0.4, 0.6 }
            };

            // Create the vector of emission densities B.
            GeneralDiscreteDistribution[] emissions =
            {
                new GeneralDiscreteDistribution(0.1, 0.4, 0.5),
                new GeneralDiscreteDistribution(0.6, 0.3, 0.1)
            };

            // Create the initial probabilities pi.
            double[] initial =
            {
                0.6, 0.4
            };

            // Create a new hidden Markov model with discrete probabilities.
            var hmm = new HiddenMarkovModel <GeneralDiscreteDistribution>(transitions, emissions, initial);

            // Query the probability of a sequence occurring. We will consider the sequence.
            double[] sequence = new double[] { 0, 1, 2 };

            // Evaluate its likelihood.
            double logLikelihood = hmm.Evaluate(sequence);

            // The log-likelihood of the sequence occurring within the model is -3.3928721329161653.
            Console.WriteLine("log-likelihood = {0}", logLikelihood);

            // Get the Viterbi path of the sequence.
            int[] path = hmm.Decode(sequence, out logLikelihood);

            // The state path will be 1-0-0 and the log-likelihood will be -4.3095199438871337.
            Console.Write("log-likelihood = {0}, Viterbi path = [", logLikelihood);
            foreach (int state in path)
            {
                Console.Write("{0},", state);
            }
            Console.WriteLine("]");
        }
Exemple #12
0
        public static void ViterbiLearning()
        {
            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(state_count: 3, symbol_count: 2);

            // Try to fit the model to the data until the difference in
            //  the average log-likelihood changes only by as little as 0.0001
            var teacher = new ViterbiLearning(hmm)
            {
                Tolerance = 0.0001, Iterations = 0
            };
            double ll = teacher.Run(sequences);

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

            Console.WriteLine("l1: {0}", System.Math.Exp(l1));
            Console.WriteLine("l2: {0}", System.Math.Exp(l2));

            // Sequences which do not start with zero have much lesser probability.
            double l3 = hmm.Evaluate(new int[] { 1, 1 });       // 0.000
            double l4 = hmm.Evaluate(new int[] { 1, 0, 0, 0 }); // 0.000

            Console.WriteLine("l3: {0}", System.Math.Exp(l3));
            Console.WriteLine("l4: {0}", System.Math.Exp(l4));

            // Sequences which contains few errors have higher probability
            //  than the ones which do not start with zero. This shows some
            //  of the temporal elasticity and error tolerance of the HMMs.
            double l5 = hmm.Evaluate(new int[] { 0, 1, 0, 1, 1, 1, 1, 1, 1 }); // 0.034
            double l6 = hmm.Evaluate(new int[] { 0, 1, 1, 1, 1, 1, 1, 0, 1 }); // 0.034

            Console.WriteLine("l5: {0}", System.Math.Exp(l5));
            Console.WriteLine("l6: {0}", System.Math.Exp(l6));
        }
Exemple #13
0
        public static void BaumWelchLearning()
        {
            // We will try to create a Hidden Markov Model which
            //  can detect if a given sequence starts with a zero
            //  and has any number of ones after that.
            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(3, 2);

            // Try to fit the model to the data until the difference in
            //  the average log-likelihood changes only by as little as 0.0001
            var teacher = new BaumWelchLearning(hmm)
            {
                Tolerance = 0.0001, Iterations = 0
            };

            double ll = teacher.Run(sequences);
            double l0 = Math.Exp(hmm.Evaluate(new int[] { 1, 0 }));
            // Calculate the probability that the given
            //  sequences originated from the model
            double l1 = Math.Exp(hmm.Evaluate(new int[] { 0, 1 }));       // 0.999
            double l2 = Math.Exp(hmm.Evaluate(new int[] { 0, 1, 1, 1 })); // 0.916

            // Sequences which do not start with zero have much lesser probability.
            double l3 = Math.Exp(hmm.Evaluate(new int[] { 1, 1 }));       // 0.000
            double l4 = Math.Exp(hmm.Evaluate(new int[] { 1, 0, 0, 0 })); // 0.000

            // Sequences which contains few errors have higher probability
            //  than the ones which do not start with zero. This shows some
            //  of the temporal elasticity and error tolerance of the HMMs.
            double l5 = Math.Exp(hmm.Evaluate(new int[] { 0, 1, 0, 1, 1, 1, 1, 1, 1 })); // 0.034
            double l6 = Math.Exp(hmm.Evaluate(new int[] { 0, 1, 1, 1, 1, 1, 1, 0, 1 })); // 0.034
        }
Exemple #14
0
        public static void Viterbi()
        {
            // Create the transition matrix A
            double[,] transition =
            {
                { 0.7, 0.3 },
                { 0.4, 0.6 }
            };

            // Create the emission matrix B
            double[,] emission =
            {
                { 0.1, 0.4, 0.5 },
                { 0.6, 0.3, 0.1 }
            };

            // Create the initial probabilities pi
            double[] initial =
            {
                0.6, 0.4
            };

            // Create a new hidden Markov model
            HiddenMarkovModel hmm = new HiddenMarkovModel(transition, emission, initial);

            // After that, one could, for example, query the probability
            // of a sequence occurring. We will consider the sequence
            int[] sequence = new int[] { 0, 1, 2 };

            // And now we will evaluate its likelihood
            double logLikelihood = hmm.Evaluate(sequence);

            // At this point, the log-likelihood of the sequence
            // occurring within the model is -3.3928721329161653.

            // We can also get the Viterbi path of the sequence
            int[] path = hmm.Decode(sequence, out logLikelihood);

            // At this point, the state path will be 1-0-0 and the
            // log-likelihood will be -4.3095199438871337
        }
Exemple #15
0
        public static void Viterbi()
        {
            // Create the transition matrix A
            double[,] transition =
            {
                { 1.0 / 3, 1.0 / 3, 1.0 / 3 },
                { 1.0 / 3, 1.0 / 3, 1.0 / 3 },
                { 1.0 / 3, 1.0 / 3, 1.0 / 3 }
            };

            // Create the emission matrix B
            double[,] emission =
            {
                { 1.0 / 4, 1.0 / 4, 1.0 / 4, 1.0 / 4,       0,       0,       0,       0 },
                { 1.0 / 6, 1.0 / 6, 1.0 / 6, 1.0 / 6, 1.0 / 6, 1.0 / 6,       0,       0 },
                { 1.0 / 8, 1.0 / 8, 1.0 / 8, 1.0 / 8, 1.0 / 8, 1.0 / 8, 1.0 / 8, 1.0 / 8 },
            };

            // Create the initial probabilities pi
            double[] initial =
            {
                0.3, 0.3, 0.4
            };

            //var pS = new double[] { 1.0 / 3, 1.0 / 3, 1.0 / 3 };
            //var p4N = new double[] { 1.0 / 4, 1.0 / 4, 1.0 / 4, 1.0 / 4 };
            //var p6N = new double[] { 1.0 / 6, 1.0 / 6, 1.0 / 6, 1.0 / 6, 1.0 / 6, 1.0 / 6 };
            //var p8N = new double[] { 1.0 / 8, 1.0 / 8, 1.0 / 8, 1.0 / 8, 1.0 / 8, 1.0 / 8, 1.0 / 8, 1.0 / 8 };
            //var pN = new double[][] { p4N, p6N, p8N };

            HiddenMarkovModel hmm = new HiddenMarkovModel(transition, emission, initial);

            int[]  sequence      = new int[] { 1, 6, 3 };
            double logLikelihood = hmm.Evaluate(sequence);


            int[] path = hmm.Decode(sequence, out logLikelihood);
        }
        public void LearnTest2()
        {
            // Declare some testing data
            int[][] inputs = new int[][]
            {
                new int[] { 0,0,1,2 },     // Class 0
                new int[] { 0,1,1,2 },     // Class 0
                new int[] { 0,0,0,1,2 },   // Class 0
                new int[] { 0,1,2,2,2 },   // Class 0

                new int[] { 2,2,1,0 },     // Class 1
                new int[] { 2,2,2,1,0 },   // Class 1
                new int[] { 2,2,2,1,0 },   // Class 1
                new int[] { 2,2,2,2,1 },   // Class 1
            };

            int[] outputs = new int[]
            {
                0,0,0,0, // First four sequences are of class 0
                1,1,1,1, // Last four sequences are of class 1
            };


            // We are trying to predict two different classes
            int classes = 2;

            // Each sequence may have up to 3 symbols (0,1,2)
            int symbols = 3;

            // Nested models will have 3 states each
            int[] states = new int[] { 3, 3 };

            // Creates a new Hidden Markov Model Classifier with the given parameters
            HiddenMarkovClassifier classifier = new HiddenMarkovClassifier(classes, states, symbols);


            // Create a new learning algorithm to train the sequence classifier
            var teacher = new HiddenMarkovClassifierLearning(classifier,

                // Train each model until the log-likelihood changes less than 0.001
                modelIndex => new BaumWelchLearning(classifier.Models[modelIndex])
                {
                    Tolerance = 0.001,
                    Iterations = 0
                }
            );

            // Enable support for sequence rejection
            teacher.Rejection = true;

            // Train the sequence classifier using the algorithm
            double likelihood = teacher.Run(inputs, outputs);

            HiddenMarkovModel threshold = classifier.Threshold;

            Assert.AreEqual(6, threshold.States);

            Assert.AreEqual(classifier.Models[0].Transitions[0, 0], threshold.Transitions[0, 0], 1e-10);
            Assert.AreEqual(classifier.Models[0].Transitions[1, 1], threshold.Transitions[1, 1], 1e-10);
            Assert.AreEqual(classifier.Models[0].Transitions[2, 2], threshold.Transitions[2, 2], 1e-10);

            Assert.AreEqual(classifier.Models[1].Transitions[0, 0], threshold.Transitions[3, 3], 1e-10);
            Assert.AreEqual(classifier.Models[1].Transitions[1, 1], threshold.Transitions[4, 4], 1e-10);
            Assert.AreEqual(classifier.Models[1].Transitions[2, 2], threshold.Transitions[5, 5], 1e-10);

            for (int i = 0; i < 3; i++)
                for (int j = 3; j < 6; j++)
                    Assert.AreEqual(Double.NegativeInfinity, threshold.Transitions[i, j]);

            for (int i = 3; i < 6; i++)
                for (int j = 0; j < 3; j++)
                    Assert.AreEqual(Double.NegativeInfinity, threshold.Transitions[i, j]);

            Assert.IsFalse(Matrix.HasNaN(threshold.Transitions));

            classifier.Sensitivity = 0.5;

            // Will assert the models have learned the sequences correctly.
            for (int i = 0; i < inputs.Length; i++)
            {
                int expected = outputs[i];
                int actual = classifier.Compute(inputs[i], out likelihood);
                Assert.AreEqual(expected, actual);
            }


            int[] r0 = new int[] { 1, 1, 0, 0, 2 };


            double logRejection;
            int c = classifier.Compute(r0, out logRejection);

            Assert.AreEqual(-1, c);
            Assert.AreEqual(0.99906957195279988, logRejection);
            Assert.IsFalse(double.IsNaN(logRejection));

            logRejection = threshold.Evaluate(r0);
            Assert.AreEqual(-4.5653702970734793, logRejection, 1e-10);
            Assert.IsFalse(double.IsNaN(logRejection));

            threshold.Decode(r0, out logRejection);
            Assert.AreEqual(-8.21169955167614, logRejection, 1e-10);
            Assert.IsFalse(double.IsNaN(logRejection));

            foreach (var model in classifier.Models)
            {
                double[,] A = model.Transitions;

                for (int i = 0; i < A.GetLength(0); i++)
                {
                    double[] row = A.Exp().GetRow(i);
                    double sum = row.Sum();
                    Assert.AreEqual(1, sum, 1e-10);
                }
            }
            {
                double[,] A = classifier.Threshold.Transitions;

                for (int i = 0; i < A.GetLength(0); i++)
                {
                    double[] row = A.GetRow(i);
                    double sum = row.Exp().Sum();
                    Assert.AreEqual(1, sum, 1e-6);
                }
            }
        }
        public void LearnTest6()
        {
            Accord.Math.Tools.SetupGenerator(0);

            // We will try to create a Hidden Markov Model which
            //  can detect if a given sequence starts with a zero
            //  and has any number of ones after that.
            //
            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(new Forward(3), 2);

            // Try to fit the model to the data until the difference in
            //  the average log-likelihood changes only by as little as 0.0001
            //
            var teacher = new ViterbiLearning(hmm)
            {
                Tolerance = 0.0001, Iterations = 0
            };

            double ll = teacher.Run(sequences);


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


            // Sequences which do not start with zero have much lesser probability.
            double l3 = hmm.Evaluate(new int[] { 1, 1 });       // 0.186
            double l4 = hmm.Evaluate(new int[] { 1, 0, 0, 0 }); // 0.003

            // Sequences which contains few errors have higher probability
            //  than the ones which do not start with zero. This shows some
            //  of the temporal elasticity and error tolerance of the HMMs.
            //
            double l5 = hmm.Evaluate(new int[] { 0, 1, 0, 1, 1, 1, 1, 1, 1 }); // 0.033
            double l6 = hmm.Evaluate(new int[] { 0, 1, 1, 1, 1, 1, 1, 0, 1 }); // 0.026


            double pl = System.Math.Exp(ll);
            double p1 = System.Math.Exp(l1);
            double p2 = System.Math.Exp(l2);
            double p3 = System.Math.Exp(l3);
            double p4 = System.Math.Exp(l4);
            double p5 = System.Math.Exp(l5);
            double p6 = System.Math.Exp(l6);

            Assert.AreEqual(1.754393540912413, pl, 1e-6);
            Assert.AreEqual(0.61368718756104801, p1, 1e-6);
            Assert.AreEqual(0.50049466955818356, p2, 1e-6);
            Assert.AreEqual(0.18643340385264684, p3, 1e-6);
            Assert.AreEqual(0.00300262431355424, p4, 1e-6);
            Assert.AreEqual(0.03338686211012481, p5, 1e-6);
            Assert.AreEqual(0.02659161933179825, p6, 1e-6);

            Assert.IsTrue(l1 > l3 && l1 > l4);
            Assert.IsTrue(l2 > l3 && l2 > l4);
        }
        /// <summary>
        ///   Runs the Maximum Likelihood learning algorithm for hidden Markov models.
        /// </summary>
        ///
        /// <param name="observations">An array of observation sequences to be used to train the model.</param>
        /// <param name="paths">An array of state labels associated to each observation sequence.</param>
        ///
        /// <returns>
        ///   The average log-likelihood for the observations after the model has been trained.
        /// </returns>
        ///
        /// <remarks>
        ///   Supervised learning problem. Given some training observation sequences O = {o1, o2, ..., oK},
        ///   known training state paths H = {h1, h2, ..., hK} and general structure of HMM (numbers of
        ///   hidden and visible states), determine HMM parameters M = (A, B, pi) that best fit training data.
        /// </remarks>
        ///
        public double Run(Array[] observations, int[][] paths)
        {
            // Convert the generic representation to a vector of multivariate sequences
            double[][][] obs = observations as double[][][];

            if (obs == null)
            {
                obs = new double[observations.Length][][];
                for (int i = 0; i < observations.Length; i++)
                {
                    obs[i] = convert(observations[i], model.Dimension);
                }
            }

            // Grab model information
            int N      = observations.Length;
            int states = model.States;

            int[] initial = new int[states];
            int[,] transitions = new int[states, states];

            // 1. Count first state occurrences
            for (int i = 0; i < paths.Length; i++)
            {
                initial[paths[i][0]]++;
            }

            // 2. Count all state transitions
            foreach (int[] path in paths)
            {
                for (int j = 1; j < path.Length; j++)
                {
                    transitions[path[j - 1], path[j]]++;
                }
            }

            if (useWeights)
            {
                int totalObservations = 0;
                for (int i = 0; i < obs.Length; i++)
                {
                    totalObservations += obs[i].Length;
                }

                double[][] weights = new double[states][];
                for (int i = 0; i < weights.Length; i++)
                {
                    weights[i] = new double[totalObservations];
                }

                double[][] all = new double[totalObservations][];

                for (int i = 0, c = 0; i < paths.Length; i++)
                {
                    for (int t = 0; t < paths[i].Length; t++, c++)
                    {
                        int state = paths[i][t];
                        all[c]            = obs[i][t];
                        weights[state][c] = 1;
                    }
                }

                for (int i = 0; i < model.States; i++)
                {
                    model.Emissions[i].Fit(all, weights[i], fittingOptions);
                }
            }
            else
            {
                // 3. Count emissions for each state
                List <double[]>[] clusters = new List <double[]> [model.States];
                for (int i = 0; i < clusters.Length; i++)
                {
                    clusters[i] = new List <double[]>();
                }

                // Count symbol frequencies per state
                for (int i = 0; i < paths.Length; i++)
                {
                    for (int t = 0; t < paths[i].Length; t++)
                    {
                        int      state  = paths[i][t];
                        double[] symbol = obs[i][t];

                        clusters[state].Add(symbol);
                    }
                }

                // Estimate probability distributions
                for (int i = 0; i < model.States; i++)
                {
                    if (clusters[i].Count > 0)
                    {
                        model.Emissions[i].Fit(clusters[i].ToArray(), null, fittingOptions);
                    }
                }
            }

            // 4. Form log-probabilities, using the Laplace
            //    correction to avoid zero probabilities

            if (useLaplaceRule)
            {
                // Use Laplace's rule of succession correction
                // http://en.wikipedia.org/wiki/Rule_of_succession

                for (int i = 0; i < initial.Length; i++)
                {
                    initial[i]++;

                    for (int j = 0; j < states; j++)
                    {
                        transitions[i, j]++;
                    }
                }
            }

            // Form probabilities
            int initialCount = initial.Sum();

            int[] transitionCount = transitions.Sum(1);

            for (int i = 0; i < initial.Length; i++)
            {
                model.Probabilities[i] = Math.Log(initial[i] / (double)initialCount);
            }

            for (int i = 0; i < transitionCount.Length; i++)
            {
                for (int j = 0; j < states; j++)
                {
                    model.Transitions[i, j] = Math.Log(transitions[i, j] / (double)transitionCount[i]);
                }
            }

            System.Diagnostics.Debug.Assert(!model.Probabilities.HasNaN());
            System.Diagnostics.Debug.Assert(!model.Transitions.HasNaN());


            // 5. Compute log-likelihood
            double logLikelihood = Double.NegativeInfinity;

            for (int i = 0; i < observations.Length; i++)
            {
                logLikelihood = Special.LogSum(logLikelihood, model.Evaluate(observations[i]));
            }

            return(logLikelihood);
        }
        /// <summary>
        ///   Runs the Maximum Likelihood learning algorithm for hidden Markov models.
        /// </summary>
        ///
        /// <param name="observations">An array of observation sequences to be used to train the model.</param>
        /// <param name="paths">An array of state labels associated to each observation sequence.</param>
        ///
        /// <returns>
        ///   The average log-likelihood for the observations after the model has been trained.
        /// </returns>
        ///
        /// <remarks>
        ///   Supervised learning problem. Given some training observation sequences O = {o1, o2, ..., oK},
        ///   known training state paths H = {h1, h2, ..., hK} and general structure of HMM (numbers of
        ///   hidden and visible states), determine HMM parameters M = (A, B, pi) that best fit training data.
        /// </remarks>
        ///
        public double Run(int[][] observations, int[][] paths)
        {
            // Grab model information
            int N       = observations.Length;
            int states  = model.States;
            int symbols = model.Symbols;

            Array.Clear(initial, 0, initial.Length);
            Array.Clear(transitions, 0, transitions.Length);
            Array.Clear(emissions, 0, emissions.Length);

            // 1. Count first state occurrences
            for (int i = 0; i < paths.Length; i++)
            {
                initial[paths[i][0]]++;
            }

            // 2. Count all state transitions
            foreach (int[] path in paths)
            {
                for (int j = 1; j < path.Length; j++)
                {
                    transitions[path[j - 1], path[j]]++;
                }
            }

            // 3. Count emissions for each state
            for (int i = 0; i < observations.Length; i++)
            {
                for (int j = 0; j < observations[i].Length; j++)
                {
                    emissions[paths[i][j], observations[i][j]]++;
                }
            }

            // 4. Form log-probabilities, using the Laplace
            //    correction to avoid zero probabilities

            if (useLaplaceRule)
            {
                // Use Laplace's rule of succession correction
                // http://en.wikipedia.org/wiki/Rule_of_succession

                for (int i = 0; i < initial.Length; i++)
                {
                    initial[i]++;

                    for (int j = 0; j < states; j++)
                    {
                        transitions[i, j]++;
                    }

                    for (int k = 0; k < symbols; k++)
                    {
                        emissions[i, k]++;
                    }
                }
            }

            // Form probabilities
            int initialCount = initial.Sum();

            int[] transitionCount = transitions.Sum(1);
            int[] emissionCount   = emissions.Sum(1);

            if (initialCount == 0)
            {
                initialCount = 1;
            }

            for (int i = 0; i < transitionCount.Length; i++)
            {
                if (transitionCount[i] == 0)
                {
                    transitionCount[i] = 1;
                }
            }

            for (int i = 0; i < emissionCount.Length; i++)
            {
                if (emissionCount[i] == 0)
                {
                    emissionCount[i] = 1;
                }
            }

            for (int i = 0; i < initial.Length; i++)
            {
                model.Probabilities[i] = Math.Log(initial[i] / (double)initialCount);
            }

            for (int i = 0; i < transitionCount.Length; i++)
            {
                for (int j = 0; j < states; j++)
                {
                    model.Transitions[i, j] = Math.Log(transitions[i, j] / (double)transitionCount[i]);
                }
            }

            for (int i = 0; i < emissionCount.Length; i++)
            {
                for (int j = 0; j < symbols; j++)
                {
                    model.Emissions[i, j] = Math.Log(emissions[i, j] / (double)emissionCount[i]);
                }
            }

            System.Diagnostics.Debug.Assert(!model.Probabilities.HasNaN());
            System.Diagnostics.Debug.Assert(!model.Transitions.HasNaN());
            System.Diagnostics.Debug.Assert(!model.Emissions.HasNaN());


            // 5. Compute log-likelihood
            double logLikelihood = Double.NegativeInfinity;

            for (int i = 0; i < observations.Length; i++)
            {
                logLikelihood = Special.LogSum(logLikelihood, model.Evaluate(observations[i]));
            }

            return(logLikelihood);
        }
Exemple #20
0
        static void Main(string[] args)
        {
            //// Create a model with given probabilities
            //HiddenMarkovModel hmm = new HiddenMarkovModel(
            //transitions: new[,] // matrix A
            //{
            //    { 0.25, 0.25, 0.00 },
            //    { 0.33, 0.33, 0.33 },
            //    { 0.90, 0.10, 0.00 },
            //},
            //emissions: new[,] // matrix B
            //{
            //    { 0.1, 0.1, 0.8 },
            //    { 0.6, 0.2, 0.2 },
            //    { 0.9, 0.1, 0.0 },
            //},
            //initial: new[]  // vector pi
            //{
            //    0.25, 0.25, 0.0
            //});

            //// Create an observation sequence of up to 2 symbols (0 or 1)
            //int[] observationSequence = new[] { 0, 1, 1, 0};

            //// Decode the sequence: the path will be 1-1-1-1-2-0-1-1
            //int[] stateSequence = hmm.Decode(observationSequence);
            //foreach (int a in stateSequence)
            //{
            //    System.Console.Write(a + " ");
            //}
            //////////////////////////////////////////////////////////////////////////////
            // Create the transation matrix A
            double[,] transition =
            {
                { 0.3, 0.2, 0.2 },
                { 0.4, 0.3, 0.1 },
                { 0.4, 0.3, 0.1 }
            };

            // emission probability by kmean algo.
            double[,] emission =
            {
                {  0.55, 0.075, 0.275, 0, 0.1 },   //Dance 1
                {  0.52,  0.22,  0.16, 0, 0.1 },   //Dance 2
                { 0.357, 0.357, 0.186, 0, 0.1 }    //Dance 3
            };

            // Create the initial probabilities pi
            double[] initial =
            {
                0.4, 0.2, 0.4
            };

            // Create a new hidden Markov model
            HiddenMarkovModel hmm = new HiddenMarkovModel(transition, emission, initial);

            // After that, one could, for example, query the probability
            // of a sequence ocurring. We will consider the sequence
            int[] sequence = new int[] { 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 };

            // And now we will evaluate its likelihood
            double logLikelihood = hmm.Evaluate(sequence);

            // At this point, the log-likelihood of the sequence
            // ocurring within the model is -3.3928721329161653.

            // We can also get the Viterbi path of the sequence
            int[] path = hmm.Decode(sequence, out logLikelihood);

            // At this point, the state path will be 1-0-0 and the
            // log-likelihood will be -4.3095199438871337


            foreach (int a in path)
            {
                System.Console.Write(a + " ");
            }
            System.Console.ReadKey();
        }
        public void LearnTest7()
        {
            // 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>(new Forward(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 ViterbiLearning <NormalDistribution>(model)
            {
                Tolerance  = 0.0001,
                Iterations = 0,
            };

            // Fit the model
            double logLikelihood = teacher.Run(sequences);

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

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

            double likelihood = Math.Exp(logLikelihood);

            a1 = Math.Exp(a1);
            a2 = Math.Exp(a2);
            a3 = Math.Exp(a3);

            Assert.AreEqual(1.5418305348314281, likelihood, 1e-10);
            Assert.AreEqual(0.4048936808991913, a1, 1e-10);
            Assert.AreEqual(0.4656014344844673, a2, 1e-10);
            Assert.AreEqual(1.4232710878429383E-48, a3, 1e-10);

            Assert.IsFalse(double.IsNaN(logLikelihood));
            Assert.IsFalse(double.IsNaN(a1));
            Assert.IsFalse(double.IsNaN(a2));
            Assert.IsFalse(double.IsNaN(a3));


            Assert.AreEqual(2, model.Emissions.Length);
            var state1 = (model.Emissions[0] as NormalDistribution);
            var state2 = (model.Emissions[1] as NormalDistribution);

            Assert.AreEqual(0.16666666666666, state1.Mean, 1e-10);
            Assert.AreEqual(6.11111111111111, state2.Mean, 1e-10);
            Assert.IsFalse(Double.IsNaN(state1.Mean));
            Assert.IsFalse(Double.IsNaN(state2.Mean));

            Assert.AreEqual(0.007499999999999, state1.Variance, 1e-10);
            Assert.AreEqual(0.538611111111111, state2.Variance, 1e-10);
            Assert.IsFalse(Double.IsNaN(state1.Variance));
            Assert.IsFalse(Double.IsNaN(state2.Variance));

            Assert.AreEqual(2, model.Transitions.GetLength(0));
            Assert.AreEqual(2, model.Transitions.GetLength(1));

            var A = Matrix.Exp(model.Transitions);

            Assert.AreEqual(0.090, A[0, 0], 1e-3);
            Assert.AreEqual(0.909, A[0, 1], 1e-3);
            Assert.AreEqual(0.875, A[1, 0], 1e-3);
            Assert.AreEqual(0.125, A[1, 1], 1e-3);

            Assert.IsFalse(A.HasNaN());
        }
Exemple #22
0
        public void PredictTest()
        {
            int[][] sequences = new int[][]
            {
                new int[] { 0, 3, 1, 2 },
            };


            HiddenMarkovModel hmm = new HiddenMarkovModel(new Forward(4), 4);

            var teacher = new BaumWelchLearning(hmm)
            {
                Tolerance = 1e-10, Iterations = 0
            };
            double ll = teacher.Run(sequences);

            double l11, l12, l13, l14;

            int p1 = hmm.Predict(new int[] { 0 }, 1, out l11)[0];
            int p2 = hmm.Predict(new int[] { 0, 3 }, 1, out l12)[0];
            int p3 = hmm.Predict(new int[] { 0, 3, 1 }, 1, out l13)[0];
            int p4 = hmm.Predict(new int[] { 0, 3, 1, 2 }, 1, out l14)[0];

            Assert.AreEqual(3, p1);
            Assert.AreEqual(1, p2);
            Assert.AreEqual(2, p3);
            Assert.AreEqual(2, p4);

            double l21 = hmm.Evaluate(new int[] { 0, 3 });
            double l22 = hmm.Evaluate(new int[] { 0, 3, 1 });
            double l23 = hmm.Evaluate(new int[] { 0, 3, 1, 2 });
            double l24 = hmm.Evaluate(new int[] { 0, 3, 1, 2, 2 });

            Assert.AreEqual(l11, l21, 1e-10);
            Assert.AreEqual(l12, l22, 1e-10);
            Assert.AreEqual(l13, l23, 1e-10);
            Assert.AreEqual(l14, l24, 1e-10);

            Assert.IsFalse(double.IsNaN(l11));
            Assert.IsFalse(double.IsNaN(l12));
            Assert.IsFalse(double.IsNaN(l13));
            Assert.IsFalse(double.IsNaN(l14));

            Assert.IsFalse(double.IsNaN(l21));
            Assert.IsFalse(double.IsNaN(l22));
            Assert.IsFalse(double.IsNaN(l23));
            Assert.IsFalse(double.IsNaN(l24));

            double ln1;

            int[] pn = hmm.Predict(new int[] { 0 }, 4, out ln1);

            Assert.AreEqual(4, pn.Length);
            Assert.AreEqual(3, pn[0]);
            Assert.AreEqual(1, pn[1]);
            Assert.AreEqual(2, pn[2]);
            Assert.AreEqual(2, pn[3]);

            double ln2 = hmm.Evaluate(new int[] { 0, 3, 1, 2, 2 });

            Assert.AreEqual(ln1, ln2, 1e-10);
        }
    /*
     * this method passes all the possible directions
     * that can create a horizontal line to the HMM library
     * as observations. A and B are the state and
     * observation probabilities for the model
     * pi is the intial state of the model
     * the function returns true if the input matches any
     * of the observations used to train the model
    */
    bool horizontalEvalution(int [] input)
    {
        if(input.Length != 1){
            return false;
        }

        int[][] sequences = new int[][]
        {
            new int[]{ EAST },
            new int[] { WEST }
        };

        double [,] A = new double[8,8]
        {
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0}
        };

        double [,] B = new double[8,8]
        {
            {1, 0, 0, 0, 0, 0, 0, 0},
            {0, 1, 0, 0, 0, 0, 0, 0},
            {0, 0, 1, 0, 0, 0, 0, 0},
            {0, 0, 0, 1, 0, 0, 0, 0},
            {0, 0, 0, 0, 1, 0, 0, 0},
            {0, 0, 0, 0, 0, 1, 0, 0},
            {0, 0, 0, 0, 0, 0, 1, 0},
            {0, 0, 0, 0, 0, 0, 0, 1}
        };

        double [] pi = new double [] {0, 0, 0.5, 0.5, 0, 0, 0, 0};

        HiddenMarkovModel model = new HiddenMarkovModel(A, B, pi);
        model.Learn(sequences, 0.0001);

        if(model.Evaluate(input) >= 0.5){
            return true;
        }else{
            return false;
        }
    }
        static void runDiscreteDensityHiddenMarkovModelLearningExample()
        {
            int[][] observationSequences =
            {
                new[] { 0, 1, 2, 3 },
                new[] { 0, 0, 0,1, 1, 2, 2, 3, 3 },
                new[] { 0, 0, 1,2, 2, 2, 3, 3 },
                new[] { 0, 1, 2,3, 3, 3, 3 },
            };

            {
                // Create a hidden Markov model with arbitrary probabilities.
                HiddenMarkovModel hmm = new HiddenMarkovModel(states: 4, symbols: 4);

                // Create a Baum-Welch learning algorithm to teach it.
                BaumWelchLearning trainer = new BaumWelchLearning(hmm);

                // Call its Run method to start learning.
                double averageLogLikelihood = trainer.Run(observationSequences);
                Console.WriteLine("average log-likelihood for the observations = {0}", averageLogLikelihood);

                // Check the probability of some sequences.
                double logLik1 = hmm.Evaluate(new[] { 0, 1, 2, 3 });       // 0.013294354967987107.
                Console.WriteLine("probability = {0}", Math.Exp(logLik1));
                double logLik2 = hmm.Evaluate(new[] { 0, 0, 1, 2, 2, 3 }); // 0.002261813011419950.
                Console.WriteLine("probability = {0}", Math.Exp(logLik2));
                double logLik3 = hmm.Evaluate(new[] { 0, 0, 1, 2, 3, 3 }); // 0.002908045300397080.
                Console.WriteLine("probability = {0}", Math.Exp(logLik3));

                // Violate the form of the training set.
                double logLik4 = hmm.Evaluate(new[] { 3, 2, 1, 0 });       // 0.000000000000000000.
                Console.WriteLine("probability = {0}", Math.Exp(logLik4));
                double logLik5 = hmm.Evaluate(new[] { 0, 0, 1, 3, 1, 1 }); // 0.000000000113151816.
                Console.WriteLine("probability = {0}", Math.Exp(logLik5));
            }

            {
                // Create a hidden Markov model with arbitrary probabilities.
                var hmm = new HiddenMarkovModel <GeneralDiscreteDistribution>(states: 4, emissions: new GeneralDiscreteDistribution(symbols: 4));

                // Create a Baum-Welch learning algorithm to teach it
                // until the difference in the average log-likelihood changes only by as little as 0.0001
                // and the number of iterations is less than 1000.
                var trainer = new BaumWelchLearning <GeneralDiscreteDistribution>(hmm)
                {
                    Tolerance  = 0.0001,
                    Iterations = 1000,
                };

                // Call its Run method to start learning.
                double averageLogLikelihood = trainer.Run(observationSequences);
                Console.WriteLine("average log-likelihood for the observations = {0}", averageLogLikelihood);

                // Check the probability of some sequences.
                double logLik1 = hmm.Evaluate(new[] { 0, 1, 2, 3 });       // 0.013294354967987107.
                Console.WriteLine("probability = {0}", Math.Exp(logLik1));
                double logLik2 = hmm.Evaluate(new[] { 0, 0, 1, 2, 2, 3 }); // 0.002261813011419950.
                Console.WriteLine("probability = {0}", Math.Exp(logLik2));
                double logLik3 = hmm.Evaluate(new[] { 0, 0, 1, 2, 3, 3 }); // 0.002908045300397080.
                Console.WriteLine("probability = {0}", Math.Exp(logLik3));

                // Violate the form of the training set.
                double logLik4 = hmm.Evaluate(new[] { 3, 2, 1, 0 });       // 0.000000000000000000.
                Console.WriteLine("probability = {0}", Math.Exp(logLik4));
                double logLik5 = hmm.Evaluate(new[] { 0, 0, 1, 3, 1, 1 }); // 0.000000000113151816.
                Console.WriteLine("probability = {0}", Math.Exp(logLik5));
            }
        }
Exemple #25
0
 /// <summary>
 ///   Gets the probability mass function (pmf) for
 ///   this distribution evaluated at point <c>x</c>.
 /// </summary>
 ///
 /// <param name="x">A single point in the distribution range.</param>
 ///
 /// <returns>
 ///   The probability of <c>x</c> occurring
 ///   in the current distribution.
 /// </returns>
 ///
 /// <remarks>
 ///   The Probability Mass Function (PMF) describes the
 ///   probability that a given value <c>x</c> will occur.
 /// </remarks>
 ///
 public override double ProbabilityMassFunction(int[] x)
 {
     return(Math.Exp(model.Evaluate(x)));
 }
Exemple #26
0
        private static double testThresholdModel(int[][] inputs, int[] outputs, HiddenMarkovClassifier classifier, double likelihood)
        {
            HiddenMarkovModel threshold = classifier.Threshold;

            Assert.AreEqual(6, threshold.States);

            Assert.AreEqual(classifier.Models[0].Transitions[0, 0], threshold.Transitions[0, 0], 1e-10);
            Assert.AreEqual(classifier.Models[0].Transitions[1, 1], threshold.Transitions[1, 1], 1e-10);
            Assert.AreEqual(classifier.Models[0].Transitions[2, 2], threshold.Transitions[2, 2], 1e-10);

            Assert.AreEqual(classifier.Models[1].Transitions[0, 0], threshold.Transitions[3, 3], 1e-10);
            Assert.AreEqual(classifier.Models[1].Transitions[1, 1], threshold.Transitions[4, 4], 1e-10);
            Assert.AreEqual(classifier.Models[1].Transitions[2, 2], threshold.Transitions[5, 5], 1e-10);

            for (int i = 0; i < 3; i++)
            {
                for (int j = 3; j < 6; j++)
                {
                    Assert.AreEqual(Double.NegativeInfinity, threshold.Transitions[i, j]);
                }
            }

            for (int i = 3; i < 6; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    Assert.AreEqual(Double.NegativeInfinity, threshold.Transitions[i, j]);
                }
            }

            Assert.IsFalse(Matrix.HasNaN(threshold.LogTransitions));

            classifier.Sensitivity = 0.5;

            // Will assert the models have learned the sequences correctly.
            for (int i = 0; i < inputs.Length; i++)
            {
                int expected = outputs[i];
                int actual   = classifier.Compute(inputs[i], out likelihood);
                Assert.AreEqual(expected, actual);
            }


            int[] r0 = new int[] { 1, 1, 0, 0, 2 };


            double logRejection;
            int    c = classifier.Compute(r0, out logRejection);

            Assert.AreEqual(-1, c);
            Assert.AreEqual(0.99996241769427985, logRejection, 1e-10);

            logRejection = threshold.Evaluate(r0);
            Assert.AreEqual(-5.5993214137039073, logRejection, 1e-10);

            threshold.Decode(r0, out logRejection);
            Assert.AreEqual(-9.31035541707617, logRejection, 1e-10);

            foreach (var model in classifier.Models)
            {
                double[,] A = model.Transitions;

                for (int i = 0; i < A.GetLength(0); i++)
                {
                    double[] row = A.Exp().GetRow(i);
                    double   sum = row.Sum();
                    Assert.AreEqual(1, sum, 1e-10);
                }
            }
            {
                double[,] A = classifier.Threshold.Transitions;

                for (int i = 0; i < A.GetLength(0); i++)
                {
                    double[] row = A.GetRow(i);
                    double   sum = row.Exp().Sum();
                    Assert.AreEqual(1, sum, 1e-6);
                }
            }
            return(likelihood);
        }
        public void LearnTest8()
        {
            // Create continuous sequences. In the sequence below, there
            // seems to be two states, one for values equal to 1 and another
            // for values equal to 2.
            double[][] sequences = new double[][]
            {
                new double[] { 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 }
            };

            // 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>(new Forward(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 ViterbiLearning <NormalDistribution>(model)
            {
                Tolerance  = 0.0001,
                Iterations = 0,

                // However, we will need to specify a regularization constant as the
                //  variance of each state will likely be zero (all values are equal)
                FittingOptions = new NormalOptions()
                {
                    Regularization = double.Epsilon
                }
            };

            // Fit the model
            double likelihood = teacher.Run(sequences);


            // See the probability of the sequences learned
            double a1 = model.Evaluate(new double[] { 1, 2, 1, 2, 1, 2, 1, 2, 1 }); // exp(a1) = infinity
            double a2 = model.Evaluate(new double[] { 1, 2, 1, 2, 1 });             // exp(a2) = infinity

            // See the probability of an unrelated sequence
            double a3 = model.Evaluate(new double[] { 1, 2, 3, 2, 1, 2, 1 });          // exp(a3) = 0
            double a4 = model.Evaluate(new double[] { 1.1, 2.2, 1.3, 3.2, 4.2, 1.0 }); // exp(a4) = 0


            Assert.AreEqual(double.PositiveInfinity, System.Math.Exp(likelihood));
            Assert.AreEqual(3340.6878090199571, a1);
            Assert.AreEqual(1855.791720669667, a2);
            Assert.AreEqual(0.0, Math.Exp(a3));
            Assert.AreEqual(0.0, Math.Exp(a4));

            Assert.AreEqual(2, model.Emissions.Length);
            var state1 = (model.Emissions[0] as NormalDistribution);
            var state2 = (model.Emissions[1] as NormalDistribution);

            Assert.AreEqual(1.0, state1.Mean, 1e-10);
            Assert.AreEqual(2.0, state2.Mean, 1e-10);
            Assert.IsFalse(Double.IsNaN(state1.Mean));
            Assert.IsFalse(Double.IsNaN(state2.Mean));

            Assert.IsTrue(state1.Variance < 1e-30);
            Assert.IsTrue(state2.Variance < 1e-30);

            var A = Matrix.Exp(model.Transitions);

            Assert.AreEqual(2, A.GetLength(0));
            Assert.AreEqual(2, A.GetLength(1));
            Assert.AreEqual(0.0714285714285714, A[0, 0], 1e-6);
            Assert.AreEqual(0.9285714285714286, A[0, 1], 1e-6);
            Assert.AreEqual(0.9230769230769231, A[1, 0], 1e-6);
            Assert.AreEqual(0.0769230769230769, A[1, 1], 1e-6);
        }
        public void LearnTest2()
        {
            // Declare some testing data
            int[][] inputs = new int[][]
            {
                new int[] { 0, 0, 1, 2 },    // Class 0
                new int[] { 0, 1, 1, 2 },    // Class 0
                new int[] { 0, 0, 0, 1, 2 }, // Class 0
                new int[] { 0, 1, 2, 2, 2 }, // Class 0

                new int[] { 2, 2, 1, 0 },    // Class 1
                new int[] { 2, 2, 2, 1, 0 }, // Class 1
                new int[] { 2, 2, 2, 1, 0 }, // Class 1
                new int[] { 2, 2, 2, 2, 1 }, // Class 1
            };

            int[] outputs = new int[]
            {
                0, 0, 0, 0, // First four sequences are of class 0
                1, 1, 1, 1, // Last four sequences are of class 1
            };


            // We are trying to predict two different classes
            int classes = 2;

            // Each sequence may have up to 3 symbols (0,1,2)
            int symbols = 3;

            // Nested models will have 3 states each
            int[] states = new int[] { 3, 3 };

            // Creates a new Hidden Markov Model Classifier with the given parameters
            HiddenMarkovClassifier classifier = new HiddenMarkovClassifier(classes, states, symbols);


            // Create a new learning algorithm to train the sequence classifier
            var teacher = new HiddenMarkovClassifierLearning(classifier,

                                                             // Train each model until the log-likelihood changes less than 0.001
                                                             modelIndex => new BaumWelchLearning(classifier.Models[modelIndex])
            {
                Tolerance  = 0.001,
                Iterations = 0
            }
                                                             );

            // Enable support for sequence rejection
            teacher.Rejection = true;

            // Train the sequence classifier using the algorithm
            double likelihood = teacher.Run(inputs, outputs);


            // Will assert the models have learned the sequences correctly.
            for (int i = 0; i < inputs.Length; i++)
            {
                int expected = outputs[i];
                int actual   = classifier.Compute(inputs[i], out likelihood);
                Assert.AreEqual(expected, actual);
            }

            HiddenMarkovModel threshold = classifier.Threshold;

            Assert.AreEqual(6, threshold.States);

            Assert.AreEqual(classifier.Models[0].Transitions[0, 0], threshold.Transitions[0, 0], 1e-10);
            Assert.AreEqual(classifier.Models[0].Transitions[1, 1], threshold.Transitions[1, 1], 1e-10);
            Assert.AreEqual(classifier.Models[0].Transitions[2, 2], threshold.Transitions[2, 2], 1e-10);

            Assert.AreEqual(classifier.Models[1].Transitions[0, 0], threshold.Transitions[3, 3], 1e-10);
            Assert.AreEqual(classifier.Models[1].Transitions[1, 1], threshold.Transitions[4, 4], 1e-10);
            Assert.AreEqual(classifier.Models[1].Transitions[2, 2], threshold.Transitions[5, 5], 1e-10);

            Assert.IsFalse(Matrix.HasNaN(threshold.Transitions));

            int[] r0 = new int[] { 1, 1, 0, 0, 2 };


            double logRejection;
            int    c = classifier.Compute(r0, out logRejection);

            Assert.AreEqual(-1, c);
            Assert.AreEqual(0.99569011079012049, logRejection);
            Assert.IsFalse(double.IsNaN(logRejection));

            logRejection = threshold.Evaluate(r0);
            Assert.AreEqual(-6.7949285513628528, logRejection, 1e-10);
            Assert.IsFalse(double.IsNaN(logRejection));

            threshold.Decode(r0, out logRejection);
            Assert.AreEqual(-8.902077561009957, logRejection, 1e-10);
            Assert.IsFalse(double.IsNaN(logRejection));
        }
Exemple #29
0
        public void LearnTest6()
        {
            // We will try to create a Hidden Markov Model which
            //  can detect if a given sequence starts with a zero
            //  and has any number of ones after that.
            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(3, 2);

            // Try to fit the model to the data until the difference in
            //  the average log-likelihood changes only by as little as 0.0001
            var teacher = new BaumWelchLearning(hmm)
            {
                Tolerance = 0.0001, Iterations = 0
            };
            double ll = teacher.Run(sequences);

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

            // Sequences which do not start with zero have much lesser probability.
            double l3 = hmm.Evaluate(new int[] { 1, 1 });       // 0.000
            double l4 = hmm.Evaluate(new int[] { 1, 0, 0, 0 }); // 0.000

            // Sequences which contains few errors have higher probability
            //  than the ones which do not start with zero. This shows some
            //  of the temporal elasticity and error tolerance of the HMMs.
            double l5 = hmm.Evaluate(new int[] { 0, 1, 0, 1, 1, 1, 1, 1, 1 }); // 0.034
            double l6 = hmm.Evaluate(new int[] { 0, 1, 1, 1, 1, 1, 1, 0, 1 }); // 0.034

            double pl = System.Math.Exp(ll);
            double p1 = System.Math.Exp(l1);
            double p2 = System.Math.Exp(l2);
            double p3 = System.Math.Exp(l3);
            double p4 = System.Math.Exp(l4);
            double p5 = System.Math.Exp(l5);
            double p6 = System.Math.Exp(l6);

            Assert.AreEqual(0.95151126952069587, pl, 1e-6);
            Assert.AreEqual(0.99996863060890995, p1, 1e-6);
            Assert.AreEqual(0.91667240076011669, p2, 1e-6);
            Assert.AreEqual(0.00002335133758386, p3, 1e-6);
            Assert.AreEqual(0.00000000000000012, p4, 1e-6);
            Assert.AreEqual(0.034237231443226858, p5, 1e-6);
            Assert.AreEqual(0.034237195920532461, p6, 1e-6);

            Assert.IsTrue(l1 > l3 && l1 > l4);
            Assert.IsTrue(l2 > l3 && l2 > l4);
        }
    /*
     * this method passes all the possible directions
     * that can create a square to the HMM library
     * as observations. A and B are the state and
     * observation probabilities for the model
     * pi is the intial state of the model
     * the function returns true if the input matches any
     * of the observations used to train the model
    */
    bool squareEvalution(int [] input)
    {
        if(input.Length != 4){
            return false;
        }

        int[][] sequences = new int[][]
        {
            new int[]{ NORTH, EAST, SOUTH, WEST},
            new int[] { EAST, SOUTH, WEST, NORTH},
            new int[] { SOUTH, WEST, NORTH, EAST},
            new int[] { WEST, NORTH, EAST, SOUTH}
        };

        double [,] A = new double[8,8]
        {
            {0, 0, 1, 0, 0, 0, 0, 0},
            {0, 0, 0, 1, 0, 0, 0, 0},
            {0, 1, 0, 0, 0, 0, 0, 0},
            {1, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0}
        };

        double [,] B = new double[8,8]
        {
            {1, 0, 0, 0, 0, 0, 0, 0},
            {0, 1, 0, 0, 0, 0, 0, 0},
            {0, 0, 1, 0, 0, 0, 0, 0},
            {0, 0, 0, 1, 0, 0, 0, 0},
            {0, 0, 0, 0, 1, 0, 0, 0},
            {0, 0, 0, 0, 0, 1, 0, 0},
            {0, 0, 0, 0, 0, 0, 1, 0},
            {0, 0, 0, 0, 0, 0, 0, 1}
        };

        double [] pi = new double [] {0.25,0.25,0.25,0.25, 0, 0, 0, 0};

        HiddenMarkovModel model = new HiddenMarkovModel(A, B, pi);
        model.Learn(sequences, 0.0001);

        if(model.Evaluate(input) >= 0.25){
            return true;
        }else{
            return false;
        }
    }
Exemple #31
0
        public void PosteriorTest1()
        {
            // Example from http://ai.stanford.edu/~serafim/CS262_2007/notes/lecture5.pdf


            double[,] A =
            {
                { 0.95, 0.05 }, // fair dice state
                { 0.05, 0.95 }, // loaded dice state
            };

            double[,] B =
            {
                {  1 / 6.0,  1 / 6.0,  1 / 6.0,  1 / 6.0,  1 / 6.0, 1 / 6.0 }, // fair dice probabilities
                { 1 / 10.0, 1 / 10.0, 1 / 10.0, 1 / 10.0, 1 / 10.0, 1 / 2.0 }, // loaded probabilities
            };

            double[] pi = { 0.5, 0.5 };

            HiddenMarkovModel hmm = new HiddenMarkovModel(A, B, pi);

            int[]  x = new int[] { 1, 2, 1, 5, 6, 2, 1, 5, 2, 4 }.Subtract(1);
            int[]  y  = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            double py = Math.Exp(hmm.Evaluate(x, y));

            Assert.AreEqual(0.00000000521158647211, py, 1e-16);

            x  = new int[] { 1, 2, 1, 5, 6, 2, 1, 5, 2, 4 }.Subtract(1);
            y  = new int[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
            py = Math.Exp(hmm.Evaluate(x, y));

            Assert.AreEqual(0.00000000015756235243, py, 1e-16);


            Accord.Math.Tools.SetupGenerator(0);
            var u = new UniformDiscreteDistribution(0, 6);

            int[] sequence = u.Generate(1000);
            int   start    = 120;
            int   end      = 150;

            for (int i = start; i < end; i += 2)
            {
                sequence[i] = 5;
            }


            // Predict the next observation in sequence
            int[]      path;
            double[][] p = hmm.Posterior(sequence, out path);

            for (int i = 0; i < path.Length; i++)
            {
                Assert.AreEqual(1, p[i][0] + p[i][1], 1e-10);
            }


            int loaded = 0;

            for (int i = 0; i < start; i++)
            {
                if (p[i][1] > 0.95)
                {
                    loaded++;
                }
            }

            Assert.AreEqual(0, loaded);

            loaded = 0;
            for (int i = start; i < end; i++)
            {
                if (p[i][1] > 0.95)
                {
                    loaded++;
                }
            }

            Assert.IsTrue(loaded > 15);

            loaded = 0;
            for (int i = end; i < p.Length; i++)
            {
                if (p[i][1] > 0.95)
                {
                    loaded++;
                }
            }

            Assert.AreEqual(0, loaded);
        }
Exemple #32
0
        public double Run(int[][] observations_db, int[][] path_db)
        {
            int K = observations_db.Length;

            DiagnosticsHelper.Assert(path_db.Length == K);

            int N = mModel.StateCount;
            int M = mModel.SymbolCount;

            int[] initial = new int[N];
            int[,] transition_matrix = new int[N, N];
            int[,] emission_matrix   = new int[N, M];

            for (int k = 0; k < K; ++k)
            {
                initial[path_db[k][0]]++;
            }

            int T = 0;

            for (int k = 0; k < K; ++k)
            {
                int[] path         = path_db[k];
                int[] observations = observations_db[k];

                T = path.Length;
                for (int t = 0; t < T - 1; ++t)
                {
                    transition_matrix[path[t], path[t + 1]]++;
                }

                for (int t = 0; t < T; ++t)
                {
                    emission_matrix[path[t], observations[t]]++;
                }
            }

            if (mUseLaplaceRule)
            {
                for (int i = 0; i < N; ++i)
                {
                    initial[i]++;

                    for (int j = 0; j < N; ++j)
                    {
                        transition_matrix[i, j]++;
                    }

                    for (int j = 0; j < M; ++j)
                    {
                        emission_matrix[i, j]++;
                    }
                }
            }

            int initial_sum = initial.Sum();

            int[] transition_sum_vec = Sum(transition_matrix, 1);
            int[] emission_sum_vec   = Sum(emission_matrix, 1);

            for (int i = 0; i < N; ++i)
            {
                mModel.LogProbabilityVector[i] = System.Math.Log(initial[i] / (double)initial_sum);
            }

            for (int i = 0; i < N; ++i)
            {
                double transition_sum = (double)transition_sum_vec[i];
                for (int j = 0; j < N; ++j)
                {
                    mModel.LogTransitionMatrix[i, j] = System.Math.Log(transition_matrix[i, j] / transition_sum);
                }
            }

            for (int i = 0; i < N; ++i)
            {
                double emission_sum = (double)emission_sum_vec[i];
                for (int m = 0; m < M; ++m)
                {
                    mModel.LogEmissionMatrix[i, m] = System.Math.Log(emission_matrix[i, m] / emission_sum);
                }
            }

            double logLikelihood = double.NegativeInfinity;

            for (int i = 0; i < observations_db.Length; i++)
            {
                logLikelihood = LogHelper.LogSum(logLikelihood, mModel.Evaluate(observations_db[i]));
            }

            return(logLikelihood);
        }