bayes.js: A Small Library for Doing MCMC in the Browser
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Bayesian data analysis is cool, Markov chain Monte Carlo is the cool technique that makes Bayesian data analysis possible, and wouldn’t it be coolness if you could do all of this in the browser? That was what I thought, at least, and I’ve now made bayes.js: A small JavaScript library that implements an adaptive MCMC sampler and a couple of probability distributions, and that makes it relatively easy to implement simple Bayesian models in JavaScript.
Here is a motivating example: Say that you have the heights of the last ten American presidents…
// The heights of the last ten American presidents in cm, from Kennedy to Obama var heights = [183, 192, 182, 183, 177, 185, 188, 188, 182, 185];
… and that you would like to fit a Bayesian model assuming a Normal distribution to this data. Well, you can do that right now by clicking “Start sampling” below! This will run an MCMC sampler in your browser implemented in JavaScript.
If this doesn’t seem to work in your browser, for some reason, then try this version of the demo.
Here is the model you just sampled from…
$$mu sim text{Normal}(0, 1000) \ sigma sim text{Uniform}(0, 1000) \ text{heights}_i sim text{Normal}(mu, sigma) ~~~ text{for} ~ i ~ text{in} 1..n$$
… and this is how it is implemented in JavaScript:
/* The code below assumes that you have loaded the two modules of bayes.js: * - mcmc.js which implements the sampler and creates the global * object mcmc. * - distributions.js which implements a number of log density functions * for common probability distributions and that creates the global object * ld (as in log density). */ // The data var heights = [183, 192, 182, 183, 177, 185, 188, 188, 182, 185]; // Parameter definitions var params = { mu: {type: "real"}, sigma: {type: "real", lower: 0}}; // Model definition var log_post = function(state, heights) { var log_post = 0; // Priors (here sloppy and vague...) log_post += ld.norm(state.mu, 0, 1000); log_post += ld.unif(state.sigma, 0, 1000); // Likelihood for(var i = 0; i < heights.length; i++) { log_post += ld.norm(heights[i], state.mu, state.sigma); } return log_post; }; // Initializing the sampler, burning some draws to the MCMC gods, // and generating a sample of size 1000. var sampler = new mcmc.AmwgSampler(params, log_post, heights); sampler.burn(1000); var samples = sampler.sample(1000);