charles-river-analytics / figaro

Figaro Programming Language and Core Libraries
Other
756 stars 151 forks source link

Questions about explicit sampling #726

Open toncho11 opened 6 years ago

toncho11 commented 6 years ago

Hi,

Two questions:

1) I get this warning: Warning: Sampling element Normal(200.0, 50.0) even though no sampler defined for this universe. Is this a problem?

2) I use this function:

def GetSampleFromNormal(mean : Int, std : Int): Long = { val sample = Normal(mean,std);

Forward(sample);

println("system: wait time ms: " + sample.value.toLong.toInt);

return sample.value.toLong;

}

but I wonder does it make a difference if I

In the second case I am sure I will get a Normal distribution with parameters specified, but when calling the function GetSampleFromNormal from time to time the way it is coded now I am not sure.

bruttenberg commented 6 years ago

Hi,

First, that warning has been changed in more recent versions of Figaro, and it’s much more informative now ☺

Second, the function you mention below shouldn’t be triggering that warning. That warning comes when you try to use a factored algorithm on a model with continuous elements, in which case the continuous ones are sampled.

The function you have below seems to be fine. Drawing the samples one at a time or all at once shouldn’t matter as long as the mean/std stay the same (FYI, the parameter to the Normal in Figaro is variance, not standard deviation).

From: toncho11 [mailto:notifications@github.com] Sent: Friday, October 27, 2017 10:36 AM To: p2t2/figaro figaro@noreply.github.com Cc: Subscribed subscribed@noreply.github.com Subject: [p2t2/figaro] Questions about explicit sampling (#726)

Hi,

Two questions:

  1. I get this warning: Warning: Sampling element Normal(200.0, 50.0) even though no sampler defined for this universe. Is this a problem?

  2. I use this function:

def GetSampleFromNormal(mean : Int, std : Int): Long = { val sample = Normal(mean,std);

Forward(sample);

println("system: wait time ms: " + sample.value.toLong.toInt);

return sample.value.toLong;

}

but I wonder does it make a difference if I

In the second case I am sure I will get a Normal distribution with parameters specified, but when calling the function GetSampleFromNormal the way it is coded now I am not sure.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHubhttps://github.com/p2t2/figaro/issues/726, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AFJOJanLfD5YkuzT7dOgMq8g1aI4nLhCks5swepGgaJpZM4QJJxJ.

toncho11 commented 6 years ago

Hi,

Thanks for your quick reply. Sure it is the variance.

Yes, I am using a factored algorithm in this universe to calculate the probabilities of a Bayes Net. All my variables are of type Flip in my model. I am using:

VariableElimination.probability(e.probVariable, true)

for each variable in my Bayes net. Is there a more optimized way to calculate the probabilities of several variables all-together? And I am also drawing samples from a Normal distribution.

bruttenberg commented 6 years ago

Yes, you can say:

Val alg = VariableElimination(target1, target2, etc) Alg.start() Alg.probability(target1, true)

Not clear to me what the normal is doing, but if you’re using a factored algorithm that’s where the warning is coming from.

From: toncho11 [mailto:notifications@github.com] Sent: Friday, October 27, 2017 3:30 PM To: p2t2/figaro figaro@noreply.github.com Cc: Brian Ruttenberg bruttenberg@cra.com; Comment comment@noreply.github.com Subject: Re: [p2t2/figaro] Questions about explicit sampling (#726)

Hi,

Thanks for your quick reply. Sure it is the variance.

Yes, I am using a factored algorithm in this universe to calculate the probabilities of a Bayes Net. All my variables are of type Flip in my model. I am using:

VariableElimination.probability(e.probVariable, true)

for each variable in my Bayes net. Is there a more optimized way to calculate the probabilities of several variables all-together? And I am also drawing samples from a Normal distribution.

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/p2t2/figaro/issues/726#issuecomment-340064379, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AFJOJWlUzFYEQA-lukOvmiYErXQkiy1Dks5swi8ogaJpZM4QJJxJ.

toncho11 commented 6 years ago

I still do not understand if the warning is important.

It seems like it is not possible instead of:

target1, target2,

to give a: val list = scala.List[com.cra.figaro.language.Element[_]] ?

mhoward2718 commented 6 years ago

Generally, you shouldn't use element.value in your code. This variable tracks internal state for Figaro's sampling algorithms. It can be useful for debugging, but you should almost never use it as part of a model. If your model is gives incorrect results, this could be one reason why.

If you want to round the value of a Normal to an integer, as you do in your GetSampleFromNormal method, you should use Apply or Chain, and use a Figaro algorithm to infer its expected or most likely value..

For example, you could do:

def makeRoundedNormal(mean: Int, variance: Int) : Element[Int] = {
   val n = Normal(mean, variance)
   def round(d: Double) = d.toInt
   val nRounded= Apply(n,round)
   nRounded
}
mhoward2718 commented 6 years ago

Also - You can convert a collection to a variable length list of arguments. So you could do something like:

val targets = List(target1,target2,target2)
val algorithm = VariableElimination(targets:_*)
...
targets.map{ t => algorithm,probability(t,true) }
toncho11 commented 6 years ago

Thanks! It helps!

For the Normal dist sampling: if I use the expected value ... I still get a double value that I need to round ... so it is better to use the MPV. I consider the Most Probable Value = Most Likely Value.

So this is the final version with MPV (Most Probable Value)

 def GetSampleFromNormal(mean : Int, variance : Int): Long =
  {
    val samplerLong = makeRoundedNormal(mean, variance);

    val algorithm = MPEBeliefPropagation(10) //10 iterations

    algorithm.start()

    val mlv = algorithm.mostLikelyValue(samplerLong)

    algorithm.kill()

    return mlv;
  }

Is it OK? It feels a bit heavy all this. Actually there is a slight difference between expected value and most likely value.

And for the Flip:

def GetSampleFromFlip(prob : Double): Boolean =
  {
    val sample = Flip(prob);

    Forward(sample);

    return sample.value;
  }

Should it be improved in a similar way as for the normal? I think it is correct (see above) because the output of Flip is discrete already (true or false).