I encountered a bug in pm.fast_sample_posterior_predictive(). Or maybe it is intended behavior that I don’t understand.
Consider this simple model with two normals and three deterministics:
import pymc3 as pm
import numpy as np
import xarray as xr
import arviz as az
with pm.Model() as model:
n1 = pm.Normal('n1', 0, 1)
d1 = pm.Deterministic('d1', n1)
n2 = pm.Normal('n2', 0, 1)
d2 = pm.Deterministic('d2', n2)
d3 = pm.Deterministic('d3', d2)
After sampling, all five variables have posterior distributions whose means are close to 0.0, and standard deviations are close to 1.0:
def mean_and_std(result):
vals = result.values
return np.mean(vals), np.std(vals)
Now a new trace incr_trace is created by copying the existing trace and then incrementing all samples of n1 by 1.0, and also incrementing all samples of d2 by 1.0.
def increment_both_distrs(posterior_ds):
new_ds = posterior_ds.copy(deep=False)
increment_distr(new_ds, 'n1')
increment_distr(new_ds, 'd2')
return new_ds
def increment_distr(dataset, var_name):
dataset[var_name] = xr.apply_ufunc(
lambda da: da+1, dataset[var_name])
incr_trace = trace.map(increment_both_distrs, groups='posterior')
As expected, the samples for n1 in incr_trace now have a mean of about 1.0, as do the samples for d2.
So far so good. Now pm.fast_sample_posterior_predictive() is run on the new trace, and d1 and d3 are sampled.
with model:
pp_trace = az.from_pymc3(
posterior_predictive=pm.fast_sample_posterior_predictive(
trace=incr_trace, var_names=['d1', 'd3']))
The d1 samples in the new posterior_predictive trace pp_trace have a mean of about 1.0, as expected. But the d3 samples in pp_trace have a mean of about 0.0, rather than 1.0.
It’s as if pm.fast_sample_posterior_predictive() ignores the incremented values for d2 in incr_trace and uses the original non-incremented values. But how does it even know about the old, non-incremented values?
Is this a bug? Or perhaps is this a misunderstanding on my part?
Note that this bug—if it is in fact a bug—is not unique to pm.fast_sample_posterior_predictive(). The old, slow pm.sample_posterior_predictive() exhibits the same behavior.
PyMC3 version 3.9.3