Ok, this was actually easy enough to make the checking functions able
to operate on any parameters. I had to add a `params` argument. The
tricky part internally (and also the speed bottleneck) was to find a
way of subsetting arrays of varying dimensions. With this I could
implement `check_model()`. Note that I renamed all checking functions
from *_check to check_* to make them verbs.
So now the global idea behind the checking functions is that you apply
a statistic on both y and y_rep. If you already have y_rep, you call
check_model. If you need to sample replicates, you call the
specialised functions like check_normal or check_bernoulli. Actually,
the distribution-specific functions just sample replicates and then
call check_model themselves.
These functions work outside gsim on extracted stanfit
simulations. (Note that if you need to get simulations in this form,
you can use `as.mclist()` on any object supported in gsim.) They don't
work inside gsim yet, but when they do the only difference will be
that they won't have a params argument.
Example with check_model:
newcomb_sims <- extract(stanfit)
out <- check_model(y = radon$y, y_rep, params = newcomb_sims,
stat = {
y_sorted <- sort(y)
abs(y_sorted[61] - y_hat) - abs(y_sorted[6] - y_hat)
})
Example with check_bernoulli:
wells_sims <- extract(stanfit)
out <- check_bernoulli(y = wells$switched, p = y_hat,
params = wells_sims, stat = sd(y - p)
)
check_normal is similar to check_bernoulli, only with mu and sigma
arguments.
When params is supplied, NSE is used for the random variables (y_rep,
mu, sigma, p, etc). So if you specify mu = y_hat, they will look
inside params for y_hat. On the other hand, when params is not
supplied, the random variables are obtained from the calling
environment. In both cases, the statistic operates on 'official' param
names (mu, sigma, p), not on supplied names.
I may change that interface if it is confusing. I would love some
feedback from experimented ppc users. One remaining issue is speed,
although it's fast enough for practical purposes. Computing a bernoulli
check on 2000 simulations takes 1.6 seconds on my computer.
Rewriting check_model in c++ would solve this.
Anyway, thanks Tamas. I don't know if these functions would be a good
replacement of map_posterior for you but our discussion helped me see
things more clearly!
Lionel