# Learning a Discrete distribution • ### 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-processingdouble[] 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 Tuesday, May 22, 2012 3:57 PM
Tuesday, May 22, 2012 10:23 AM

• 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 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 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