public static HiddenMarkovModel<GeneralDiscreteDistribution, int> CreateDiscrete(double[,] transitions, double[,] emissions, double[] probabilities, bool logarithm = false) { ITopology topology = new Custom(transitions, probabilities, logarithm); if (emissions == null) { throw new ArgumentNullException("emissions"); } if (emissions.GetLength(0) != topology.States) { throw new ArgumentException( "The emission matrix should have the same number of rows as the number of states in the model.", "emissions"); } // Initialize B using a discrete distribution var B = new GeneralDiscreteDistribution[topology.States]; for (int i = 0; i < B.Length; i++) B[i] = new GeneralDiscreteDistribution(Accord.Math.Matrix.GetRow(emissions, i)); return new HiddenMarkovModel<GeneralDiscreteDistribution, int>(topology, B); }
public void ConstructorTest() { // Create a Categorical distribution for 3 symbols, in which // the first and second symbol have 25% chance of appearing, // and the third symbol has 50% chance of appearing. // 1st 2nd 3rd double[] probabilities = { 0.25, 0.25, 0.50 }; var dist = new GeneralDiscreteDistribution(probabilities); double mean = dist.Mean; // 1.25 double median = dist.Median; // 1.00 double var = dist.Variance; // 0.6875 double cdf = dist.DistributionFunction(k: 2); // 1 double pdf1 = dist.ProbabilityMassFunction(k: 0); // 0.25 double pdf2 = dist.ProbabilityMassFunction(k: 1); // 0.25 double pdf3 = dist.ProbabilityMassFunction(k: 2); // 0.50 double lpdf = dist.LogProbabilityMassFunction(k: 2); // -0.69314718055994529 double ccdf = dist.ComplementaryDistributionFunction(k: 2); // 0.0 int icdf1 = dist.InverseDistributionFunction(p: 0.17); // 0 int icdf2 = dist.InverseDistributionFunction(p: 0.39); // 1 int icdf3 = dist.InverseDistributionFunction(p: 0.56); // 2 double hf = dist.HazardFunction(x: 0); // 0.33333333333333331 double chf = dist.CumulativeHazardFunction(x: 0); // 0.2876820724517809 string str = dist.ToString(CultureInfo.InvariantCulture); // "Categorical(x; p = { 0.25, 0.25, 0.5 })" Assert.AreEqual(1.25, mean); Assert.AreEqual(1.00, median); Assert.AreEqual(0.6875, var); Assert.AreEqual(0.2876820724517809, chf, 1e-10); Assert.AreEqual(1.0, cdf); Assert.AreEqual(0.25, pdf1); Assert.AreEqual(0.25, pdf2); Assert.AreEqual(0.5, pdf3); Assert.AreEqual(-0.69314718055994529, lpdf); Assert.AreEqual(0.33333333333333331, hf, 1e-10); Assert.AreEqual(0.0, ccdf); Assert.AreEqual(0, icdf1); Assert.AreEqual(1, icdf2); Assert.AreEqual(2, icdf3); Assert.AreEqual("Categorical(x; p = { 0.25, 0.25, 0.5 })", str); }
/// <summary> /// Generates a random observation from the current distribution. /// </summary> /// /// <returns>A random observations drawn from this distribution.</returns> /// public override double Generate() { // Choose one coefficient at random int c = GeneralDiscreteDistribution.Random(coefficients); // Sample from the chosen coefficient var d = components[c] as ISampleableDistribution <double>; if (d == null) { throw new InvalidOperationException(); } return(d.Generate()); }
/// <summary> /// Generates a random observation from the current distribution. /// </summary> /// /// <returns>A random observations drawn from this distribution.</returns> /// public override double Generate(Random source) { if (sampleable == null) { sampleable = new ISampleableDistribution <double> [components.Length]; for (int i = 0; i < sampleable.Length; i++) { sampleable[i] = this.components[i] as ISampleableDistribution <double>; } } // Choose one coefficient at random int j = GeneralDiscreteDistribution.Random(coefficients, source); // Sample from the chosen coefficient return(sampleable[j].Generate()); }
public static HiddenMarkovModel<GeneralDiscreteDistribution, int> CreateDiscrete(ITopology topology, int symbols, bool random) { if (symbols <= 0) { throw new ArgumentOutOfRangeException("symbols", "Number of symbols should be higher than zero."); } double[,] A; double[] pi; topology.Create(true, out A, out pi); // Initialize B with a uniform discrete distribution var B = new GeneralDiscreteDistribution[topology.States]; if (random) { for (int i = 0; i < B.Length; i++) { double[] probabilities = new double[symbols]; double sum = 0; for (int j = 0; j < probabilities.Length; j++) sum += probabilities[j] = Accord.Math.Random.Generator.Random.NextDouble(); for (int j = 0; j < probabilities.Length; j++) probabilities[j] /= sum; B[i] = new GeneralDiscreteDistribution(true, probabilities.Log()); } } else { for (int i = 0; i < B.Length; i++) B[i] = new GeneralDiscreteDistribution(logarithm: true, symbols: symbols); } return new HiddenMarkovModel<GeneralDiscreteDistribution, int>(A, B, pi, logarithm: true); }
/// <summary> /// Generates a random vector of observations from the current distribution. /// </summary> /// /// <param name="samples">The number of samples to generate.</param> /// <param name="result">The location where to store the samples.</param> /// /// <returns>A random vector of observations drawn from this distribution.</returns> /// public override double[] Generate(int samples, double[] result) { if (sampleable == null) { sampleable = new ISampleableDistribution <double> [components.Length]; for (int i = 0; i < sampleable.Length; i++) { sampleable[i] = this.components[i] as ISampleableDistribution <double>; } } for (int i = 0; i < samples; i++) { // Choose one coefficient at random int j = GeneralDiscreteDistribution.Random(coefficients); // Sample from the chosen coefficient result[i] = sampleable[j].Generate(); } return(result); }
public void GenerateTest() { double[] transProbRow = { 0.2, 0.5, 0.3 }; var gdd = new GeneralDiscreteDistribution(transProbRow); int n = 100000; { int[] samples = gdd.Generate(n); var target = new GeneralDiscreteDistribution(3); target.Fit(samples); Assert.AreEqual(0.2, target.Frequencies[0], 0.01); Assert.AreEqual(0.5, target.Frequencies[1], 0.01); Assert.AreEqual(0.3, target.Frequencies[2], 0.01); } { int[] samples = new int[n].Apply((x) => gdd.Generate()); var target = new GeneralDiscreteDistribution(3); target.Fit(samples); Assert.AreEqual(0.2, target.Frequencies[0], 0.01); Assert.AreEqual(0.5, target.Frequencies[1], 0.01); Assert.AreEqual(0.3, target.Frequencies[2], 0.01); } { double[] samples = gdd.Generate(n).ToDouble(); var target = new GeneralDiscreteDistribution(3); target.Fit(samples); Assert.AreEqual(0.2, target.Frequencies[0], 0.01); Assert.AreEqual(0.5, target.Frequencies[1], 0.01); Assert.AreEqual(0.3, target.Frequencies[2], 0.01); } { double[] samples = new int[n].Apply((x) => (double)gdd.Generate()); var target = new GeneralDiscreteDistribution(3); target.Fit(samples); Assert.AreEqual(0.2, target.Frequencies[0], 0.01); Assert.AreEqual(0.5, target.Frequencies[1], 0.01); Assert.AreEqual(0.3, target.Frequencies[2], 0.01); } }
/// <summary> /// Constructs a new Hidden Markov Model with discrete state probabilities. /// </summary> /// /// <param name="topology"> /// A <see cref="Topology"/> object specifying the initial values of the matrix of transition /// probabilities <c>A</c> and initial state probabilities <c>pi</c> to be used by this model. /// </param> /// <param name="symbols">The number of output symbols used for this model.</param> /// public static HiddenMarkovModel<GeneralDiscreteDistribution> CreateGeneric(ITopology topology, int symbols) { if (symbols <= 0) { throw new ArgumentOutOfRangeException("symbols", "Number of symbols should be higher than zero."); } // Initialize B with a uniform discrete distribution GeneralDiscreteDistribution[] B = new GeneralDiscreteDistribution[topology.States]; for (int i = 0; i < B.Length; i++) B[i] = new GeneralDiscreteDistribution(symbols); return new HiddenMarkovModel<GeneralDiscreteDistribution>(topology, B); }
public void EntropyTest() { var target = new GeneralDiscreteDistribution(42, 0.1, 0.4, 0.5); double expected = -0.1 * System.Math.Log(0.1) + -0.4 * System.Math.Log(0.4) + -0.5 * System.Math.Log(0.5); Assert.AreEqual(expected, target.Entropy); }
public void MeanTest3() { var target = new GeneralDiscreteDistribution(2, 0.5, 0.5); double expected = (2.0 + 3.0) / 2.0; double actual = target.Mean; Assert.AreEqual(expected, actual); }
public void DistributionFunctionTest() { var target = new GeneralDiscreteDistribution(0.1, 0.4, 0.5); double actual; actual = target.DistributionFunction(0); Assert.AreEqual(0.1, actual, 1e-6); actual = target.DistributionFunction(1); Assert.AreEqual(0.5, actual, 1e-6); actual = target.DistributionFunction(2); Assert.AreEqual(1.0, actual, 1e-6); actual = target.DistributionFunction(3); Assert.AreEqual(1.0, actual, 1e-6); Assert.AreEqual(1.3999999, target.Mean, 1e-6); }
/// <summary> /// Creates a new object that is a copy of the current instance. /// </summary> /// <returns> /// A new object that is a copy of this instance. /// </returns> public override object Clone() { var c = new GeneralDiscreteDistribution(); c.probabilities = (double[]) probabilities.Clone(); c.start = start; c.mean = mean; c.entropy = entropy; c.variance = variance; return c; }
public void RunTest() { // Example from // http://www.cs.columbia.edu/4761/notes07/chapter4.3-HMM.pdf double[][] observations = { new double[] { 0,0,0,1,0,0 }, new double[] { 1,0,0,1,0,0 }, new double[] { 0,0,1,0,0,0 }, new double[] { 0,0,0,0,1,0 }, new double[] { 1,0,0,0,1,0 }, new double[] { 0,0,0,1,1,0 }, new double[] { 1,0,0,0,0,0 }, new double[] { 1,0,1,0,0,0 }, }; int[][] paths = { new int[] { 0,0,1,0,1,0 }, new int[] { 1,0,1,0,1,0 }, new int[] { 1,0,0,1,1,0 }, new int[] { 1,0,1,1,1,0 }, new int[] { 1,0,0,1,0,1 }, new int[] { 0,0,1,0,0,1 }, new int[] { 0,0,1,1,0,1 }, new int[] { 0,1,1,1,0,0 }, }; GeneralDiscreteDistribution initial = new GeneralDiscreteDistribution(symbols: 2); var model = new HiddenMarkovModel<GeneralDiscreteDistribution>(states: 2, emissions: initial); var target = new MaximumLikelihoodLearning<GeneralDiscreteDistribution>(model); target.UseLaplaceRule = false; double logLikelihood = target.Run(observations, paths); var pi = Matrix.Exp(model.Probabilities); var A = Matrix.Exp(model.Transitions); var B = model.Emissions; Assert.AreEqual(0.5, pi[0]); Assert.AreEqual(0.5, pi[1]); Assert.AreEqual(7 / 20.0, A[0, 0], 1e-5); Assert.AreEqual(13 / 20.0, A[0, 1], 1e-5); Assert.AreEqual(14 / 20.0, A[1, 0], 1e-5); Assert.AreEqual(6 / 20.0, A[1, 1], 1e-5); Assert.AreEqual(17 / 25.0, B[0].ProbabilityMassFunction(0)); Assert.AreEqual(8 / 25.0, B[0].ProbabilityMassFunction(1)); Assert.AreEqual(19 / 23.0, B[1].ProbabilityMassFunction(0)); Assert.AreEqual(4 / 23.0, B[1].ProbabilityMassFunction(1)); Assert.AreEqual(-1.1472359046136624, logLikelihood); }
/// <summary> /// Constructs a new Hidden Markov Model. /// </summary> /// <param name="transitions">The transitions matrix A for this model.</param> /// <param name="emissions">The emissions matrix B for this model.</param> /// <param name="probabilities">The initial state probabilities for this model.</param> public ContinuousHiddenMarkovModel(double[,] transitions, double[,] emissions, double[] probabilities) : base(new Custom(transitions, probabilities)) { if (emissions == null) { throw new ArgumentNullException("emissions"); } if (emissions.GetLength(0) != States) { throw new ArgumentException( "The emission matrix should have the same number of rows as the number of states in the model.", "emissions"); } // Initialize B using a discrete distribution B = new GeneralDiscreteDistribution[States]; for (int i = 0; i < B.Length; i++) B[i] = new GeneralDiscreteDistribution(Matrix.GetRow(emissions, i)); dimension = 1; }
/// <summary> /// Constructs a new Hidden Markov Model with discrete state probabilities. /// </summary> /// <param name="topology"> /// A <see cref="Topology"/> object specifying the initial values of the matrix of transition /// probabilities <c>A</c> and initial state probabilities <c>pi</c> to be used by this model. /// </param> /// <param name="symbols">The number of output symbols used for this model.</param> public ContinuousHiddenMarkovModel(ITopology topology, int symbols) : base(topology) { if (symbols <= 0) { throw new ArgumentOutOfRangeException("symbols", "Number of symbols should be higher than zero."); } // Initialize B with a uniform discrete distribution B = new IDistribution[States]; for (int i = 0; i < B.Length; i++) B[i] = new GeneralDiscreteDistribution(symbols); dimension = 1; }
public void ConstructorTest2() { double[] probabilities = { 0.25, 0.25, 0.50 }; var dist = new GeneralDiscreteDistribution(probabilities); double var = dist.Variance; // 0.6875 double median = dist.Median; // 1.00 double mean = dist.Mean; // 1.25 Assert.AreEqual(1.25, mean); Assert.AreEqual(1.00, median); Assert.AreEqual(0.6875, var); }
public void FitTest2() { double[] expected = { 0.50, 0.00, 0.25, 0.25 }; GeneralDiscreteDistribution target; double[] values = { 0.00, 2.00, 3.00 }; double[] weights = { 0.50, 0.25, 0.25 }; target = new GeneralDiscreteDistribution(4); target.Fit(values, weights); double[] actual = target.Frequencies; Assert.IsTrue(Matrix.IsEqual(expected, actual)); // -- double[] values2 = { 0.00, 0.00, 2.00, 3.00 }; double[] weights2 = { 0.25, 0.25, 0.25, 0.25 }; target = new GeneralDiscreteDistribution(4); target.Fit(values2, weights2); double[] actual2 = target.Frequencies; Assert.IsTrue(Matrix.IsEqual(expected, actual2)); }
public static HiddenMarkovClassifier<Independent> CreateModel2(out double[][][] sequences, out int[] labels) { sequences = new double[][][] { new double[][] { // This is the first sequence with label = 0 new double[] { 0, 1.1 }, new double[] { 1, 2.5 }, new double[] { 1, 3.4 }, new double[] { 1, 4.7 }, new double[] { 2, 5.8 }, }, new double[][] { // This is the second sequence with label = 1 new double[] { 2, 3.2 }, new double[] { 2, 2.6 }, new double[] { 1, 1.2 }, new double[] { 1, 0.8 }, new double[] { 0, 1.1 }, } }; labels = new[] { 0, 1 }; // Create a Continuous density Hidden Markov Model Sequence Classifier // to detect a multivariate sequence and the same sequence backwards. var comp1 = new GeneralDiscreteDistribution(3); var comp2 = new NormalDistribution(1); var density = new Independent(comp1, comp2); // Creates a sequence classifier containing 2 hidden Markov Models with 2 states // and an underlying multivariate mixture of Normal distributions as density. var classifier = new HiddenMarkovClassifier<Independent>( 2, new Ergodic(2), density); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning<Independent>( classifier, // Train each model until the log-likelihood changes less than 0.0001 modelIndex => new BaumWelchLearning<Independent>( classifier.Models[modelIndex]) { Tolerance = 0.0001, Iterations = 0, } ); // Train the sequence classifier using the algorithm double logLikelihood = teacher.Run(sequences, labels); return classifier; }
public void MeanTest2() { var target = new GeneralDiscreteDistribution(42, 0.1, 0.4, 0.5); double expected = 42 * 0.1 + 43 * 0.4 + 44 * 0.5; double actual = target.Mean; Assert.AreEqual(expected, actual); }
public static HiddenMarkovClassifier<Independent> CreateModel3(out double[][][] sequences2, out int[] labels2) { sequences2 = new double[][][] { new double[][] { // This is the first sequence with label = 0 new double[] { 1, 1.12, 2.41, 1.17, 9.3 }, new double[] { 1, 2.54, 1.45, 0.16, 4.5 }, new double[] { 1, 3.46, 2.63, 1.15, 9.2 }, new double[] { 1, 4.73, 0.41, 1.54, 5.5 }, new double[] { 2, 5.81, 2.42, 1.13, 9.1 }, }, new double[][] { // This is the first sequence with label = 0 new double[] { 0, 1.49, 2.48, 1.18, 9.37 }, new double[] { 1, 2.18, 1.44, 2.19, 1.56 }, new double[] { 1, 3.77, 2.62, 1.10, 9.25 }, new double[] { 2, 4.76, 5.44, 3.58, 5.54 }, new double[] { 2, 5.85, 2.46, 1.16, 5.13 }, new double[] { 2, 4.84, 5.44, 3.54, 5.52 }, new double[] { 2, 5.83, 3.41, 1.22, 5.11 }, }, new double[][] { // This is the first sequence with label = 0 new double[] { 2, 1.11, 2.41, 1.12, 2.31 }, new double[] { 1, 2.52, 3.73, 0.12, 4.50 }, new double[] { 1, 3.43, 2.61, 1.24, 9.29 }, new double[] { 1, 4.74, 2.42, 2.55, 6.57 }, new double[] { 2, 5.85, 2.43, 1.16, 9.16 }, }, new double[][] { // This is the second sequence with label = 1 new double[] { 0, 1.26, 5.44, 1.56, 9.55 }, new double[] { 2, 2.67, 5.45, 4.27, 1.54 }, new double[] { 1, 1.28, 3.46, 2.18, 4.13 }, new double[] { 1, 5.89, 2.57, 1.79, 5.02 }, new double[] { 0, 1.40, 2.48, 2.10, 6.41 }, }, new double[][] { // This is the second sequence with label = 1 new double[] { 2, 3.21, 2.49, 1.54, 9.17 }, new double[] { 2, 2.62, 5.40, 4.25, 1.54 }, new double[] { 1, 1.53, 6.49, 2.17, 4.52 }, new double[] { 1, 2.84, 2.58, 1.73, 6.04 }, new double[] { 1, 1.45, 2.47, 2.28, 5.42 }, new double[] { 1, 1.46, 2.46, 2.35, 5.41 }, }, new double[][] { // This is the second sequence with label = 1 new double[] { 1, 5.27, 5.45, 1.4, 9.5 }, new double[] { 2, 2.68, 2.54, 3.2, 2.2 }, new double[] { 1, 2.89, 3.83, 2.6, 4.1 }, new double[] { 1, 1.80, 1.32, 1.2, 4.2 }, new double[] { 0, 1.41, 2.41, 2.1, 6.4 }, } }; labels2 = new[] { 0, 0, 0, 1, 1, 1 }; // Create a Continuous density Hidden Markov Model Sequence Classifier // to detect a multivariate sequence and the same sequence backwards. var comp1 = new GeneralDiscreteDistribution(3); var comp2 = new NormalDistribution(1); var comp3 = new NormalDistribution(2); var comp4 = new NormalDistribution(3); var comp5 = new NormalDistribution(4); var density = new Independent(comp1, comp2, comp3, comp4, comp5); // Creates a sequence classifier containing 2 hidden Markov Models with 2 states // and an underlying multivariate mixture of Normal distributions as density. var classifier = new HiddenMarkovClassifier<Independent>( 2, new Forward(5), density); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning<Independent>( classifier, // Train each model until the log-likelihood changes less than 0.0001 modelIndex => new BaumWelchLearning<Independent>( classifier.Models[modelIndex]) { Tolerance = 0.0001, Iterations = 0, } ); // Train the sequence classifier using the algorithm double logLikelihood = teacher.Run(sequences2, labels2); return classifier; }
public void VarianceTest() { var target = new GeneralDiscreteDistribution(42, 0.1, 0.4, 0.5); double mean = target.Mean; double expected = ((42 - mean) * (42 - mean) * 0.1 + (43 - mean) * (43 - mean) * 0.4 + (44 - mean) * (44 - mean) * 0.5); Assert.AreEqual(expected, target.Variance); }
public static HiddenMarkovClassifier<Independent> CreateModel3() { // Create a Continuous density Hidden Markov Model Sequence Classifier // to detect a multivariate sequence and the same sequence backwards. var comp1 = new GeneralDiscreteDistribution(3); var comp2 = new NormalDistribution(1); var comp3 = new NormalDistribution(2); var comp4 = new NormalDistribution(3); var comp5 = new NormalDistribution(4); var density = new Independent(comp1, comp2, comp3, comp4, comp5); // Creates a sequence classifier containing 2 hidden Markov Models with 2 states // and an underlying multivariate mixture of Normal distributions as density. var classifier = new HiddenMarkovClassifier<Independent>( 2, new Forward(5), density); // Configure the learning algorithms to train the sequence classifier var teacher = new HiddenMarkovClassifierLearning<Independent>( classifier, // Train each model until the log-likelihood changes less than 0.0001 modelIndex => new BaumWelchLearning<Independent>( classifier.Models[modelIndex]) { Tolerance = 0.0001, Iterations = 0, } ); // Train the sequence classifier using the algorithm double logLikelihood = teacher.Run(sequences2, labels2); return classifier; }
public void MedianTest() { var target = new GeneralDiscreteDistribution(0.1, 0.4, 0.5); Assert.AreEqual(target.Median, target.InverseDistributionFunction(0.5)); }
public void FitTest3() { GeneralDiscreteDistribution target = new GeneralDiscreteDistribution(-1, 4); double[] values = { 0.00, 1.00, 2.00, 3.00 }; double[] weights = { 0.25, 0.25, 0.25, 0.25 }; target.Fit(values.Subtract(1), weights); double[] expected = { 0.25, 0.25, 0.25, 0.25 }; double[] actual = target.Frequencies; Assert.IsTrue(Matrix.IsEqual(expected, actual)); }
public void FitTest_vector_inputs() { double[] expected = { 0.50, 0.00, 0.25, 0.25 }; GeneralDiscreteDistribution target; double[] values = { 0.00, 2.00, 3.00 }; double[] weights = { 0.50, 0.25, 0.25 }; target = new GeneralDiscreteDistribution(4); target.Fit(values, weights); double[] actual = target.Frequencies; Assert.IsTrue(Matrix.IsEqual(expected, actual)); // -- double[][] values2 = { new[] { 1.00, 0.00, 0.00, 0.00 }, new[] { 0.00, 0.00, 0.00, 0.00 }, new[] { 0.00, 0.00, 1.00, 0.00 }, new[] { 0.00, 0.00, 0.00, 1.00 }, }; double[] weights2 = { 0.50, 0.00, 0.25, 0.25 }; target = new GeneralDiscreteDistribution(4); target.Fit(values2, weights2); double[] actual2 = target.Frequencies; Assert.IsTrue(Matrix.IsEqual(expected, actual2)); double[][] values3 = { new[] { 1.00, 0.00, 0.00, 0.00 }, new[] { 0.00, 1.00, 0.00, 0.00 }, new[] { 0.00, 0.00, 1.00, 0.00 }, new[] { 0.00, 0.00, 0.00, 1.00 }, }; double[] weights3 = { 0.50, 0.00, 0.25, 0.25 }; target = new GeneralDiscreteDistribution(4); target.Fit(values3, weights3); double[] actual3 = target.Frequencies; Assert.IsTrue(Matrix.IsEqual(expected, actual3)); double[][] values4 = { new[] { 0.50, 0.00, 0.00, 0.00 }, new[] { 0.00, 0.00, 0.00, 0.00 }, new[] { 0.00, 0.00, 0.25, 0.00 }, new[] { 0.00, 0.00, 0.00, 0.25 }, }; target = new GeneralDiscreteDistribution(4); target.Fit(values4); double[] actual4 = target.Frequencies; Assert.IsTrue(Matrix.IsEqual(expected, actual4)); }
/// <summary> /// Converts this <see cref="HiddenMarkovModel">Discrete density Hidden Markov Model</see> /// into a <see cref="HiddenMarkovModel{TDistribution}">arbitrary density model</see>. /// </summary> public HiddenMarkovModel<GeneralDiscreteDistribution> ToContinuousModel() { var transitions = (double[,])Transitions.Clone(); var probabilities = (double[])Probabilities.Clone(); var emissions = new GeneralDiscreteDistribution[States]; for (int i = 0; i < emissions.Length; i++) emissions[i] = new GeneralDiscreteDistribution(Accord.Math.Matrix.GetRow(Emissions, i)); return new HiddenMarkovModel<GeneralDiscreteDistribution>(transitions, emissions, probabilities); }