예제 #1
0
파일: Program.cs 프로젝트: zetaby/infer-hmm
        /// <summary>
        /// Tests the hidden markov model.
        /// </summary>
        static void TestHiddenMarkovModel()
        {
            // fix random seed
            Rand.Restart(12347);

            // model size
            int T = 100;
            int K = 2;

            // set hyperparameters
            Dirichlet ProbInitPriorObs = Dirichlet.Uniform(K);

            Dirichlet[] CPTTransPriorObs = Enumerable.Repeat(Dirichlet.Uniform(K), K).ToArray();
            Gaussian[]  EmitMeanPriorObs = Enumerable.Repeat(Gaussian.FromMeanAndVariance(0, 1000), K).ToArray();
            Gamma[]     EmitPrecPriorObs = Enumerable.Repeat(Gamma.FromShapeAndScale(1000, 0.001), K).ToArray();

            // sample model parameters
            double[]   init  = ProbInitPriorObs.Sample().ToArray();
            double[][] trans = new double[K][];
            for (int i = 0; i < K; i++)
            {
                trans[i] = CPTTransPriorObs[i].Sample().ToArray();
            }
            double[] emitMeans = new double[K];
            for (int i = 0; i < K; i++)
            {
                emitMeans[i] = EmitMeanPriorObs[i].Sample();
            }
            double[] emitPrecs = new double[K];
            for (int i = 0; i < K; i++)
            {
                emitPrecs[i] = EmitPrecPriorObs[i].Sample();
            }

            // print parameters
            HiddenMarkovModel modelForPrinting = new HiddenMarkovModel(T, K);

            modelForPrinting.SetParameters(init, trans, emitMeans, emitPrecs);
            Console.WriteLine("parameters:");
            modelForPrinting.PrintParameters();
            Console.WriteLine();

            // create distributions for sampling
            Discrete initDist = new Discrete(init);

            Discrete[] transDist = new Discrete[K];
            for (int i = 0; i < K; i++)
            {
                transDist[i] = new Discrete(trans[i]);
            }
            Gaussian[] emitDist = new Gaussian[K];
            for (int i = 0; i < K; i++)
            {
                emitDist[i] = Gaussian.FromMeanAndPrecision(emitMeans[i], emitPrecs[i]);
            }

            // calculate order of actual states
            int[] actualStateOrder = argSort(emitDist);
            Console.WriteLine("actualStateOrder");
            Console.WriteLine(string.Join(",", actualStateOrder));
            Console.WriteLine();

            // sample state and emission data
            int[]    actualStates = new int[T];
            double[] emissions    = new double[T];
            actualStates[0] = initDist.Sample();
            emissions[0]    = emitDist[actualStates[0]].Sample();
            for (int i = 1; i < T; i++)
            {
                actualStates[i] = transDist[actualStates[i - 1]].Sample();
                emissions[i]    = emitDist[actualStates[i]].Sample();
            }
            Console.WriteLine("sample data:");
            Console.WriteLine(string.Join(",", actualStates));
            Console.WriteLine();

            // infer model parameters, states and model evidence given priors and emission data
            HiddenMarkovModel model = new HiddenMarkovModel(T, K);

            model.SetPriors(ProbInitPriorObs, CPTTransPriorObs, EmitMeanPriorObs, EmitPrecPriorObs);
            model.ObserveData(emissions);
            model.InitialiseStatesRandomly();
            model.InferPosteriors();
            Console.WriteLine("model likelihood: " + model.ModelEvidencePosterior);
            Discrete[] mapStatesDistr = model.StatesPosterior;
            int[]      mapStates      = mapStatesDistr.Select(s => s.GetMode()).ToArray();
            Console.WriteLine();

            // print maximum a priori states
            Console.WriteLine("statesMAP");
            Console.WriteLine(string.Join(",", mapStates));
            Console.WriteLine();

            // print posterior distributions
            Console.WriteLine("posteriors");
            model.PrintPosteriors();
            Console.WriteLine();

            // calculate order of MAP states
            int[] mapStateOrder = argSort(model.EmitMeanPosterior);
            Console.WriteLine("mapStateOrder");
            Console.WriteLine(string.Join(",", mapStateOrder));
            Console.WriteLine();

            // accuracy of MAP estimates
            int correctStates = 0;

            for (int i = 0; i < actualStates.Length; i++)
            {
                if (actualStateOrder[actualStates[i]] == mapStateOrder[mapStates[i]])
                {
                    correctStates++;
                }
            }
            Console.WriteLine("correctStates: " + correctStates + " / " + actualStates.Length);
            Console.WriteLine();

            Console.WriteLine("------------------\n");
        }