locked
Learning a Discrete distribution RRS feed

  • Question

  • Hi everyone, I am trying to learn a discrete distribution modifying the tutorial example LearningAGaussianWithRanges (Efficient Bayesian learning of the mean and precision of some data using ranges). This because I would like to exploit the learned discrete distribution to generate new samples.

    The result I got back from the inference engine seems wrong to me and I am not able to figure out the reason.

    Suppose we have 100 categories/classes for the discrete distribution that has to be learned. Moreover we have an initial training set of few (50) examples that we can exploit to initialise the discrete distributions.

    public Variable<int> category;
    public VariableArray<int> x;
    int nCategory = 100;

    So, here the (straightforward) pgm I wrote to learn the discrete distribution. In 'data' is stored the training set which contains int numbers in [0,99].

    In particular I adopted the following one: [10, 5, 20, 10, 10, 5, 20,  10, 5, 30, 10, 5, 20, 10, 10, 5, 20,  10, 5, 30, 10, 5, 20, 10, 10, 5, 20,  10, 5, 30, 10, 5, 20, 10, 10, 5, 20,  10, 5, 30, 10, 5, 20, 10, 10, 5, 20,  10, 5, 30 ].

    //pre-processing

    double[] probs = new double[nCategory]; for (int i = 0; i < nCategory; i++) probs[i] = 0; for (int i = 0; i < data.Length; i++) probs[data[i]]++; Vector probsVec = Vector.FromArray(probs) + 0.000001; Vector normalizer = Vector.Zero(nCategory); normaliser.SetAllElementsTo(probsVec.Sum()); probsVec = probsVec / normaliser; // model category = Variable.Discrete(probsVec).Named("category"); Range dataRange = new Range(data.Length).Named("n"); VariableArray<int> x = Variable.Array<int>(dataRange).Named("x"); x[dataRange] = Variable.DiscreteUniform(category).ForEach(dataRange); x.ObservedValue = data;


    As you can see I initialized 'category' using the probabilities obtained from the training data.

    Finally, I run the inference engine and I sample  from the learned distribution.

    Discrete out = engine.Infer<Discrete>(category);

    int sample = (int) out.Sample();


    In any case I the mean/expected value for the learned distribution is 31 or 32 instead of 10.

    Can anyone give me a hint?

    Cheers,

    Diego 


    • Edited by dtosato Tuesday, May 22, 2012 3:57 PM
    Tuesday, May 22, 2012 10:23 AM

Answers

  • Hi Diego,
     
    If you look more closely at the Learning a Gaussian example, you'll notice that there we are trying to learn the parameters that define the Gaussian. In order to perform inference, we need a prior on each parameter that we want to learn. The situation here is the same. We want to learn a Discrete (which is a distribution over integers), and the parameter of such a distribution is a probability vector. The prior for a probability vector is a Dirichlet distribution. So, if you want to learn a Discrete, in your model you'd have a Variable<Vector> with a Dirichlet prior, rather than a Variable<int> with a Discrete prior.
     
    Here is the code I'd propose for your example:


                int[] data = new int[] { 10, 5, 20, 10, 10, 5, 20,  10, 5, 30, 10, 5, 20, 10, 10, 5, 20, 10, 5, 30, 10, 5, 20, 10, 10, 5, 20,  10, 5, 30, 10, 5, 20, 10, 10, 5, 20,  10, 5, 30, 10, 5, 20, 10, 10, 5, 20,  10, 5, 30 };
    
                Range r = new Range(data.Length);
                Variable<Vector> prob = Variable.Dirichlet(Util.ArrayInit(data.Length, i => 0.02));
                VariableArray<int> x = Variable.Array<int>(r);
    
                x[r] = Variable.Discrete(prob).ForEach(r);
                x.ObservedValue = data;
    
                InferenceEngine engine = new InferenceEngine();
                Dirichlet probPosterior = engine.Infer<Dirichlet>(prob);
                Vector posteriorMean = probPosterior.GetMean();
    
                Console.WriteLine(new Discrete(posteriorMean).Sample());

    One thing that is not quite clear here is what you want to use the model for. Do you want to maintain the uncertainty in the parameter? I simply printed a sample, as you did in your code.

    Thanks,
    Yordan
    • Marked as answer by dtosato Wednesday, May 23, 2012 2:27 PM
    Tuesday, May 22, 2012 4:38 PM

All replies

  • Hi Diego,
     
    If you look more closely at the Learning a Gaussian example, you'll notice that there we are trying to learn the parameters that define the Gaussian. In order to perform inference, we need a prior on each parameter that we want to learn. The situation here is the same. We want to learn a Discrete (which is a distribution over integers), and the parameter of such a distribution is a probability vector. The prior for a probability vector is a Dirichlet distribution. So, if you want to learn a Discrete, in your model you'd have a Variable<Vector> with a Dirichlet prior, rather than a Variable<int> with a Discrete prior.
     
    Here is the code I'd propose for your example:


                int[] data = new int[] { 10, 5, 20, 10, 10, 5, 20,  10, 5, 30, 10, 5, 20, 10, 10, 5, 20, 10, 5, 30, 10, 5, 20, 10, 10, 5, 20,  10, 5, 30, 10, 5, 20, 10, 10, 5, 20,  10, 5, 30, 10, 5, 20, 10, 10, 5, 20,  10, 5, 30 };
    
                Range r = new Range(data.Length);
                Variable<Vector> prob = Variable.Dirichlet(Util.ArrayInit(data.Length, i => 0.02));
                VariableArray<int> x = Variable.Array<int>(r);
    
                x[r] = Variable.Discrete(prob).ForEach(r);
                x.ObservedValue = data;
    
                InferenceEngine engine = new InferenceEngine();
                Dirichlet probPosterior = engine.Infer<Dirichlet>(prob);
                Vector posteriorMean = probPosterior.GetMean();
    
                Console.WriteLine(new Discrete(posteriorMean).Sample());

    One thing that is not quite clear here is what you want to use the model for. Do you want to maintain the uncertainty in the parameter? I simply printed a sample, as you did in your code.

    Thanks,
    Yordan
    • Marked as answer by dtosato Wednesday, May 23, 2012 2:27 PM
    Tuesday, May 22, 2012 4:38 PM
  • Many thanks Yordan. I am trying to to build a simple pgm to produce new values or "hypothesis" given a set of discrete observations. I am aware that at the state-of-the-art kalman filters, particle filters, etc. can do that, but it is not easy to me to implement properly those methods using infer.NET. This because I have just started to implement machine learning models using this framework.

    You probably could tell me that it is not the posterior probability what I should to estimate. In fact, form a Bayesian point of view, I should use the likelihood probability distribution. However, it is not completely clear how to use infer.NET to compute the likelihood of a pgm. 



    Thanks,

    Diego

    Wednesday, May 23, 2012 2:27 PM