public Evaluate ( int observations ) : double | ||
observations | int | /// A sequence of observations. /// |
return | 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("]"); }
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)); }
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); }
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); }
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); }
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]); }
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); }
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); }
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); }
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; } }
private static double Evaluate(HiddenMarkovModel hmm, int[] sequence) { return hmm.Evaluate(sequence); }
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); }
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("]"); }
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)); } }
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("]"); }
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)); }
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); }
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); }
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 }