Invert deterministic operations from measured variables #119
Replies: 4 comments 5 replies
-
The expectations for this library are that both examples should be supported, so there's no need to question the relevance of the idea. Side note: Regarding these specific examples, the easiest way to support This non-generalized-transform-based approach maintains a simplicity that generic transforms can't. More specifically, it's much easier to build further rewrites that operate on or expect log-normals, because it's much easier to identify a log-normal when it's just a Ultimately, we want to support such rewrites at least as much as the more generic transform approach. It should be possible for people to work with simple graphs that—as directly as is reasonably possible—map to a high-level representation of a model. |
Beta Was this translation helpful? Give feedback.
-
Just to be clear the problem is not with replacing This involves acting on the value variables directly (at least that's what we are doing so far for TransformedRVs), but we may not know which value variables are ultimately associated with intermediate IR variables |
Beta Was this translation helpful? Give feedback.
This comment was marked as off-topic.
This comment was marked as off-topic.
-
I am not completely sure about the design of import aesara.tensor as at
from aemcmc.basic import construct_sampler
srng = at.random.RandomStream(0)
Y_rv = my_model(srng)
y_vv = Y_rv.clone()
sampling_steps, updates, initial_values = construct_sampler(srng, {Y_rv: y_vv})
print(sampling_steps.model)
# Prints the model graph for instance The NUTS sampler currently operates on the original graph, and AePPL handles the transforms at the value variable level, so the transformation is not immediately obvious to callers, unless they inspect the Let’s give an example of logprob with transforms on a simple model: import aesara.tensor as at
from aemcmc.basic import construct_sampler
import aeppl
from aeppl.transforms import LogTransform, TransformValuesRewrites
srng = at.random.RandomStream(0)
mu_at = at.scalar('mu')
sigma_rv = at.random.lognormal(1.)
Y_rv = at.random.normal(mu_at, sigma_rv)
sigma_vv = sigma_rv.clone()
y_vv = Y_rv.clone()
rewrites = TransformValuesRewrites({sigma_vv: LogTransform()})
logprob = aeppl.joint_logprob({Y_rv: y_vv, sigma_rv: sigma_vv}, extra_rewrites=rewrites) When I would like instead to be able to transform the original graph to the following and condition on srng = at.random.RandomStream(0)
mu_at = at.scalar('mu')
sigma_rv = at.random.lognormal(1.)
sigma_rv_tr = at.log(sigma_rv)
Y_rv = at.random.normal(mu_at, sigma_rv)
sigma_vv_tr = sigma_rv_tr.clone()
y_vv = Y_rv.clone()
logprob = aeppl.joint_logprob({Y_rv: y_vv, sigma_rv_tr: sigma_vv_tr})
sigma_vv = at.exp(sigma_vv_tr) So NUTS can operate on this space, and then returns print(sampling_steps[sigma_rv].model)
# Model sampled
#
# mu_at = at.scalar('mu')
# sigma_rv = at.random.lognormal(1.)
# sigma_rv_tr = at.log(sigma_rv) <-- conditionned on
# Y_rv = at.random.normal(mu_at, sigma_rv) <--- conditionned on
#
# Returns
#
# sigma_vv = at.exp(sigma_vv_trans) More fundamentally, I don’t see any reason why the bijections needed by algorithms in the HMC family should have a special status among graph rewrites. In the end, these transforms should be implemented as a function that returns the transformed graph, the value variables to condition on and the value variables in the original space. It is fine to me if |
Beta Was this translation helpful? Give feedback.
-
Epistemic status: I am not sure about the usefulness of this, other than for variable transforms which we already have a solution for. So this may very well fit in the cute but perhaps useless category.
When Aeppl is asked to derive a logprob graph from a deterministic 1-1 operation based on some upstream random/measurable variable, we have to create a graph that reverses these deterministic operations (adding extra logprob and jacobian terms if needed):
This specific case is not implemented yet, but would be after #26
Other logprob terms like that of
z
are then allowed to depend ony
. However, they are not allowed to dependx
(which in the logprob term ofz
should be replaced byexp(y_vv)
) or in any other intermediate variables betweeny
andx
if there were more. For instance the following is not possible:That type of logp graph can currently be achieved via the TransformValuesOpt but that feels like a clunky add-on. If the above were allowed, we would have a very natural way of defining variable transformations in Aeppl. For more complex transformations we could still use specialized Op's that specify what the inverse graph should be:
And the transformation would still be part of the generative graph, without the need for the extra rewrite.
I wonder how feasible this would be, and whether it opens the door for more interesting features or just falls in the "cute" category.
Beta Was this translation helpful? Give feedback.
All reactions