locked
A Better Way to Create an Array of Constant Bernoulli Distr.? (Migrated from community.research.microsoft.com) RRS feed

  • Question

  • nbeckman posted on 07-02-2010 1:02 PM

    Hi,

    Looks like I've been asking a lot of questions here recently! Sorry for my ignorance, but I really appreciate the help and the hard work the Infer.NET team has done. 

     

    Sadly, I am getting to a point where my models are so large that they are causing issues at run-time. I am wondering if there is a more efficient way to do what I am doing (and from analyzing the generated code, it appears that there should be). 

     

    Here is a simplified notion of what I am doing: Basically, I have a bunch of very large arrays of boolean random variables. My arrays are something on the order of 80,000 variables large. Then I take sub-arrays from the large arrays, and say that certain sub-arrays both must be true (logical AND), and importantly, that they both must be true with some high probability. So my code looks something like this:

     

    let main_array:VariableArray<bool> = ...         // comes from earlier in the program

    let likely = new Bernoulli(0.89) in                    // both sub-arrays must be true with this prob.

    let ar_1_ndxs:int[] = getArray1Ndxs() in

    let ar_2_ndxs:int[] = getArray2Ndxs() in         // size is equal to ar_1_ndxs

    let range = new Range(Array.length ar_1_ndxs) in

    let ar_1 = Variable.GetItems(main_array, Variable.Constant<int>(ar_1_ndxs,range)) in

    let ar_2 = Variable.GetItems(main_array, Variable.Constant<int>(ar_2_ndxs,range)) in

    let AND_array = Variable.Array<bool>(range) in

    let () = AND_array <- (ar_1.[range] &&& ar_2.[range]) in // We will constrain AND_array to be likely true

    let likely_constants' = Array.init (Array.length ar_1_ndxs) (fun _ -> likely) in

    let likely_constants = Variable.Constant<Bernoulli>(likely_constants', range) in // an array of 0.89 Bern. distrs.

    Variable.ConstrainEqualRandom( AND_array.[range], likely_constants.[range] )

     

    So I guess the first question would be, does this code even accomplish what I want, which is to provide a constraint that the elements of ar_1 AND ar_2 both must be true with high (89%) probability?

     

    But now the real problem is the code that this generates in Model_EP.cs. The call to ConstrainEqualRandom causes a very large array of Bernoullis to be created. In my case, the array is 15,000 elements large. But the problem is (I think) that each element of the array is a constructor call. Here is a snippet:

    this.vBernoulli__23 = new Bernoulli[15521] {new Bernoulli(0.89),new Bernoulli(0.89),new Bernoulli(0.89),.........

    In other words, even though I want the array likely_constants to be constant, Infer.NET is creating a new object for each element. That doesn't seem so bad per-say, but for some reason this array is so big that if I try to run the Model_EP.Reset() method that contains it, the program throws a StackoverflowException before the body of the Reset method even begins to be executed. If I remove just the field initialization line above, the error does not occur. 

    So what I'm wondering is, isn't there a better way of creating array constants? One perhaps in which the generated code would look more like this:

    Bernoulli c = new Bernoulli(0.89);

    this.vBernoulli__23 = new Bernoulli[15521] {c,c,c,c,c,c,c,c,c,c,c,c,c,c,.......

     

    I know I don't have a great understanding of the code generation process, so this may not be possible. But I am confused as to what I can do at this point.

     

    Thanks again,

    Nels

    Friday, June 3, 2011 5:54 PM

Answers

  • nbeckman replied on 07-05-2010 1:16 PM

    Yes! Thank-you. That worked perfectly.

     

    Nels

    Friday, June 3, 2011 5:55 PM

All replies

  • minka replied on 07-04-2010 1:09 PM

    The answer to your first question is yes, this code does accomplish what you want.  For the second question, if you want to avoid creating a large array of Bernoullis, then don't create one in your code.  Instead, do this:

    Variable.ConstrainEqualRandom( AND_array.[range], likely)

    You don't need to declare the likely_constants array at all. 

    Friday, June 3, 2011 5:55 PM
  • nbeckman replied on 07-05-2010 1:16 PM

    Yes! Thank-you. That worked perfectly.

     

    Nels

    Friday, June 3, 2011 5:55 PM