-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Infer logprob of Ifelse
graphs
#6529
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #6529 +/- ##
==========================================
- Coverage 92.02% 87.21% -4.82%
==========================================
Files 92 92
Lines 15563 15587 +24
==========================================
- Hits 14322 13594 -728
- Misses 1241 1993 +752
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice approach @ricardoV94. I left a pair of comments. One thing that I found confusing were the first two commits. Are those really central to this PR or could they be PR in itself?
rvs_to_values_else = {else_rv: value for else_rv, value in zip(base_rvs[len(values) :], values)} | ||
|
||
logps_then = [ | ||
logprob(rv_then, value, **kwargs) for rv_then, value in rvs_to_values_then.items() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What’s the behaviour of logprob when the value variable doesn’t have the expected shape? Will it raise a ValueError? I think that would be bad in this case. Imagine if you have a step method on the condition variable. The stepper might choose to move the condition to an infeasible value and that would kill the sampling process. I would like the condition that doesn’t match shapes to simply return -inf logprob. That way the stepper would discard the proposal and stay in reasonable regions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The behavior of the logprob when the value variable doesn't match shape is exactly the same as the logprob of the underlying components. If it doesn't match, it will try to broadcast and fail if it cannot. Other than that we don't use size information in any of the core logprob functions.
pm.logp(pm.Normal.dist(size=(4,)), np.ones((2,)))
will be happy to return a logp with two values.
One other case where this shows up is in graphs of the form pt.ones((5,)) + pm.Normal.dist()
which we infer to have an equivalent logp as that of pm.Normal.dist(shape=(5,))
even though the generative process contains only one true random variable, and not 5.
I think we need a bigger discussion about the role of shape information in the random and logp graphs, so I wouldn't treat IfElse
differently for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Opened an issue here: #6530
logps_then = replace_rvs_by_values(logps_then, rvs_to_values=rvs_to_values_then) | ||
logps_else = replace_rvs_by_values(logps_else, rvs_to_values=rvs_to_values_else) | ||
|
||
return ifelse(if_var, logps_then, logps_else) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the goal only to allow for explicit conditions in the mixture instead of marginalising?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The applications may vary. We don't explicitly marginalize anything in the logprob submodule, but something like MarginalModel would marginalize this just fine if we can give it the logprob function that this PR offers.
They could be in a PR by itself, but this one builds directly on the refactoring done in those commits, so I would wait for it to get merged first if it was separate. |
ca4b29e
to
3789eea
Compare
3789eea
to
d89ce91
Compare
These have now been merged elsewhere |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some more questions :)
This kind of graphs can't be handled by switch mixtures, because that requires outputs to have the same shapes.
This could one day be useful for variable size samplers... for now it's just here for completeness and libraries building on top of PyMC.