public override void Learn(SequenceData trainingData, SequenceData validationData, SequenceData testData) { //HMMGraph graph = RandomGraph(trainingData.NumSymbols); HMMGraph graph; //bestHMM = ModelConverter.Graph2HMM(graph); bestHMM = SparseHiddenMarkovModel.FromCompleteGraph(trainingData.NumSymbols, trainingData.NumSymbols); bestHMM.Learn(trainingData.GetNonempty(), baumwelchThreshold); //while (bestHMM.States < maxStates) while (bestHMM.NumberOfStates < maxStates) { WriteLine("Taking one more iteration"); //graph = ModelConverter.HMM2Graph(bestHMM); graph = bestHMM.ToGraph(); Dictionary<int, double> nodePerformance = new Dictionary<int, double>(); Dictionary<int, int> nodeOccurence = new Dictionary<int, int>(); double hiddenStateSequenceProbability; foreach (int[] signal in validationData.GetNonempty()) { //int[] hiddenStateSequence = bestHMM.Decode(signal, out hiddenStateSequenceProbability); int[] hiddenStateSequence = bestHMM.Viterby(signal, out hiddenStateSequenceProbability); for (int j = 0; j < hiddenStateSequence.Length; j++) { if (nodePerformance.ContainsKey(hiddenStateSequence[j])) { //nodePerformance[hiddenStateSequence[j]] += (Math.Log(hiddenStateSequenceProbability) + Math.Log(bestHMM.Emissions[hiddenStateSequence[j], signal[j]])); nodePerformance[hiddenStateSequence[j]] += (Math.Log(hiddenStateSequenceProbability) + Math.Log(bestHMM.EmissionProbability(hiddenStateSequence[j], signal[j]))); nodeOccurence[hiddenStateSequence[j]]++; } else { nodePerformance.Add(hiddenStateSequence[j], (Math.Log(hiddenStateSequenceProbability) + Math.Log(bestHMM.EmissionProbability(hiddenStateSequence[j], signal[j])))); nodeOccurence.Add(hiddenStateSequence[j], 1); } } } foreach (int node in nodeOccurence.Keys) { nodePerformance[node] /= nodeOccurence[node]; } int weakPoint = nodePerformance.Keys.Aggregate((a, b) => ((nodePerformance[b] < nodePerformance[a]) ? b : a)); SplitWorstPerformingNode(graph, weakPoint); //bestHMM = ModelConverter.Graph2HMM(graph); bestHMM = SparseHiddenMarkovModel.FromGraph(graph); WriteLine("Running BaumWelch"); bestHMM.Learn(trainingData.GetNonempty(), baumwelchThreshold); //Run the BaumWelch algorithm WriteLine(""); WriteLine("Log Likelihood: " + LogLikelihood(bestHMM, trainingData)); } }
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); }
public override void Learn(SequenceData trainingData, SequenceData validationData, SequenceData testData) { HMMGraph graph = new HMMGraph(trainingData.NumSymbols); //Add nodes and set initial and emission probabilities for (int i = 0; i < states; i++) { Node new_node = new Node(); for (int s = 0; s < trainingData.NumSymbols; s++) new_node.SetEmission(s, ran.NextDouble()); new_node.InitialProbability = ran.NextDouble(); graph.AddNode(new_node); } //Add random transmissions. Each node will have at most Log(n) edges in both directions //for (int i = 0; i < graph.Nodes.Count; i++) //{ // List<Node> shuffled = graph.Nodes.Select(e => e).ToList(); // Utilities.Shuffle(shuffled); // int upperBound = (int)Math.Ceiling(Math.Log(graph.Nodes.Count)); // if (upperBound >= graph.Nodes.Count) // upperBound = graph.Nodes.Count - 1; // for (int p = 0; p <= upperBound; p++) // { // Node from = graph.Nodes[i]; // Node to = graph.Nodes[p]; // from.SetTransition(to, ran.NextDouble()); // } //} int numberOfTransitions = (int)Math.Ceiling(Math.Log(states)); foreach (Node node in graph.Nodes) { for (int i = 0; i < numberOfTransitions; i++) { Node target; while (node.Transitions.ContainsKey(target = graph.Nodes[ran.Next(states)])); node.SetTransition(target, ran.NextDouble()); } } graph.Normalize(); hmm = SparseHiddenMarkovModel.FromGraph(graph); hmm.Learn(trainingData.GetNonempty(), tolerance); }
public override void Learn(SequenceData trainingData, SequenceData validationData, SequenceData testData) { //trainingData.AddSequences(validationData); double[] initialProbabilities = new double[states]; double sum = 0.0; for (int k = 0; k < states; k++) { initialProbabilities[k] = random.NextDouble(); sum += initialProbabilities[k]; } for (int k = 0; k < states; k++) { initialProbabilities[k] /= sum; } double[,] transitionMatrix = new double[states, states]; for (int k = 0; k < states; k++) { sum = 0.0; for (int l = 0; l < states; l++) { transitionMatrix[k, l] = random.NextDouble(); sum += transitionMatrix[k, l]; } for (int l = 0; l < states; l++) { transitionMatrix[k, l] /= sum; } } double[,] emissionMatrix = new double[states, testData.NumSymbols]; for (int k = 0; k < states; 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; } } //hmm = new HiddenMarkovModel(trainingData.NumSymbols, states); hmm = new HiddenMarkovModel(transitionMatrix, emissionMatrix, initialProbabilities); Stopwatch sw = new Stopwatch(); sw.Start(); hmm.Learn(trainingData.GetNonempty(), tolerance); sw.Stop(); Console.WriteLine(sw.Elapsed.TotalSeconds); }
private double[] ComputeViterbyScores(SequenceData validationData, bool normalise = false) { double[] scores = new double[NumberOfStates]; foreach (int[] signal in validationData.GetNonempty()) { double probability; double[] subscore = new double[NumberOfStates]; int[] occurenceCount = new int[NumberOfStates]; //int[] hiddenStateSequence = hmm.Viterby(signal, out probability); int[] hiddenStateSequence = hmm.Decode(signal, out probability); if (hiddenStateSequence == null) { continue; } for (int t = 0; t < signal.Length; t++) { //subscore[hiddenStateSequence[t]] += hmm.EmissionProbability(hiddenStateSequence[t], signal[t]); subscore[hiddenStateSequence[t]] += hmm.Emissions[hiddenStateSequence[t], signal[t]]; occurenceCount[hiddenStateSequence[t]]++; } for (int i = 0; i < NumberOfStates; i++) { if (occurenceCount[i] > 0) { subscore[i] = ((probability * subscore[i]) / occurenceCount[i]); } scores[i] += subscore[i]; } } for (int i = 0; i < NumberOfStates; i++) { scores[i] /= validationData.Count; } if (normalise) { double sum = 0; for (int i = 0; i < NumberOfStates; i++) { sum += scores[i]; } for (int i = 0; i < NumberOfStates; i++) { scores[i] /= sum; } } return scores; }
public override void Learn(SequenceData trainingData, SequenceData validationData, SequenceData testData) { hmm = SparseHiddenMarkovModel.FromCompleteGraph(1, trainingData.NumSymbols); double temperature = 2; double epsilon = 1.0; double likelihood = 0.0; double newLikelihood = Double.MinValue; double lastSparsity = hmm.TransitionSparsity; int stagnation = 1; do { if (temperature > 2) { HMMGraph graph = hmm.ToGraph(); CutEdges(graph, epsilon); if (hmm.TransitionSparsity != lastSparsity) { lastSparsity = hmm.TransitionSparsity; stagnation = Math.Max(1, (stagnation - 1)); } else { stagnation++; } //int numberOfStatesToAdd = Math.Max(0, (int)Math.Min(hmm.NumberOfStates, Math.Ceiling(Math.Log(Math.Pow(Math.Log(newLikelihood - likelihood), (1 / stagnation)) / (Math.Sqrt(temperature) * threshold))))); //int numberOfStatesToAdd = (((stagnation / temperature) > threshold) ? 1 : 0); int numberOfStatesToAdd = 1; foreach (int weakPoint in IdentifyWeakStates(validationData, numberOfStatesToAdd)) { SplitState(graph, weakPoint); stagnation = 1; } if (numberOfStatesToAdd == 0) { stagnation *= 2; } hmm = SparseHiddenMarkovModel.FromGraph(graph); WriteLine(String.Format("Added {0} states", numberOfStatesToAdd)); } temperature *= Math.Max(2, Math.Sqrt(hmm.NumberOfStates)); //temperature *= Math.Max(2, stagnation); epsilon = (1 / Math.Log(temperature)); double bwThreshold = Math.Pow(Math.Max(threshold, (1 / (-Math.Min((-1), Math.Log(Math.Min((1 - threshold), (1 / temperature)) / (1 - threshold)))))), stagnation); //int bwIterations = Math.Max(1, (int)Math.Log(stagnation * temperature * threshold)); WriteLine(String.Format("Running Baum-Welch with threshold {0}...", bwThreshold)); //WriteLine(String.Format("Running Baum-Welch with {0} iterations...", bwIterations)); hmm.Learn(trainingData.GetNonempty(), bwThreshold); //hmm.Learn(trainingData.GetNonempty(), 0.0, bwIterations); likelihood = newLikelihood; newLikelihood = 0.0; foreach (int[] signal in validationData.GetNonempty()) { newLikelihood += hmm.Evaluate(signal, true); } WriteLine(String.Empty); WriteLine(String.Format("Stagnation: {0}", stagnation)); WriteLine(String.Format("Epsilon: {0}", epsilon)); WriteLine(String.Format("Number of HMM States: {0}", hmm.NumberOfStates)); WriteLine(String.Format("Transition Sparsity; {0}", hmm.TransitionSparsity)); WriteLine(String.Format("Log Likelihood: {0}", newLikelihood)); WriteLine(String.Empty); } while ((Math.Abs(newLikelihood - likelihood) * Math.Pow(epsilon, 2)) > threshold); }
private IEnumerable<int> IdentifyWeakStates(SequenceData validationData, int numberOfStates = 1) //Using Viterby { double[] scores = new double[hmm.NumberOfStates]; foreach(int[] signal in validationData.GetNonempty()) { double probability; double[] subscore = new double[hmm.NumberOfStates]; int[] occurenceCount = new int[hmm.NumberOfStates]; int[] hiddenStateSequence = hmm.Viterby(signal, out probability); if (hiddenStateSequence == null) { continue; } for (int t = 0; t < signal.Length; t++) { subscore[hiddenStateSequence[t]] += hmm.EmissionProbability(hiddenStateSequence[t], signal[t]); occurenceCount[hiddenStateSequence[t]]++; } for (int i = 0; i < hmm.NumberOfStates; i++) { if (occurenceCount[i] > 0) { subscore[i] = ((probability * subscore[i]) / occurenceCount[i]); } scores[i] += subscore[i]; } } return Enumerable.Range(0, hmm.NumberOfStates).OrderBy(i => scores[i]).Take(numberOfStates); //double worstScore = Double.MaxValue; //int worstPerformer = 0; //for (int i = 0; i < hmm.NumberOfStates; i++) //{ // if (scores[i] < worstScore) // { // worstScore = scores[i]; // worstPerformer = i; // } //} //yield return worstPerformer; }