stan-dev / posteriordb

Database with posteriors of interest for Bayesian inference
176 stars 36 forks source link

Add model implementations to the API #125

Open eerolinna opened 4 years ago

eerolinna commented 4 years ago

I will show the potential changes with an example using python

model = my_pdb.model("eight_schools_centered")

We can access the different model implementations

stan_implementation = model.implementation("stan")
pymc_implementation = model.implementation("pymc3")

From the model implementation we can access prior samples and predictive samples

stan_prior = stan_implementation.sample_prior()
pymc_prior = pymc_implementation.sample_prior()

stan_prior_predictive = stan_implementation.predictive_draws(stan_prior)
pymc_prior_predictive = pymc_implementation.predictive_draws(pymc_prior)

The stan implementation would use the likelihood file for predictive draws and a prior file for prior draws while the pymc implementation could just use the generic functionality of pymc. For stan if the likelihood file is missing the code will throw an error saying that the model doesn't support predictive draws, and the same for the prior.

We can also load the model code

# this returns the compiled stan model
stan_model = stan_implementation.load()

# this returns the function defined in
# https://github.com/MansMeg/posteriordb/blob/development/posterior_database/models/pymc3/eight_schools_noncentered.py
pymc_model = pymc_implementation.load()

Posterior predictive draws can be computed with predictive_draws

# posterior draws from some posterior that uses the eight schools model
stan_posterior_draws = ...
pymc_posterior_draws = ...

stan_posterior_predictive =  stan_implementation.predictive_draws(stan_posterior_draws)
pymc_posterior_predictive = pymc_implementation.predictive_draws(pymc_posterior_draws)

In other words, a model implementation has a particular interface that all implementations must satisfy. In this example the interface is that all implementations must have methods predictive_draws, sample_prior and load. The particular names of the methods are just initial suggestions and open to improvements.

In cases where some of the methods are not appropriate (like trying to load a R-only model into python) the implementation may throw an error.

I would probably also include getting the model code in the interface. Then model.code("stan") would be a shorthand for model.implementation("stan").code() and the same for code_file_path.

eerolinna commented 4 years ago

@MansMeg any comments?

MansMeg commented 4 years ago

Not yet. have not thought so much asbout this. Ill have to implement it myself in R (predictive draws) to be sure. For the basic stuff (pymc3) I didnt change the R api that is simply

mc <- model_code("model", framework = "pymc3")
eerolinna commented 4 years ago

I will start working on a PR that implements this for python

MansMeg commented 4 years ago

I think this is good with the exception that we should call it prior draws rather than sample_prior.

eerolinna commented 4 years ago

So stan_implementation.prior_draws() instead of stan_implementation.sample_prior()? Sounds good.

MansMeg commented 4 years ago

Yes.