Skip to main content

Infer.NET user guide : The Infer.NET Modelling API

Computing derivatives of functions

The commonly used distributions like Gaussian and Gamma provide a GetDerivatives method that returns the derivative of the log-density at any point. When you infer the marginal distribution of a variable, you are getting an approximation to the posterior. Applying GetDerivatives to the posterior gives the derivative of the log-likelihood plus the derivative of the log-prior. To get the derivative of the log-likelihood at a point, you can in principle make the prior narrow around that point, compute the derivative of the log-posterior, and subtract the derivative of the log-prior. In practice, that approach suffers from large round-off errors.

A better approach is to ask for MarginalDividedByPrior, which excludes the prior automatically. That way the prior can be a point mass, and the derivative is exact.

This technique is illustrated in the example below. The example uses Variable.ConstrainEqualRandom to increment the log density by the expression whose derivative we want to take.

// Compute the derivative of the function log(x) at the point x = 0.5
Variable<double> xPoint = Variable.Observed(0.5);
Variable<double> x = Variable.GammaFromMeanAndVariance(xPoint, 0.0);
x.AddAttribute(QueryTypes.MarginalDividedByPrior);
Variable<double> f = Variable.Log(x);
Variable.ConstrainEqualRandom(f, Gaussian.FromNatural(1, 0)); // increment the log density by f

InferenceEngine engine = new InferenceEngine();
var xPost = engine.Infer<Gaussian>(x, QueryTypes.MarginalDividedByPrior);
xPost.GetDerivatives(xPoint.ObservedValue, out double derivative, out _);
// derivative is 1 / xPoint

To compute the derivative at a different point, change xPoint.ObservedValue and call engine.Infer again. Here is another example, using a Gaussian-distributed x and a Gamma-distributed f:

// Compute the derivative of the function exp(x) at the point x = 0.5
Variable<double> xPoint = Variable.Observed(0.5);
Variable<double> x = Variable.GaussianFromMeanAndVariance(xPoint, 0.0);
x.AddAttribute(QueryTypes.MarginalDividedByPrior);
Variable<double> f = Variable.Exp(x);
Variable.ConstrainEqualRandom(f, Gamma.FromNatural(0, -1)); // increment the log density by f

InferenceEngine engine = new InferenceEngine();
var xPost = engine.Infer<Gaussian>(x, QueryTypes.MarginalDividedByPrior);
xPost.GetDerivatives(xPoint.ObservedValue, out double derivative, out _);
// derivative is exp(xPoint)