locked
How to only compile once and work for both variable being observed and unobserved cases? RRS feed

  • Question

  • I have a model in which I am interested in the marginal distribution of certain variables. This model has N leaf variables, n of which will be observed. n changes from time to time. So currently, for each n, Infer.Net has to compile once.

    Is there a way that Infer.Net only compiles once for all n? Below is a minimum example:

        class InferNetTest
        {
            Variable<double> _x = Variable.GaussianFromMeanAndVariance(0, 2);
            Variable<double> _y;
            Variable<double> _z;
            Variable<Gaussian> _a = Variable.New<Gaussian>();
            InferenceEngine _engine = new InferenceEngine();

            public InferNetTest()
            {
                _y = Variable.GaussianFromMeanAndVariance(_x, 3);
                _z = Variable<double>.Random(_a);
                Variable.ConstrainEqual (_y, _z);
            }

            public void Infer()
            {
                _a.ObservedValue = Gaussian.Uniform ();
                Console.WriteLine(_engine.Infer(_x));
                _a.ObservedValue = Gaussian.PointMass (1);
                Console.WriteLine(_engine.Infer(_x));

    }

    In the above case, _x has a Gaussian prior distribution, and _y has a Gaussian distribution conditional on _x. I would like to build a model that can infer the "posterior" distribution of _x, and try to reuse the model whether _y is observed or not.

    Here, if _y is not observed, _x is just N(0, 2). But if _y is observed to be 1, then the posterior _x is N(0.4, 1.2).

    The trick I tried, is to add another variable _z that has prior _a, and enforce _z equal to _y. Thus, when I would have observed _y, I set _a.ObservedValue as a Gaussian.PointMass @ observed value. When we would not have observed _y, I set _a.ObservedValue as Uniform.

    This way, the model is only compiled once, and I set _a.ObservedValue accordingly.

    However, when I came to the Poisson case, I struggled. 

        class InferNetTest
        {
            Variable<double> _x = Variable.GammaFromShapeAndScale(1, 2);
            Variable<int> _y;
            Variable<int> _z;
            Variable<Poisson> _a = Variable.New<Poisson>();
            InferenceEngine _engine = new InferenceEngine();
            public InferNetTest()
            {
                _y = Variable.Poisson(_x);
                _z = Variable<int>.Random(_a);
                Variable.ConstrainEqual (_y, _z);
            }

            public void Infer()
            {
                _a.ObservedValue = Poisson.Uniform ();
                Console.WriteLine(_engine.Infer(_x));
                _a.ObservedValue = Poisson.PointMass(3);;
                Console.WriteLine(_engine.Infer(_x));

    }

    Now it would fail because factor equal doesn't support poisson?  What's the best approach to achieve my needs? Also, I feel even in Gaussian case the workaround seems be a bit complex. Is there any other simple shortcut?

     
    Wednesday, October 1, 2014 2:02 PM

Answers

  • The best way to do this is with Variable.If, like so:

    var yIsObserved = Variable.New<bool>(); var yObs = Variable.Observed<int>(0); using (Variable.If(yIsObserved)) {
    _y = Variable.Poisson(_x); Variable.ConstrainEqual(_y, yObs); } yIsObserved.ObservedValue = false; Console.WriteLine(_engine.Infer(_x)); yIsObserved.ObservedValue = true; yObs.ObservedValue = 3; Console.WriteLine(_engine.Infer(_x));



    Wednesday, October 1, 2014 3:23 PM
    Owner