/// <summary> /// Constructs a new potential function modeling Hidden Markov Models. /// </summary> /// /// <param name="states">The number of states.</param> /// <param name="symbols">The number of symbols.</param> /// <param name="outputClasses">The number of output classes.</param> /// public MarkovDiscreteFunction(int states, int symbols, int outputClasses) { this.Outputs = outputClasses; this.Symbols = symbols; int factorIndex = 0; var factorParams = new List <double>(); var factorFeatures = new List <IFeature <int> >(); this.Factors = new FactorPotential <int> [Outputs]; int[] classOffset = new int[outputClasses]; int[] edgeOffset = new int[outputClasses]; int[] stateOffset = new int[outputClasses]; int[] classCount = new int[outputClasses]; int[] edgeCount = new int[outputClasses]; int[] stateCount = new int[outputClasses]; // Create features for initial class probabilities for (int c = 0; c < outputClasses; c++) { var stateParams = new List <double>(); var stateFeatures = new List <IFeature <int> >(); var edgeParams = new List <double>(); var edgeFeatures = new List <IFeature <int> >(); var classParams = new List <double>(); var classFeatures = new List <IFeature <int> >(); // Create features for class labels classParams.Add(Math.Log(1.0 / outputClasses)); classFeatures.Add(new OutputFeature <int>(this, c, c)); // Create features for initial state probabilities for (int i = 0; i < states; i++) { edgeParams.Add((i == 0) ? Math.Log(1.0) : Math.Log(0.0)); edgeFeatures.Add(new InitialFeature <int>(this, c, i)); } // Create features for state transition probabilities for (int i = 0; i < states; i++) { for (int j = 0; j < states; j++) { edgeParams.Add(Math.Log(1.0 / states)); edgeFeatures.Add(new TransitionFeature <int>(this, c, i, j)); } } // Create features for symbol emission probabilities for (int i = 0; i < states; i++) { for (int k = 0; k < symbols; k++) { stateParams.Add(Math.Log(1.0 / symbols)); stateFeatures.Add(new EmissionFeature(this, c, i, k)); } } classOffset[c] = factorIndex; edgeOffset[c] = factorIndex + classParams.Count; stateOffset[c] = factorIndex + classParams.Count + edgeParams.Count; classCount[c] = classParams.Count; edgeCount[c] = edgeParams.Count; stateCount[c] = stateParams.Count; // 1. classes factorFeatures.AddRange(classFeatures); factorParams.AddRange(classParams); // 2. edges factorFeatures.AddRange(edgeFeatures); factorParams.AddRange(edgeParams); // 3. states factorFeatures.AddRange(stateFeatures); factorParams.AddRange(stateParams); factorIndex += classParams.Count + stateParams.Count + edgeParams.Count; } Accord.Diagnostics.Debug.Assert(factorIndex == factorParams.Count); Accord.Diagnostics.Debug.Assert(factorIndex == factorFeatures.Count); this.Weights = factorParams.ToArray(); this.Features = factorFeatures.ToArray(); for (int c = 0; c < outputClasses; c++) { Factors[c] = new MarkovDiscreteFactor(this, states, c, symbols, classIndex: classOffset[c], classCount: classCount[c], // 1. classes edgeIndex: edgeOffset[c], edgeCount: edgeCount[c], // 2. edges stateIndex: stateOffset[c], stateCount: stateCount[c]); // 3. states } }
/// <summary> /// Constructs a new potential function modeling Hidden Markov Models. /// </summary> /// /// <param name="classifier">The classifier model.</param> /// <param name="includePriors">True to include class features (priors), false otherwise.</param> /// public MarkovDiscreteFunction(HiddenMarkovClassifier <GeneralDiscreteDistribution, int> classifier, bool includePriors = true) { this.Symbols = classifier.Models[0].Emissions[0].Length; this.Outputs = classifier.Classes; int factorIndex = 0; var factorParams = new List <double>(); var factorFeatures = new List <IFeature <int> >(); this.Factors = new FactorPotential <int> [Outputs]; int[] classOffset = new int[classifier.Classes]; int[] edgeOffset = new int[classifier.Classes]; int[] stateOffset = new int[classifier.Classes]; int[] classCount = new int[classifier.Classes]; int[] edgeCount = new int[classifier.Classes]; int[] stateCount = new int[classifier.Classes]; // Create features for initial class probabilities for (int c = 0; c < classifier.Classes; c++) { var stateParams = new List <double>(); var stateFeatures = new List <IFeature <int> >(); var edgeParams = new List <double>(); var edgeFeatures = new List <IFeature <int> >(); var classParams = new List <double>(); var classFeatures = new List <IFeature <int> >(); var model = classifier[c]; if (includePriors) { // Create features for class labels classParams.Add(Math.Log(classifier.Priors[c])); classFeatures.Add(new OutputFeature <int>(this, c, c)); } // Create features for initial state probabilities for (int i = 0; i < model.States; i++) { edgeParams.Add(model.LogInitial[i]); edgeFeatures.Add(new InitialFeature <int>(this, c, i)); } // Create features for state transition probabilities for (int i = 0; i < model.States; i++) { for (int j = 0; j < model.States; j++) { edgeParams.Add(model.LogTransitions[i][j]); edgeFeatures.Add(new TransitionFeature <int>(this, c, i, j)); } } // Create features for symbol emission probabilities for (int i = 0; i < model.States; i++) { for (int k = 0; k < model.Emissions[i].Length; k++) { stateParams.Add(model.Emissions[i][k]); stateFeatures.Add(new EmissionFeature(this, c, i, k)); } } classOffset[c] = factorIndex; edgeOffset[c] = factorIndex + classParams.Count; stateOffset[c] = factorIndex + classParams.Count + edgeParams.Count; classCount[c] = classParams.Count; edgeCount[c] = edgeParams.Count; stateCount[c] = stateParams.Count; // 1. classes factorFeatures.AddRange(classFeatures); factorParams.AddRange(classParams); // 2. edges factorFeatures.AddRange(edgeFeatures); factorParams.AddRange(edgeParams); // 3. states factorFeatures.AddRange(stateFeatures); factorParams.AddRange(stateParams); factorIndex += classParams.Count + stateParams.Count + edgeParams.Count; } Accord.Diagnostics.Debug.Assert(factorIndex == factorParams.Count); Accord.Diagnostics.Debug.Assert(factorIndex == factorFeatures.Count); this.Weights = factorParams.ToArray(); this.Features = factorFeatures.ToArray(); for (int c = 0; c < classifier.Models.Length; c++) { Factors[c] = new MarkovDiscreteFactor(this, classifier.Models[c].States, c, Symbols, classIndex: classOffset[c], classCount: classCount[c], // 1. classes edgeIndex: edgeOffset[c], edgeCount: edgeCount[c], // 2. edges stateIndex: stateOffset[c], stateCount: stateCount[c]); // 3. states } }