dotnet / infer

Infer.NET is a framework for running Bayesian inference in graphical models
https://dotnet.github.io/infer/
MIT License
1.56k stars 229 forks source link

Update a model in Infer with a new observation #401

Closed Vedrannb closed 8 months ago

Vedrannb commented 2 years ago

Is there a possibility in INFER to update the model, for example here I determined the weights, means and posteriors from the data in mixed gaussian model.

// Define a range for the number of mixture components

            Variable<int> nK = Variable.Observed(2).Named("k");

            Range k = new Range(nK);

            // Mixture component means

            var meansVector = Variable.Observed(Vector.FromArray(0.0, 0.0)).Named("Means");

            var precsMatrix = Variable.Observed(PositiveDefiniteMatrix.IdentityScaledBy(2, 0.01)).Named("Precs");

            VariableArray<Vector> means = Variable.Array<Vector>(k).Named("mean");

            using (Variable.ForEach(k))

            {

                means[k] = Variable.VectorGaussianFromMeanAndPrecision(meansVector, precsMatrix);

            }

            double scaleValue = 100;

            var scaleInt = Variable.Observed(scaleValue).Named("Scale");

            var shapeMatrix = Variable.Observed(PositiveDefiniteMatrix.IdentityScaledBy(2, 0.01)).Named("Shape");

            // Mixture component precisions

            VariableArray<PositiveDefiniteMatrix> precs = Variable.Array<PositiveDefiniteMatrix>(k).Named("prec");

            using (Variable.ForEach(k))

            {

                precs[k] = Variable.WishartFromShapeAndScale(scaleInt, shapeMatrix);

            }

            // Mixture weights

            Variable<Vector> weights = Variable.Dirichlet(k, new double[] { 1, 1 }).Named("weights");

            // Create a variable array which will hold the data

            Variable<int> numData = Variable.Observed(300).Named("n");

            Range n = new Range(numData);

            VariableArray<Vector> data = Variable.Array<Vector>(n).Named("x");

            // Create latent indicator variable for each data point

            VariableArray<int> z = Variable.Array<int>(n).Named("z");

            // The mixture of Gaussians model

            using (Variable.ForEach(n))

            {

                z[n] = Variable.Discrete(weights);

                using (Variable.Switch(z[n]))

                {

                    data[n] = Variable.VectorGaussianFromMeanAndPrecision(means[z[n]], precs[z[n]]);

                }

            }

            // Attach some generated data

           data.ObservedValue = GenerateData(300);

            // Initialise messages randomly to break symmetry

            VariableArray<Discrete> zInit = Variable.Array<Discrete>(n).Named("zInit");

            zInit.ObservedValue = Util.ArrayInit(300, i => Discrete.PointMass(Rand.Int(2), 2));

            z[n].InitialiseTo(zInit[n]);

            // The inference

            InferenceEngine engine = new InferenceEngine();

            engine.Algorithm = new VariationalMessagePassing();

            var weights_infer = engine.Infer(weights);

            var means_infer = engine.Infer(means);

            var precs_infer = engine.Infer(precs);
public static Vector[] GenerateData(int nData)

        {

            Vector trueM1 = Vector.FromArray(2.0, 3.0);

            Vector trueM2 = Vector.FromArray(7.0, 5.0);

            PositiveDefiniteMatrix trueP1 = new PositiveDefiniteMatrix(

                new double[,] { { 3.0, 0.2 }, { 0.2, 2.0 } });

            PositiveDefiniteMatrix trueP2 = new PositiveDefiniteMatrix(

                new double[,] { { 2.0, 0.4 }, { 0.4, 4.0 } });

            VectorGaussian trueVG1 = VectorGaussian.FromMeanAndPrecision(trueM1, trueP1);

            VectorGaussian trueVG2 = VectorGaussian.FromMeanAndPrecision(trueM2, trueP2);

            double truePi = 0.6;

            Bernoulli trueB = new Bernoulli(truePi);

            // Restart the infer.NET random number generator

            Rand.Restart(12347);

            Vector[] data = new Vector[nData];

            for (int j = 0; j < nData; j++)

            {

                bool bSamp = trueB.Sample();

                data[j] = bSamp ? trueVG1.Sample() : trueVG2.Sample();

            }

            return data;

        }

Can I now enter a new data point (only one datapoint) in the model with the new inferred mean, precision and weights, and get completely new posteriors?

tminka commented 2 years ago

Yes, see Online learning.