Description
Description
The current behavior of sample_posterior_predictive
regarding "volatility" and var_names
is very opaque and error-prone.
If you include a model variable in var_names
it will always be sampled, even if it was an unobserved variable with values in the trace. Furthermore, any variables that depend on variables being sampled ("volatile") will also be sampled even if they are not in var_names
, and become "volatile" themselves. With this, it's easy for users to end up resampling the whole model from the prior by accident when they only wanted to do predictions and copy some variables from the posterior to the predictions group.
Most of the times I've seen users including unobserved variables in var_names
, they seemed to only want to copy those over from the posterior to the posterior_predictive, to be together with the newly sampled observed variables. The volatile logic was a bug from their perspective.
Furthermore if an unobserved variable depends on MutableData/Coords that have changed that will also be resampled, and the whole cascade of volatility propagation happens the same.
If this doesn't make sense, I tried to explain the current behavior in #7014
Why did we ever think this behavior was a good idea?
Both behaviors are sensible in that they provide internally consistent draws, and avoid reusing posteriors in case they are likely to make little theoretical sense (if you have an intercept for the cities ["Paris", "Lisbon"], and now changed the coords to be ["London", "Madrid"], there is no reason to think the old posteriors should apply to the new cities), or computational sense (the length of the intercepts may have changed, and reusing the old ones would likely cause shape errors or silent bugs).
Aside: Maybe in that example users set the new coords to be ["Paris, "Lisbon", "London"], or they changed the shape from 2 to 3, expecting the new dim would be sampled, but the original two reused. That would be nice but hard to do, and on the verge of mind reading if only the shape changed. Such behavior should not be the competence of sample_posterior_predictive
, but helper model transformation function. sample_posterior_predictive
should only have to worry whether the variables with the same name as those in the posterior trace can be used as is, or must be resampled.
The current flexibility is not only a burden! It allows to do many interesting things like https://www.pymc-labs.io/blog-posts/out-of-model-predictions-with-pymc/
Anyway, the original motivation for these changes was because of Deterministics, which should sometimes be resampled (because they depended on MutableData that has changed) and other times reused to avoid useless re-computations in sample_posterior_predictive
.
- Deterministics not resampled in posterior predictive #5302
pm.set_data
does not affect posterior predictive shape whenpm.Deterministic
is used #5512
We initially went overboard and resampled everything that depended on MutableData, regardless of whether that had changed
Which was fixed in #6147
Because the behavior still seemed too implicit and hard to debug, we tried to make logging explicit, although some environments like vscode/colab like to suppress those logs #5973
Latest proposal
IMO the issue with the current behavior, is that it's too silent/implicit and only rarely what users want. Instead of making it easy for power-users to do what they want, I would err on the side of caution and alerting users for those cases where reusing posterior draws may not be reasonable. My proposal:
-
Distinguish between
var_names
andsample_vars
. The first determines which variables are included in the trace, the second which variables are being sampled. By default, observed variables are included in both fields, and the function behaves as the current default. I think most users think ofvar_names
like this already from use in arviz functions. -
Instead of defaulting to sampling new variables that depend on trace constant_data / coords / dims that have changed, but which are not in
sample_vars
try to reuse those from the trace but issue a warning that the posterior draws may no longer be valid since the model structure has changed. If they are insample_vars
, there is no warning and it behaves as now. We could make it a hard error... but someone will certainly complain that's actually want they wanted to do, and how can they do it then. -
The warning should happen regardless of whether those constant_data / coords / dims are defined in the model as Mutable/ConstantData or coords/coords_mutable (brought up in
sample_posterior_predictive
does not consider changes in "ConstantData" and "Constant coords" #6876) -
Deterministics, which is the reason why much of the behavior was written as is (we want to update Deterministics if model data / coords have changed, but reuse from the trace otherwise), still follow the current implicit volatile logic. They cannot be included in
sample_vars
, but can be invar_names
in which case they are recomputed or copied, depending on whether there were any changes in the model structure leading to them (or if they depend on a variable that is being sampled).
More extreme proposal (rejected in the comments)
Only allow sampling of observed variables in sample_posterior_predictive
and create a new function predict
(or whatever, just not so verbose) that has all the flexibility sample_posterior_predictive
currently has. Could also be used for prior when no idata
is passed.
This could also allow the values of ObservedRV
s to be used in place of the variables when they are not being sampled, which is often useful in forecasting models.
Recent examples where var_names
did not do what the user expected: