How to use a precompiled inference algorithm when you want to sequentially update the posteriors? (Migrated from community.research.microsoft.com)
-
Friday, June 03, 2011 6:47 PMOwner
shengbo posted on 04-28-2011 9:51 AM
Hi Team,
Thanks for providing the examples of using a precompiled inference algorithm, such as:
and example 2: http://research.microsoft.com/en-us/um/cambridge/projects/infernet/docs/Controlling%20how%20inference%20is%20performed.aspx
In some cases, one may wants to use the precompiled inference algorithm on different chunks of one dataset. let say there are two chunks, A and B. Suppose we have run the algorithm on chunk A, and get the posteriors for model parameters. Could the posteriors be fed to the algorithm when running the algorithm in chunk B?
I have seen the use of SharedVariable for similar purposes, however, it is unclear how to use SharedVariable in the case of using a precompile algorithm. Any suggestions and pointers would be appreciated.
Thanks and regards,
Shengbo
All Replies
-
Friday, June 03, 2011 6:47 PMOwner
John Guiver replied on 05-03-2011 10:37 AM
Hi Shengbo
You will need to implement the shared variable pattern explicitly rather than use the shared variable wrapper classes. The general pattern for shared variables is described in http://research.microsoft.com/en-us/um/cambridge/projects/infernet/docs/Sharing%20variables%20between%20models.aspx. To paraphrase:
- Run inference to convergence on one of the sub-models, say model/chunk A
- Extract the shared variable messages output from model/chunk A
- Initialise the next model, model/chunk B, say, by providing as input a product of all the output messages from all models/chunks except B (along with the prior)
Note that you want the output message rather than the marginal from the compiled algorithm (at least if you are running Expectation Propagation); to generate code for this output message, you need to set an Output attribute on the shared variable in your original code (see http://research.microsoft.com/en-us/um/cambridge/projects/infernet/docs/Adding%20attributes%20to%20your%20model.aspx).
There are several tricky aspects to this which govern how you should define your model. I think the first thing would be to understand how a simple scalar example works. I give code for a learning a Gaussian example below. Note that I am not using precompiled code in this example - its only purpose is to show you the shared variable pattern. The extension from scalar to array follows exactly the same pattern but is a bit more tricky syntactically; I can help you there in a follow-up post if necessary, depending on your needs.
John
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MicrosoftResearch.Infer.Models;
using MicrosoftResearch.Infer.Distributions;
using MicrosoftResearch.Infer;
namespace sharedvar_with_precompiled
{
class Program
{
static void Main(string[] args)
{
var numData = Variable.New<int>();
Range n = new Range(numData);
var input = Variable.New<Gaussian>();
var a = Variable.Random<double, Gaussian>(input).Attrib(new Output());
var d = Variable.Array<double>(n);
d[n] = Variable.GaussianFromMeanAndPrecision(a, 1.0).ForEach(n);
var engine = new InferenceEngine();
// Prior
var Prior = Gaussian.FromMeanAndPrecision(0.1, 0.2);
// Data chunks
double [][] data = new double[][]
{
new double[] {1.0, 2.0, 3.0},
new double[] {1.5, 2.5},
new double[] {2.1, 2.2, 2.3}
};
int numChunks = data.Length;
// Start with uniform output messages
Gaussian[] outputs = new Gaussian[numChunks];
for (int i = 0; i < numChunks; i++) outputs[i] = Gaussian.Uniform();
int numPasses = 2;
for (int p = 0; p < numPasses; p++)
{
for (int i = 0; i < numChunks; i++)
{
// Multiply the prior with all output messages from other chunks
Gaussian inputValue = (Gaussian)Prior.Clone();
inputValue = Distribution.SetToProductWithAllExcept(inputValue, outputs, i);
input.ObservedValue = inputValue;
d.ObservedValue = data[i];
numData.ObservedValue = data[i].Length;
if (engine.Algorithm is ExpectationPropagation)
outputs[i] = engine.GetOutputMessage<Gaussian>(a);
else
{
outputs[i] = engine.Infer<Gaussian>(a);
outputs[i].SetToRatio(outputs[i], inputValue);
}
}
}
Console.WriteLine("Posterior = {0}", engine.Infer<Gaussian>(a));
}
}
}
- Marked As Answer by Microsoft ResearchOwner Friday, June 03, 2011 6:47 PM