stanimaniacs,
thanks to the stan development team, implementing stochastic MAP
estimation in stan is easy. there was a little trickiness to getting
it to work, so i thought i'd share.
best
dave
---
you'll need
- a subsample(b) function that grabs a subsample of size b from your
data set
- a stepsize(t) function that gets the t-th stepsize. (to start, you
can even just choose a constant stepsize.)
here is a skeleton of the program:
# model_filename = stan model
# subsample(b) = fun that returns a sample of b data points from the data
# n = data set size
# batch_size = size for each subsample to analyze on each iteration
# niter = number of iterations
# stepsize(t) = fun that returns the stepsize at iteration t
# model = (opt) a pre-compiled model
stochastic.map <- function(model_filename, subsample, n, batch_size,
niter, stepsize, model = NULL)
{
# compile the model (if needed) and initial parameters.
# here, parameters are initialized to zero.
if (is.null(model))
{
dummy_subsample <- sample.documents(data, batch_size)
model <- stan(model_filename, data = dummy_subsample, chains=0)
}
nparams <- sum(unlist(model@par_dims))
params <- rep(0, nparams)
grad_scale <- n / batch_size
# run stochastic gradient ascent by subsampling a batch, computing a
# noisy gradient, and taking a step. at each point, compute the
# the per-data log probability as a score to track.
score <- numeric(niter)
for (t in 1:niter)
{
batch <- subsample(batch_size)
iter_model <- stan(fit = model, data = batch, chains = 0)
grad <- grad_scale * grad_log_prob(iter_model, params)
params <- params + stepsize(t) * grad
score[t] <- log_prob(iter_model, params) / batch_size
}
# return the model object (in case we want to run again)
# the params vector
# the score trajectory
list(model = model, params = params, score = score)
}