Evaluate() публичный Метод

Calculates the probability that this model has generated the given sequence.
Evaluation problem. Given the HMM M = (A, B, pi) and the observation sequence O = {o1, o2, ..., oK}, calculate the probability that model M has generated sequence O. This can be computed efficiently using the either the Viterbi or the Forward algorithms.
public Evaluate ( int observations ) : double
observations int /// A sequence of observations. ///
Результат double
        public override void Learn(SequenceData trainingData, SequenceData validationData, SequenceData testData)
        {
            //hmm = SparseHiddenMarkovModel.FromCompleteGraph(2, trainingData.NumSymbols);
            hmm = new HiddenMarkovModel(trainingData.NumSymbols, 4);

            double likelihood = 0.0;
            double newLikelihood = Double.MinValue;

            do
            {
                //HMMGraph graph = hmm.ToGraph();
                HMMGraph graph = ModelConverter.HMM2Graph(hmm);

                //CutEdges(graph, epsilon);

                double[] viterbyScores = ComputeViterbyScores(validationData, true);

                int[] statesToSplit = IdentifyWeakStates(viterbyScores).ToArray();
                foreach (int weakPoint in statesToSplit)
                {
                    SplitState(graph, weakPoint);
                }

                WriteLine(String.Format("Added {0} states", statesToSplit.Length));
                //WriteLine(String.Format("Removed {0} states", RemoveUnpopularStates(graph, viterbyScores)));

                //hmm = SparseHiddenMarkovModel.FromGraph(graph);
                hmm = ModelConverter.Graph2HMM(graph);

                WriteLine("Running Baum Welch...");
                //hmm.Learn(trainingData.GetNonempty(), 0.0, 8);
                hmm.Learn(trainingData.GetNonempty(), 8);

                likelihood = newLikelihood;
                newLikelihood = 0.0;

                foreach (int[] signal in validationData.GetNonempty())
                {
                    newLikelihood += hmm.Evaluate(signal, true);
                }

                WriteLine(String.Empty);
                WriteLine(String.Format("Number of HMM States: {0}", NumberOfStates));
                //WriteLine(String.Format("Transition Sparsity; {0}", hmm.TransitionSparsity));
                WriteLine(String.Format("Log Likelihood: {0}", newLikelihood));
                WriteLine(String.Empty);
            }
            while (Math.Abs(newLikelihood - likelihood) > convergenceThreshold);
        }
        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("]");
        }
Пример #3
0
        public void LearnTest12()
        {

            // Suppose we have a set of six sequences and we would like to
            // fit a hidden Markov model with mixtures of Normal distributions
            // as the emission densities. 

            // First, let's consider a set of univariate sequences:
            double[][] sequences =
            {
                new double[] { -0.223, -1.05, -0.574, 0.965, -0.448, 0.265, 0.087, 0.362, 0.717, -0.032 },
                new double[] { -1.05, -0.574, 0.965, -0.448, 0.265, 0.087, 0.362, 0.717, -0.032, -0.346 },
                new double[] { -0.574, 0.965, -0.448, 0.265, 0.087, 0.362, 0.717, -0.032, -0.346, -0.989 },
                new double[] { 0.965, -0.448, 0.265, 0.087, 0.362, 0.717, -0.032, -0.346, -0.989, -0.619 },
                new double[] { -0.448, 0.265, 0.087, 0.362, 0.717, -0.032, -0.346, -0.989, -0.619, 0.02 },
                new double[] { 0.265, 0.087, 0.362, 0.717, -0.032, -0.346, -0.989, -0.619, 0.02, -0.297 },
            };


            // Now we can begin specifing a initial Gaussian mixture distribution. It is
            // better to add some different initial parameters to the mixture components:
            var density = new Mixture<NormalDistribution>(
                new NormalDistribution(mean: 2, stdDev: 1.0), // 1st component in the mixture
                new NormalDistribution(mean: 0, stdDev: 0.6), // 2nd component in the mixture
                new NormalDistribution(mean: 4, stdDev: 0.4), // 3rd component in the mixture
                new NormalDistribution(mean: 6, stdDev: 1.1)  // 4th component in the mixture
            );

            // Let's then create a continuous hidden Markov Model with two states organized in a forward
            //  topology with the underlying univariate Normal mixture distribution as probability density.
            var model = new HiddenMarkovModel<Mixture<NormalDistribution>>(new Forward(2), density);

            // Now we should configure the learning algorithms to train the sequence classifier. We will
            // learn until the difference in the average log-likelihood changes only by as little as 0.0001
            var teacher = new BaumWelchLearning<Mixture<NormalDistribution>>(model)
            {
                Tolerance = 0.0001,
                Iterations = 0,

                // Note, however, that since this example is extremely simple and we have only a few
                // data points, a full-blown mixture wouldn't really be needed. Thus we will have a
                // great chance that the mixture would become degenerated quickly. We can avoid this
                // by specifying some regularization constants in the Normal distribution fitting:

                FittingOptions = new MixtureOptions()
                {
                    Iterations = 1, // limit the inner e-m to a single iteration

                    InnerOptions = new NormalOptions()
                    {
                        Regularization = 1e-5 // specify a regularization constant
                    }
                }
            };

            // Finally, we can fit the model
            double logLikelihood = teacher.Run(sequences);

            // And now check the likelihood of some approximate sequences.
            double[] newSequence = { -0.223, -1.05, -0.574, 0.965, -0.448, 0.265, 0.087, 0.362, 0.717, -0.032 };
            double a1 = Math.Exp(model.Evaluate(newSequence)); // 11729312967893.566

            int[] path = model.Decode(newSequence);

            // We can see that the likelihood of an unrelated sequence is much smaller:
            double a3 = Math.Exp(model.Evaluate(new double[] { 8, 2, 6, 4, 1 })); // 0.0


            Assert.AreEqual(11729312967893.566, a1);
            Assert.AreEqual(0.0, a3);

            Assert.IsFalse(Double.IsNaN(a1));
            Assert.IsFalse(Double.IsNaN(a3));
        }
Пример #4
0
        private void foo()
        {
            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 },
            };

            NormalDistribution density = new NormalDistribution();

            var model = new HiddenMarkovModel<NormalDistribution>(new Ergodic(2), density);

            var teacher = new BaumWelchLearning<NormalDistribution>(model)
            {
                Tolerance = 0.0001,
                Iterations = 0,
            };

            double likelihood = teacher.Run(sequences);

            double l1 = model.Evaluate(new[] { 0.1, 5.2, 0.3, 6.7, 0.1, 6.0 }); // 0.87
            double l2 = model.Evaluate(new[] { 0.2, 6.2, 0.3, 6.3, 0.1, 5.0 }); // 1.00

            double l3 = model.Evaluate(new[] { 1.1, 2.2, 1.3, 3.2, 4.2, 1.0 }); // 0.00
        }
        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);
        }
Пример #6
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);
        }
Пример #7
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);
        }
Пример #8
0
        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 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.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) = inf
            double a2 = model.Evaluate(new double[] { 1, 2, 1, 2, 1 });             // exp(a2) = inf

            // 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(302.59496915947972, a1);
            Assert.AreEqual(168.26234890650207, 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, A[0, 0]);
            Assert.AreEqual(1, A[0, 1]);
            Assert.AreEqual(1, A[1, 0]);
            Assert.AreEqual(0, A[1, 1]);
        }
Пример #9
0
        public void DecodeIntegersTest()
        {
            double[,] transitions = 
            {  
                { 0.7, 0.3 },
                { 0.4, 0.6 }
            };

            GeneralDiscreteDistribution[] emissions = 
            {  
                new GeneralDiscreteDistribution(0.1, 0.4, 0.5),
                new GeneralDiscreteDistribution(0.6, 0.3, 0.1)
            };

            double[] initial =
            {
                0.6, 0.4
            };

            var hmm = new HiddenMarkovModel<GeneralDiscreteDistribution>(transitions, emissions, initial);

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

            double logLikelihood = hmm.Evaluate(sequence);
            int[] path = hmm.Decode(sequence, out logLikelihood);

            Assert.AreEqual(logLikelihood, Math.Log(0.01344), 1e-10);
            Assert.AreEqual(path[0], 1);
            Assert.AreEqual(path[1], 0);
            Assert.AreEqual(path[2], 0);
        }
Пример #10
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);
        }
Пример #11
0
        public void LearnTest7()
        {
            Accord.Math.Tools.SetupGenerator(0);

            // 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());
        }
        private void Run(string name, int numberOfStates, int numberOfRuns, double threshold, Dictionary<int, double[]> runScores, Dictionary<int, double[]> runTimes, Dictionary<int, double[]> runTicks, Tuple<SequenceData, SequenceData>[] data)
        {
            Stopwatch watch = new Stopwatch();

            runScores.Add(numberOfStates, new double[numberOfRuns]);
            runTimes.Add(numberOfStates, new double[numberOfRuns]);
            runTicks.Add(numberOfStates, new double[numberOfRuns]);

            for (int i = 0; i < numberOfRuns; i++)
            {
                Console.WriteLine("run {0}...", i);

                watch.Reset();

                //Learner learner = new BaumWelchLearner(numberOfStates, threshold);

                double[] initialProbabilities = new double[numberOfStates];

                double sum = 0.0;

                for (int k = 0; k < numberOfStates; k++)
                {
                    initialProbabilities[k] = random.NextDouble();
                    sum += initialProbabilities[k];
                }

                for (int k = 0; k < numberOfStates; k++)
                {
                    initialProbabilities[k] /= sum;
                }

                double[,] transitionMatrix = new double[numberOfStates, numberOfStates];

                for (int k = 0; k < numberOfStates; k++)
                {
                    sum = 0.0;

                    for (int l = 0; l < numberOfStates; l++)
                    {
                        transitionMatrix[k, l] = random.NextDouble();
                        sum += transitionMatrix[k, l];
                    }

                    for (int l = 0; l < numberOfStates; l++)
                    {
                        transitionMatrix[k, l] /= sum;
                    }
                }

                double[,] emissionMatrix = new double[numberOfStates, testData.NumSymbols];

                for (int k = 0; k < numberOfStates; k++)
                {
                    sum = 0.0;

                    for (int l = 0; l < testData.NumSymbols; l++)
                    {
                        emissionMatrix[k, l] = random.NextDouble();
                        sum += emissionMatrix[k, l];
                    }

                    for (int l = 0; l < testData.NumSymbols; l++)
                    {
                        emissionMatrix[k, l] /= sum;
                    }
                }

                HiddenMarkovModel model = new HiddenMarkovModel(transitionMatrix, emissionMatrix, initialProbabilities);

                //learner.Learn(data[i].Item1, data[i].Item2, testData);

                watch.Start();

                //model.Learn(data[i].Item1.GetNonempty(), threshold);

                watch.Stop();

                Console.WriteLine();

                //double score = PautomacEvaluator.Evaluate(learner, testData, solutionData);

                sum = 0.0;

                int[][] testSignals = testData.GetAll();
                double[] results = new double[testSignals.Length];

                for (int j = 0; j < testSignals.Length; j++)
                {
                    if (testSignals[j].Length == 0)
                    {
                        results[j] = 1;
                    }
                    else
                    {
                        results[j] = model.Evaluate(testSignals[j]);
                    }

                    sum += results[j];
                }

                for (int j = 0; j < testSignals.Length; j++)
                {
                    results[j] /= sum;
                }

                double score = PautomacEvaluator.Evaluate(results, solutionData);

                runScores[numberOfStates][i] = score;
                runTimes[numberOfStates][i] = (watch.ElapsedMilliseconds / 1000);
                runTicks[numberOfStates][i] = watch.ElapsedTicks;

                DirectoryInfo dir = new DirectoryInfo(String.Format("Models_{0}", name));

                if (!dir.Exists)
                {
                    dir.Create();
                }

                using (StreamWriter sw = new StreamWriter(String.Format(@"Models_{0}\n{1}_r{2}.txt", name, numberOfStates, i)))
                {
                    sw.WriteLine("Number of States: {0}", numberOfStates);
                    sw.WriteLine("Threshold: {0}", threshold);
                    sw.WriteLine("Run Number: {0}", i);
                    sw.WriteLine("PautomaC Score: {0:0.0000000000}", score);
                    sw.WriteLine();

                    sw.WriteLine("Initial Distribution:");
                    for (int k = 0; k < numberOfStates; k++ )
                    {
                        sw.Write("{0:0.0000}\t", model.Probabilities[k]);
                    }
                    sw.WriteLine();
                    sw.WriteLine();

                    sw.WriteLine("Transitions:");
                    for (int k = 0; k < numberOfStates; k++)
                    {
                        for (int l = 0; l < numberOfStates; l++)
                        {
                            sw.Write("{0:0.0000}\t", model.Transitions[k, l]);
                        }

                        sw.WriteLine();
                    }
                    sw.WriteLine();

                    sw.WriteLine("Emissions");
                    for (int k = 0; k < numberOfStates; k++)
                    {
                        for (int l = 0; l < testData.NumSymbols; l++)
                        {
                            sw.Write("{0:0.0000}\t", model.Emissions[k, l]);
                        }

                        sw.WriteLine();
                    }
                }
            }
        }
        /// <summary>
        /// Trains the model based on the given position data.
        /// </summary>
        private void TrainModel()
        {
            double trainingLikelihood;
            double factor = this.trainingSampleCount;

            int[][] trainingLabels = DataKMeans();

            Forward modelTopology = new Forward(statesCount, 2);
            this.model = new HiddenMarkovModel(modelTopology, alphabetCount);
            var baumWelchTeacher = new BaumWelchLearning(model);
            baumWelchTeacher.Run(trainingLabels);

            for (int i = 0; i < this.trainingSampleCount; i++)
            {
                trainingLikelihood = model.Evaluate(trainingLabels[i]);
                this.recognitionThreshold += trainingLikelihood;
            }

            this.recognitionThreshold *= (2 / factor);
        }
Пример #14
0
        public static double[] BaumWelchDetectionRGB(double[,] coeffs, Image watermarkedImage, int NumOfScale2, int NumOfTrees, List<int> PNSeq, string rgb, double embed_constant)
        {
            if (rgb == "red")
            {
                #region Red
                double[] Watermark = new double[NumOfTrees];
                /// detectedWatermark will be divide by 3, each will be taken as much as tree/segmented Watermark before embedding
                /// Segmented Watermark for android watermark segmented become 6480 tree each subband. Each subband will be taken 6480 tree
                /// So total row of tree in detected watermark will be 6480 * 3.
                /// in each 6480, the same tree in the same index will be concat become 15 digit watermark, and will be reverse to 5 according to mapping rule.
                /*double[][] detectedWatermark = new double[NumOfScale2][];*/ //49152 total of tree, will be known in input

                // Convert Matrix of Watermark into List of 5-nodes tree get from LH,HH,and HL.
                double[][] listOfTrees = GetSequenceParameter2(coeffs, watermarkedImage, NumOfTrees,"red").Item1;

                // Get the trees of watermark where the actual watermark was embedded
                double[][] WaveletTrees = TreeOfWatermark2(listOfTrees, NumOfTrees, "hh");

                /// Test
                //TextWriter tw1 = new StreamWriter("LIST_OF_WAVELET_TREES.txt");
                //tw1.WriteLine("Total Watermark: " + WaveletTrees.GetLength(0));
                //for (int i = 0; i < WaveletTrees.GetLength(0); i++)
                //{
                //    for (int j = 0; j < WaveletTrees[i].Length; j++)
                //    {
                //        tw1.Write("["+j+"]"+ WaveletTrees[i][j] + " # ");
                //    }
                //    tw1.WriteLine();
                //}
                //foreach (double i in ExtractedWatermark)
                //{
                //    tw1.WriteLine(i);
                //}
                //tw1.Close();

                double[][] watermarkPermutation = GetSequenceParameter2(coeffs, watermarkedImage, NumOfTrees, "red").Item2;
                double[,] hvs = GetSequenceParameter2(coeffs, watermarkedImage, NumOfTrees, "red").Item3;

                double[][] detectedWatermark = new double[WaveletTrees.GetLength(0)][];

                /// Train original wavelet coefficients
                //double[][] listOfTrees2 = GetSequenceParameter(realCoeffs, watermarkedImage).Item1;
                //double[][] WaveletTrees2 = TreeOfWatermark2(listOfTrees2, NumOfTrees);

                #region Baum-Welch Estimation and Learning
                // 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 = 10,

                    FittingOptions = new NormalOptions()
                    {
                        Regularization = 1e-5 // specify a regularization constant
                    }
                };

                // Fit the model
                double likelihood = teacher.Run(WaveletTrees);
                #endregion



                for (int i = 0; i < detectedWatermark.GetLength(0); i++) //Looping each tree = 49152
                {
                    List<double> listOfLikelihood = new List<double>();
                    double[][] pattern = WatermarkPattern(i, PNSeq);
                    double[,] V = CalculateVi2(i, pattern, hvs, embed_constant);
                    for (int j = 0; j < 2; j++) //Looping each permutation of watermark possibility in a tree = 32
                    {
                        double[] T = new double[5];
                        for (int k = 0; k < 5; k++) // Looping each node in tree (5 nodes)
                        {
                            T[k] = (double)WaveletTrees[i][k] - (double)V[j, k];
                        }

                        double loglikelihood = model.Evaluate(T); //Calculate loglikelihood P(W|hmm)
                        listOfLikelihood.Add(loglikelihood);
                    }

                    int maxindex = MaxValueIndex(listOfLikelihood); // Look for maximum value in list of loglikelihood for detection result
                                                                    //detectedWatermark[i] = pattern[maxindex];
                    Watermark[i] = maxindex;
                }


                //return detectedWatermark;
                return Watermark;
                #endregion
            }
            else if(rgb == "green")
            {
                #region Red
                double[] Watermark = new double[NumOfTrees];
                /// detectedWatermark will be divide by 3, each will be taken as much as tree/segmented Watermark before embedding
                /// Segmented Watermark for android watermark segmented become 6480 tree each subband. Each subband will be taken 6480 tree
                /// So total row of tree in detected watermark will be 6480 * 3.
                /// in each 6480, the same tree in the same index will be concat become 15 digit watermark, and will be reverse to 5 according to mapping rule.
                /*double[][] detectedWatermark = new double[NumOfScale2][];*/ //49152 total of tree, will be known in input

                // Convert Matrix of Watermark into List of 5-nodes tree get from LH,HH,and HL.
                double[][] listOfTrees = GetSequenceParameter2(coeffs, watermarkedImage, NumOfTrees, "green").Item1;

                // Get the trees of watermark where the actual watermark was embedded
                double[][] WaveletTrees = TreeOfWatermark2(listOfTrees, NumOfTrees, "hh");

                /// Test
                //TextWriter tw1 = new StreamWriter("LIST_OF_WAVELET_TREES.txt");
                //tw1.WriteLine("Total Watermark: " + WaveletTrees.GetLength(0));
                //for (int i = 0; i < WaveletTrees.GetLength(0); i++)
                //{
                //    for (int j = 0; j < WaveletTrees[i].Length; j++)
                //    {
                //        tw1.Write("["+j+"]"+ WaveletTrees[i][j] + " # ");
                //    }
                //    tw1.WriteLine();
                //}
                //foreach (double i in ExtractedWatermark)
                //{
                //    tw1.WriteLine(i);
                //}
                //tw1.Close();

                double[][] watermarkPermutation = GetSequenceParameter2(coeffs, watermarkedImage, NumOfTrees, "green").Item2;
                double[,] hvs = GetSequenceParameter2(coeffs, watermarkedImage, NumOfTrees, "green").Item3;

                double[][] detectedWatermark = new double[WaveletTrees.GetLength(0)][];

                /// Train original wavelet coefficients
                //double[][] listOfTrees2 = GetSequenceParameter(realCoeffs, watermarkedImage).Item1;
                //double[][] WaveletTrees2 = TreeOfWatermark2(listOfTrees2, NumOfTrees);

                #region Baum-Welch Estimation and Learning
                // 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 = 10,

                    FittingOptions = new NormalOptions()
                    {
                        Regularization = 1e-5 // specify a regularization constant
                    }
                };

                // Fit the model
                double likelihood = teacher.Run(WaveletTrees);
                #endregion



                for (int i = 0; i < detectedWatermark.GetLength(0); i++) //Looping each tree = 49152
                {
                    List<double> listOfLikelihood = new List<double>();
                    double[][] pattern = WatermarkPattern(i, PNSeq);
                    double[,] V = CalculateVi2(i, pattern, hvs, embed_constant);
                    for (int j = 0; j < 2; j++) //Looping each permutation of watermark possibility in a tree = 32
                    {
                        double[] T = new double[5];
                        for (int k = 0; k < 5; k++) // Looping each node in tree (5 nodes)
                        {
                            T[k] = (double)WaveletTrees[i][k] - (double)V[j, k];
                        }

                        double loglikelihood = model.Evaluate(T); //Calculate loglikelihood P(W|hmm)
                        listOfLikelihood.Add(loglikelihood);
                    }

                    int maxindex = MaxValueIndex(listOfLikelihood); // Look for maximum value in list of loglikelihood for detection result
                                                                    //detectedWatermark[i] = pattern[maxindex];
                    Watermark[i] = maxindex;
                }


                //return detectedWatermark;
                return Watermark;
                #endregion
            }
            else
            {
                double[] Watermark = new double[NumOfTrees];
                /// detectedWatermark will be divide by 3, each will be taken as much as tree/segmented Watermark before embedding
                /// Segmented Watermark for android watermark segmented become 6480 tree each subband. Each subband will be taken 6480 tree
                /// So total row of tree in detected watermark will be 6480 * 3.
                /// in each 6480, the same tree in the same index will be concat become 15 digit watermark, and will be reverse to 5 according to mapping rule.
                /*double[][] detectedWatermark = new double[NumOfScale2][];*/ //49152 total of tree, will be known in input

                // Convert Matrix of Watermark into List of 5-nodes tree get from LH,HH,and HL.
                double[][] listOfTrees = GetSequenceParameter2(coeffs, watermarkedImage, NumOfTrees, "blue").Item1;

                // Get the trees of watermark where the actual watermark was embedded
                double[][] WaveletTrees = TreeOfWatermark2(listOfTrees, NumOfTrees, "hh");

                /// Test
                //TextWriter tw1 = new StreamWriter("LIST_OF_WAVELET_TREES.txt");
                //tw1.WriteLine("Total Watermark: " + WaveletTrees.GetLength(0));
                //for (int i = 0; i < WaveletTrees.GetLength(0); i++)
                //{
                //    for (int j = 0; j < WaveletTrees[i].Length; j++)
                //    {
                //        tw1.Write("["+j+"]"+ WaveletTrees[i][j] + " # ");
                //    }
                //    tw1.WriteLine();
                //}
                //foreach (double i in ExtractedWatermark)
                //{
                //    tw1.WriteLine(i);
                //}
                //tw1.Close();

                double[][] watermarkPermutation = GetSequenceParameter2(coeffs, watermarkedImage, NumOfTrees, "blue").Item2;
                double[,] hvs = GetSequenceParameter2(coeffs, watermarkedImage, NumOfTrees, "blue").Item3;

                double[][] detectedWatermark = new double[WaveletTrees.GetLength(0)][];

                /// Train original wavelet coefficients
                //double[][] listOfTrees2 = GetSequenceParameter(realCoeffs, watermarkedImage).Item1;
                //double[][] WaveletTrees2 = TreeOfWatermark2(listOfTrees2, NumOfTrees);

                #region Baum-Welch Estimation and Learning
                // 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 = 10,

                    FittingOptions = new NormalOptions()
                    {
                        Regularization = 1e-5 // specify a regularization constant
                    }
                };

                // Fit the model
                double likelihood = teacher.Run(WaveletTrees);
                #endregion



                for (int i = 0; i < detectedWatermark.GetLength(0); i++) //Looping each tree = 49152
                {
                    List<double> listOfLikelihood = new List<double>();
                    double[][] pattern = WatermarkPattern(i, PNSeq);
                    double[,] V = CalculateVi2(i, pattern, hvs, embed_constant);
                    for (int j = 0; j < 2; j++) //Looping each permutation of watermark possibility in a tree = 32
                    {
                        double[] T = new double[5];
                        for (int k = 0; k < 5; k++) // Looping each node in tree (5 nodes)
                        {
                            T[k] = (double)WaveletTrees[i][k] - (double)V[j, k];
                        }

                        double loglikelihood = model.Evaluate(T); //Calculate loglikelihood P(W|hmm)
                        listOfLikelihood.Add(loglikelihood);
                    }

                    int maxindex = MaxValueIndex(listOfLikelihood); // Look for maximum value in list of loglikelihood for detection result
                                                                    //detectedWatermark[i] = pattern[maxindex];
                    Watermark[i] = maxindex;
                }


                //return detectedWatermark;
                return Watermark;
            }
            
        }
Пример #15
0
 private static double Evaluate(HiddenMarkovModel hmm, int[] sequence)
 {
     return hmm.Evaluate(sequence);
 }
Пример #16
0
        public void GenerateTest()
        {
            double[,] A;
            double[] pi;

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

            GeneralDiscreteDistribution[] B = 
            {  
                new GeneralDiscreteDistribution(0.1, 0.4, 0.5),
                new GeneralDiscreteDistribution(0.6, 0.3, 0.1)
            };

            pi = new double[]
            {
                0.6, 0.4
            };

            var hmm = new HiddenMarkovModel<GeneralDiscreteDistribution>(A, B, pi);


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

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

            Assert.AreEqual(expected, logLikelihood);

        }
Пример #17
0
        public void DecodeTest()
        {

            // Create the transation 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);

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

            // 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

            Assert.AreEqual(logLikelihood, Math.Log(0.01344), 1e-10);
            Assert.AreEqual(path[0], 1);
            Assert.AreEqual(path[1], 0);
            Assert.AreEqual(path[2], 0);
        }
        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("]");
        }
Пример #19
0
        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 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.0001,
                Iterations = 0,
            };

            // Fit the model
            double logLikelihood = teacher.Run(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 });

            Assert.IsTrue(states.IsEqual(0, 1, 0, 1, 0, 1));

            Assert.AreEqual(1.1341500279562791, likelihood, 1e-10);
            Assert.AreEqual(0.8798587580029778, a1, 1e-10);
            Assert.AreEqual(1.0117804233450216, a2, 1e-10);
            Assert.AreEqual(1.8031545195073828E-130, 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, A[0, 0], 1e-16);
            Assert.AreEqual(1, A[0, 1], 1e-16);
            Assert.AreEqual(1, A[1, 0], 1e-16);
            Assert.AreEqual(0, A[1, 1], 1e-16);

            Assert.IsFalse(A.HasNaN());
        }
        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));
            }
        }
Пример #21
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;
        }
        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("]");
        }
Пример #23
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);
        }
        public void LearnTest11()
        {

            // Suppose we have a set of six sequences and we would like to
            // fit a hidden Markov model with mixtures of Normal distributions
            // as the emission densities. 

            // First, let's consider a set of univariate sequences:
            double[][] sequences =
            {
                new double[] { 1, 1, 2, 2, 2, 3, 3, 3 },
                new double[] { 1, 2, 2, 2, 3, 3 },
                new double[] { 1, 2, 2, 3, 3, 5 },
                new double[] { 2, 2, 2, 2, 3, 3, 3, 4, 5, 5, 1 },
                new double[] { 1, 1, 1, 2, 2, 5 },
                new double[] { 1, 2, 2, 4, 4, 5 },
            };


            // Now we can begin specifying a initial Gaussian mixture distribution. It is
            // better to add some different initial parameters to the mixture components:
            var density = new Mixture<NormalDistribution>(
                new NormalDistribution(mean: 2, stdDev: 1.0), // 1st component in the mixture
                new NormalDistribution(mean: 0, stdDev: 0.6), // 2nd component in the mixture
                new NormalDistribution(mean: 4, stdDev: 0.4), // 3rd component in the mixture
                new NormalDistribution(mean: 6, stdDev: 1.1)  // 4th component in the mixture
            );

            // Let's then create a continuous hidden Markov Model with two states organized in a forward
            //  topology with the underlying univariate Normal mixture distribution as probability density.
            var model = new HiddenMarkovModel<Mixture<NormalDistribution>>(new Forward(2), density);

            // Now we should configure the learning algorithms to train the sequence classifier. We will
            // learn until the difference in the average log-likelihood changes only by as little as 0.0001
            var teacher = new BaumWelchLearning<Mixture<NormalDistribution>>(model)
            {
                Tolerance = 0.0001,
                Iterations = 0,

                // Note, however, that since this example is extremely simple and we have only a few
                // data points, a full-blown mixture wouldn't really be needed. Thus we will have a
                // great chance that the mixture would become degenerated quickly. We can avoid this
                // by specifying some regularization constants in the Normal distribution fitting:

                FittingOptions = new MixtureOptions()
                {
                    Iterations = 1, // limit the inner e-m to a single iteration

                    InnerOptions = new NormalOptions()
                    {
                        Regularization = 1e-5 // specify a regularization constant
                    }
                }
            };

            // Finally, we can fit the model
            double logLikelihood = teacher.Run(sequences);

            // And now check the likelihood of some approximate sequences.
            double a1 = Math.Exp(model.Evaluate(new double[] { 1, 1, 2, 2, 3 })); // 2.3413833128741038E+45
            double a2 = Math.Exp(model.Evaluate(new double[] { 1, 1, 2, 5, 5 })); // 9.94607618459872E+19

            // We can see that the likelihood of an unrelated sequence is much smaller:
            double a3 = Math.Exp(model.Evaluate(new double[] { 8, 2, 6, 4, 1 })); // 1.5063654166181737E-44

            Assert.IsTrue(a1 > 1e+6);
            Assert.IsTrue(a2 > 1e+6);
            Assert.IsTrue(a3 < 1e-6);

            Assert.IsFalse(Double.IsNaN(a1));
            Assert.IsFalse(Double.IsNaN(a2));
            Assert.IsFalse(Double.IsNaN(a3));
        }
Пример #25
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);
        }
Пример #26
0
        public void LearnTest10()
        {
            // Create sequences of vector-valued observations. In the
            // sequence below, a single observation is composed of two
            // coordinate values, such as (x, y). There seems to be two
            // states, one for (x,y) values less than (5,5) and another
            // for higher values. The states seems to be switched on
            // every observation.
            double[][][] sequences =
            {
                new double[][] // sequence 1
                {
                    new double[] { 1, 2 }, // observation 1 of sequence 1
                    new double[] { 6, 7 }, // observation 2 of sequence 1
                    new double[] { 2, 3 }, // observation 3 of sequence 1
                },
                new double[][] // sequence 2
                {
                    new double[] { 2, 2 }, // observation 1 of sequence 2
                    new double[] { 9, 8 }, // observation 2 of sequence 2
                    new double[] { 1, 0 }, // observation 3 of sequence 2
                },
                new double[][] // sequence 3
                {
                    new double[] { 1, 3 }, // observation 1 of sequence 3
                    new double[] { 8, 9 }, // observation 2 of sequence 3
                    new double[] { 3, 3 }, // observation 3 of sequence 3
                },
            };


            // Specify a initial normal distribution for the samples.
            var density = new MultivariateNormalDistribution(dimension: 2);

            // 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<MultivariateNormalDistribution>(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 BaumWelchLearning<MultivariateNormalDistribution>(model)
            {
                Tolerance = 0.0001,
                Iterations = 0,
            };

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

            // See the likelihood of the sequences learned
            double a1 = Math.Exp(model.Evaluate(new[] { 
                new double[] { 1, 2 }, 
                new double[] { 6, 7 },
                new double[] { 2, 3 }})); // 0.000208

            double a2 = Math.Exp(model.Evaluate(new[] { 
                new double[] { 2, 2 }, 
                new double[] { 9, 8  },
                new double[] { 1, 0 }})); // 0.0000376

            // See the likelihood of an unrelated sequence
            double a3 = Math.Exp(model.Evaluate(new[] { 
                new double[] { 8, 7 }, 
                new double[] { 9, 8  },
                new double[] { 1, 0 }})); // 2.10 x 10^(-89)

            Assert.AreEqual(0.00020825319093038984, a1);
            Assert.AreEqual(0.000037671116792519834, a2);
            Assert.AreEqual(2.1031924118199194E-89, a3);
        }
        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(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);
        }
Пример #28
0
        private void foo2()
        {
            double[][][] sequences = new double[][][]
            {
                new double[][] { new double[] {0.1, 10}, new double[] {5.2, 10}, new double[] {0.3, 10}, new double[] {6.7, 10}, new double[] {0.1, 10}, new double[] {6.0, 10} },
                new double[][] { new double[] {0.2, 0}, new double[] {6.2, 0}, new double[] {0.3, 0}, new double[] {6.3, 0}, new double[] {0.1, 0}, new double[] {5.0, 0} },
                new double[][] { new double[] {0.1, 0}, new double[] {7.0, 0}, new double[] {0.1, 0}, new double[] {7.0, 0}, new double[] {0.2, 0}, new double[] {5.6, 0} },
            };

            MultivariateNormalDistribution density = new MultivariateNormalDistribution(2);

            var model = new HiddenMarkovModel<MultivariateNormalDistribution>(new Ergodic(2), density);

            var teacher = new BaumWelchLearning<MultivariateNormalDistribution>(model)
            {
                Tolerance = 0.0001,
                Iterations = 0,
                // Specify a regularization constant
                FittingOptions = new NormalOptions() { Regularization = 1e-5 }
            };

            double likelihood = teacher.Run(sequences);

            double l1 = model.Evaluate(new double[][] { new double[] { 0.1, 0 }, new double[] { 7.0, 0 }, new double[] { 0.1, 0 }, new double[] { 7.0, 0 }, new double[] { 0.2, 0 }, new double[] { 5.6, 0 } }, true); // 0.87
            double l2 = model.Evaluate(new double[][] { new double[] { 0.2, 0 }, new double[] { 6.2, 0 }, new double[] { 0.3, 0 }, new double[] { 6.3, 0 }, new double[] { 0.1, 0 }, new double[] { 5.0, 0 } }, true); // 1.00

            double l3 = model.Evaluate(new double[][] { new double[] { 1.2, 0 }, new double[] { 1.2, 0 }, new double[] { 1.3, 0 }, new double[] { 1.3, 0 }, new double[] { 1.1, 0 }, new double[] { 1.0, 0 } }, true); // 0.00
        }