Constraining Bayesian Network using Jagged Array
-
venerdì 18 maggio 2012 03:18
Hi, all~Rookie trying to mess with inference here……
I was trying to express that a[0]=a[1]&a[2]&a[3], a[1] == a[4], each has a Bernoulli prior of 0.5. I want to see what happens if a[0] is observed to be false.
But the mighty engine says that this model has zero probability. I notice that if I use something like using(Variable.If(b)){ var a = Variable.Bernoulli(0.99999);} would be a work around, but I don't know how……
using System;
using System.Collections.Generic;
using System.Text;
using MicrosoftResearch.Infer.Models;
using MicrosoftResearch.Infer;
using MicrosoftResearch.Infer.Distributions;
using MicrosoftResearch.Infer.Maths;
using PruneDynamicSlicing.Dependency.Interface;
using PruneDynamicSlicing.Dependency.Implementation;
using System.Collections;
namespace ProbInfer
{
class ProbInfer
{
static void Main(string[] args)
{
Variable<int> size = Variable.New<int>();
VariableArray<bool> array = Variable.Array<bool>(new Range(size));
size.ObservedValue = 5;
int[][] parents = new int[5][] { new int[] { 1, 2, 3 }, new int[] { 4 }, new int[] { }, new int[] { }, new int[] { } };
int[] index = new int[] { 3, 1, 0, 0, 0 };
Variable<int> outersize = Variable.New<int>();
Range outer = new Range(outersize);
VariableArray<int> innersize = Variable.Array<int>(outer);
Range inner = new Range(innersize[outer]);
outersize.ObservedValue = size.ObservedValue;
innersize.ObservedValue = index;
VariableArray<VariableArray<int>, int[][]> parentsArray = Variable.Array(Variable.Array<int>(inner), outer);
using (Variable.ForEach(outer))
{
using (Variable.ForEach(inner))
{
parentsArray[outer][inner] = Variable.New<int>();
}
}
parentsArray.ObservedValue = parents;
using (Variable.ForEach(array.Range)) { array[array.Range] = Variable.Bernoulli(0.5); }
using (ForEachBlock block = Variable.ForEach(outer))
{
VariableArray<bool> probs = Variable.Subarray<bool>(array, parentsArray[outer]);
Variable<bool> allTrue = Variable.AllTrue(probs);
Variable.ConstrainEqual(array[block.Index], allTrue);
}
Variable.ConstrainFalse(array[0]);
InferenceEngine engine = new InferenceEngine();
Console.WriteLine(engine.Infer(array));
return;}}}
Thanks a lot.
Tutte le risposte
-
venerdì 18 maggio 2012 12:01
For an array of length zero, AllTrue returns true. Thus your model is effectively constraining all variables to be true. You need to eliminate some of these constraints. By the way, this code is redundant:
using (Variable.ForEach(outer)) { using (Variable.ForEach(inner)) { parentsArray[outer][inner] = Variable.New<int>(); } }
Once you create a VariableArray, all elements are already created (they are just not given any distribution).- Modificato Tom MinkaMicrosoft Employee venerdì 18 maggio 2012 12:21
- Contrassegnato come risposta Rex Xia sabato 19 maggio 2012 11:43
-
venerdì 18 maggio 2012 12:10
Hi Rex,
Look carefully at your ForEachBlock. You iterate over the Range "outer", the size of which is 5. The first two iterations do exactly what you want. However, the third iteration constrains array[2] to AllTrue of an empty array, which is 1.0! The fourth and fifth iterations of the block do the same with array[3] and array[4]. And since array[1] is constrained to be equal to array[4], it is also inferred as Bernoulli(1). Now, when you do Variable.ConstrainFalse(array[0]), you actually say:
false = array[0] = array[1] & array[2] & array[3] = true & true & true = true <!>
I think what you actually want is to loop only twice here. For example:Range i = new Range(2); using (ForEachBlock block = Variable.ForEach(i)) { VariableArray<bool> probs = Variable.Subarray<bool>(array, parentsArray[block.Index]); Variable<bool> allTrue = Variable.AllTrue(probs); Variable.ConstrainEqual(array[block.Index], allTrue); }
Thanks,
Yordan- Contrassegnato come risposta Rex Xia sabato 19 maggio 2012 11:43
-
sabato 19 maggio 2012 05:32
Hi Yordan,
Thank you very much for your reply. I was wondering what this code would look like if I do not have the information about the array length?
What if I have no idea the length of each variable's dependency? I used this code to build a constraint network based on a text input. Should I still use Variable.AllTrue?
Best,
Rex
-
sabato 19 maggio 2012 05:50
Thanks Tom, I think I know why this constraint has glitch.
using (ForEachBlock block = Variable.ForEach(outer)) { using (Variable.IfNot(parentsArray[outer].Range.Size.Equals(0))) { VariableArray<bool> probs = Variable.Subarray<bool>(array, parentsArray[outer]); Variable<bool> allTrue = Variable.AllTrue(probs); Variable.ConstrainEqual(array[block.Index], allTrue); } }I modified this part but still have the same error message ...
-
sabato 19 maggio 2012 05:52
Hi Yordan,
I tried to modify the part but still messed up, the result says still zero probability...
using (ForEachBlock block = Variable.ForEach(outer)) { using (Variable.IfNot(parentsArray[outer].Range.Size.Equals(0))) { VariableArray<bool> probs = Variable.Subarray<bool>(array, parentsArray[outer]); Variable<bool> allTrue = Variable.AllTrue(probs); Variable.ConstrainEqual(array[block.Index], allTrue); } }Something wrong with my assertion of a non-zero length dependency?
Best,
Rex
-
sabato 19 maggio 2012 09:54
The Equals method is not overloaded by Infer.NET so it does not work in model expressions. Your idea will work if you say: using(Variable.IfNot(innersize[outer] == 0))
- Contrassegnato come risposta Rex Xia sabato 19 maggio 2012 11:42