Infer.NET user guide : The Infer.NET Modelling API
Creating variables
The modelling API allows you to create variables with three types of usage:
- random: variables whose values are unknown and whose posterior distributions can be calculated during inference.
- constant: variables whose values are known and fixed when the model is constructed.
- observed: variables whose values not specified when the model is constructed, but are given before performing inference. This allows the same model to be used again and again with different observed values, such as different data sets or different priors.
All these types of usage share the same generic .NET type Variable<T>, where T is the underlying type of the variable. By default, a Variable is random, but it can be observed by specifying an ObservedValue, and it can be made constant by means of the IsReadOnly property. Almost all model constructs make use of static constructor methods on the untyped Variable class, including methods to create constant or observed variables directly from their data.
Creating new random variables
One way to create random variables is to specify a prior distribution for them (you can also create random variables as functions of other random variables). There are static methods on the Variable class for creating variables with many common prior distributions, such as Gaussian, Gamma, Dirichlet, Beta, Bernoulli, Discrete etc. (see Distribution Factors for a full list, and see Variable types and their distributions for the relationship between variables and distributions). For example, the following lines create a double random variable with a Gaussian prior of zero mean and unit variance, and a boolean random variable with a Bernoulli prior:
Variable<double> x = Variable.GaussianFromMeanAndVariance(0, 1);
Variable<bool> b = Variable.Bernoulli(0.5);
Notice that the variables are strongly typed, for example x has type Variable<double>
. All modelling elements are strongly typed, so that models are guaranteed to be type safe. This allows many errors to be caught at compile-time rather than run time.
Whilst there are built-in methods for the distributions that come with Infer.NET, you can also create random variables with any prior distribution using the Random() method:
Variable<double> y = Variable.Random(new MyDistributionClass());
where MyDistributionClass is any distribution class, including built-in ones. For example, an equivalent way of creating the Gaussian distributed random variable x defined above is:
Variable<double> x = Variable.Random(Gaussian.FromMeanAndVariance(0, 1));
It is also possible to create 1D arrays and 2D rectangular arrays of random variables (see working with arrays and ranges) as well as jagged arrays of random variables (see jagged arrays).
It is often convenient for debugging purposes to name your variables (otherwise they will be given unique but unhelpful names like ‘v13’ in the code generated by the model compiler). This can be achieved by setting the Name property of the variable or using the inline Named() method:
Variable<bool> b = Variable.Bernoulli(0.5).Named("b");
Creating constants
It is also possible to just pass in ordinary .NET values when you want to have a constant value in your model. For example, to create a Gaussian variable whose mean is given by a random variable x and whose precision is constant at 1.0, you can write:
Variable<double> z = Variable.GaussianFromMeanAndPrecision(x, 1.0);
It is also possible to create constants manually using the syntax:
Variable<double> one = Variable.Constant(1.0);
However, there is an implicit conversion from any type to a constant variable of that type. So you can also write:
Variable<double> one = 1.0;
Once a constant has been created, its value cannot be changed (it is immutable). The Constant constructor sets the ObservedValue of the variable to be the specified constant, and sets the IsReadOnly property of the variable to be true. So an equivalent way of writing the previous snippet is:
Variable<double> one = Variable.New<double>();
one.ObservedValue = 1;
one.IsReadOnly = true;
Constants can be used as arguments to most Modelling API methods. For example, the above variable z could also have been defined using:
Variable<double> z = Variable.GaussianFromMeanAndPrecision(x, Variable.Constant(1.0));
Because of the implicit conversion to a constant described above, you can also write this in the much more natural way that we just saw, i.e.:
Variable<double> z = Variable.GaussianFromMeanAndPrecision(x, 1.0);
It is also possible to create constant arrays and constant jagged arrays.
Except for simple cases as above, it is better practice to use observed variables rather than constant variables, as discussed in the next section.
Observed values
Often you want to use the same model multiple times with different settings or with different data. Rather than define variables to be constant (which are then compiled into the model), it is much more efficient to allow the observed value of a variable to be set prior to running the inference. For example:
Variable<int> size = Variable.New<int>().Named("size");
creates an integer variable called “size”. The value of the variable can then be set using
size.ObservedValue = 10;
The only difference from defining a constant is that the IsReadOnly property is set to false. The model compiler then knows that this variable may be changed at run-time and generates code that allows the variable’s observed value to be changed. So after performing inference with size set to 10, you can later set it to another value e.g.
size.ObservedValue = 15;
You can also directly specify an initial value for the observed value in the constructor. The following line is equivalent to the first two lines above,
Variable<int> size = Variable.Observed(10).Named("size");
Variables which are observed can be used as arguments to most modelling API methods. For example, you can make a variable whose Gaussian prior is an observed variable:
Variable<Gaussian> priorOnX = Variable.New<Gaussian>();
Variable<double> x = Variable<double>.Random(priorOnX);
The value of priorOnX must be specified before performing inference, or an exception will be thrown. For example:
priorOnX.ObservedValue = Gaussian.FromMeanAndPrecision(1.0, 2.0);
It is also possible to specify observed values for arrays and jagged arrays.