knitr::opts_chunk$set( fig.path = paste('figure/', knitr::current_input(), '-figs/', sep=''), fig.width = 7, fig.height = 5 )
library(doit) library(lhs) library(tidyverse)
suppressPackageStartupMessages(library(doit)) suppressPackageStartupMessages(library(lhs)) suppressPackageStartupMessages(library(tidyverse))
We use the example model from Joseph (2012), namely a Bernoulli likelihood with logit link function and a Normal prior:
The unnormalised posterior is given by
h = function(r) { p = 1/(1+exp(-r)) dbinom(1, 1, p) * dnorm(r, 1, 4) }
We evaluate the unnormalised posterior at 10 equally spaced design points:
design = data.frame(x=seq(-10, 20, len=10)) design$f = sapply(design$x, h)
The DoIt method works by approximating the target density by a weighted sum of
Normal distributions. The optimal variance parameter w
of the Normal
distributions is estimated by the function doit_estimate_w()
:
w = doit_estimate_w(design) print(w)
The function doit_fit()
estimates the parameters of the DoIt method and saves
them in an object of class doit
:
doit = doit_fit(design, w=w)
We specify the parameter values at which we want to approximate the target
posterior and use doit_approx()
to calculate the approximation:
theta_eval = data.frame(x = seq(-15,25,.1)) doit_out = doit_approx(doit, theta_eval)
The approximation function returns the approximated density value and the estimation error variance:
head(doit_out)
The output of doit_approx()
works nicely with the ggplot2
package:
ggplot() + geom_line(data=doit_out, aes(x=x, y=dens_approx, colour=variance)) + geom_point(data=design, aes(x=x, y=0), pch=1, cex=2)
To extend the existing design, we use doit_propose_new()
to choose a new
design point where the current estimation variance is particularly high:
x_n = doit_propose_new(doit) design_new = mutate(x_n, f=h(x))
Instead of using doit_fit()
again on the original design plus additional new
point, we can use the doit_update()
function which is more efficient. Note
that the kernel width w
is not updated:
doit = doit_update(doit, design_new)
We plot the new approximation and highlight the added design point:
doit_out = doit_approx(doit, theta_eval) ggplot() + geom_point(data=design_new, aes(x=x, y=0), pch=1, cex=2, col='red') + geom_point(data=design, aes(x=x, y=0), pch=1, cex=2) + geom_line(data=doit_out, aes(x=x, y=dens_approx, colour=variance))
We have functions to approximate posterior mean and variance:
doit_expectation(doit) doit_variance(doit)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.