Implements many - but currently not all - of the Bayesian models in posteriordb
by implementing Julia macros and functions which mimick Stan blocks and functions respectively, with relatively light dependencies.
Using the macros and functions defined in this package, the "shortest" posteriordb
model (earn_height.stan
)
data {
int<lower=0> N;
vector[N] earn;
vector[N] height;
}
parameters {
vector[2] beta;
real<lower=0> sigma;
}
model {
earn ~ normal(beta[1] + beta[2] * height, sigma);
}
becomes
julia_implementation(::Val{:earn_height}; N, earn, height, kwargs...) = begin
@stan begin
@parameters begin
beta::vector[2]
sigma::real(lower=0.)
end
@model begin
earn ~ normal(@broadcasted(beta[1] + beta[2] * height), sigma);
end
end
end
Instantiating the posterior (i.e. model + data) requires loading PosteriorDB.jl
,
which provides access to the datasets, e.g. to load the earnings-earn_height
posterior (earn_height
model + earning
data):
import StanBlocks, PosteriorDB
pdb = PosteriorDB.database()
post = PosteriorDB.posterior(pdb, "earnings-earn_height")
jlpdf = StanBlocks.julia_implementation(post)
jlpdf(randn(StanBlocks.dimension(jlpdf))) # Returns some number
Stan's default "sampling statement" (e.g. y ~ normal(mu, sigma);
) automatically drops constant terms (unless configured differently), see https://mc-stan.org/docs/reference-manual/statements.html#log-probability-increment-vs.-distribution-statement.
Constant terms are terms which do not depend on model parameters, and this package's macros and functions currently do not try to figure out which terms do not depend on model parameters, and as such we never drop them.
This may lead to (constant) differences in the computed log-densities from the Stan and Julia implementations.
I've implemented many of the models, but I haven't implemented all of them, and I probably have made some mistakes in implementing some of them.
Just that.
See https://nsiccha.github.io/StanBlocks.jl/#overview-of-posteriors for an overview of (hopefully) correctly implemented models.
See test/runtests.jl
for a way to run and check the models.
After importing PosteriorDB
, StanLogDensityProblems
and LogDensityProblems
, you should have access to reference Stan implementations of the log density and of its gradient, see the documentation of StanLogDensityProblems.jl
.
The Stan log density can then be compared to the Julia log density as is, and after loading Julia's AD packages, you can also compare the Stan log density gradient to the Julia log density gradient.
Check out https://nsiccha.github.io/StanBlocks.jl/performance.html for an overview of implemented posteriors and their relative performances.