library("nimble")
library("ggplot2")
library("tidyr")
library("dplyr")
dmnorm example
from Daniel, who notes we need to be explicit about vector/matrix sizes on both LHS and RHS,
code <- nimbleCode({
mu ~ dunif(-100, 100)
sigma ~ dunif(0, 100)
rho ~ dunif(20, 100)
muVec[1:N] <- mu * onesVector[1:N]
Cov[1:N, 1:N] <- sigma^2 * exp(-dist[1:N, 1:N]/rho)
g[1:N] ~ dmnorm(muVec[1:N], cov = Cov[1:N, 1:N])
for (i in 1:N) {
y[i] ~ dpois(exp(g[i]))
}
})
constants <- list(N = 148,
onesVector = rep(1, 148),
dist = matrix(1, nrow=148, ncol=148))
y = rpois(148, 1) # vector of 148 observations (counts)
data <- list(y=y)
inits <- list(mu = 0,
sigma = 5,
rho = 60,
g = rep(0, 148))
m <- nimbleModel(code = code, constants = constants, data = data, inits = inits)
GP Model, original specification
This model definition doesn’t work, since we do not define sizes explicitly
code <- nimbleCode({
l ~ dunif(0,1e4)
sigma.n ~ dunif(0, 1e4)
Sigma[1:N, 1:N] <- exp(-0.5 * diff / l ^ 2) + sigma.n ^ 2 * I
y[1:N] ~ dmnorm(Mu, cov = Sigma)
})
obs <- data.frame(x = c(-4, -3, -1, 0, 2),
y = c(-2, 0, 1, 2, -1))
N <- length(obs$x)
diff <- outer(obs$x, obs$x, function(xi, xj) (xi-xj)^2)
constants = list(N = N, x = obs$x, Mu = rep(0,N), diff = diff, I = diag(1,N))
inits <- list(l = 1, sigma.n = 10)
data <- data.frame(y = obs$y)
m <- nimbleModel(code = code, constants = constants, data = data, inits = inits)
Error in x$parentNodeExprs[[iV]][[iDim + 2]]: object of type 'symbol' is not subsettable
GP Model, v2
This model definition still doesn’t work, even though it appears to be more explicit
code <- nimbleCode({
l ~ dunif(0,100)
sigma.n ~ dunif(0,100)
SE <- function(xi,xj, l) exp(-0.5 * (xi - xj) ^ 2 / l ^ 2)
Sigma[1:N, 1:N] <- outer(x[1:N], x[1:N], SE, l) + sigma.n ^ 2 * I[1:N, 1:N]
y[1:N] ~ dmnorm(Mu[1:N], cov = Sigma[1:N, 1:N])
})
obs <- data.frame(x = c(-4, -3, -1, 0, 2),
y = c(-2, 0, 1, 2, -1))
N <- length(obs$x)
constants = list(N = N, x = obs$x, Mu = rep(0,N), I = diag(1,N))
inits <- list(l = 1, sigma.n = 10)
data <- data.frame(y = obs$y)
nimbleModel(code = code, constants = constants, data = data, inits = inits)
Error in replaceConstantsRecurse(x, constEnv, constNames): Error, hit end
GP Model
A successful specification looks like this:
code <- nimbleCode({
l ~ dunif(0,1e5) # dgamma(5, 5)
sigma.n ~ dunif(0, 1e5) # dgamma(5, 5)
Sigma[1:N, 1:N] <- exp(-0.5 * diff[1:N, 1:N] / l ^ 2) + sigma.n ^ 2 * I[1:N, 1:N]
y[1:N] ~ dmnorm(Mu[1:N], cov = Sigma[1:N, 1:N])
})
obs <- data.frame(x = c(-4, -3, -1, 0, 2),
y = c(-2, 0, 1, 2, -1))
N <- length(obs$x)
diff <- outer(obs$x, obs$x, function(xi, xj) (xi-xj)^2)
constants = list(N = N, x = obs$x, Mu = rep(0,N), diff = diff, I = diag(1,N))
inits <- list(l = 1, sigma.n = 10)
data <- data.frame(y = obs$y)
m <- nimbleModel(code = code, constants = constants, data = data, inits = inits)
Define our mcmc procedure in Nimble
my_mcmc <- function(code, constants, data, inits, n_iter=1e5, thin = 1e2){
Rmodel <- nimbleModel(code = code, constants = constants, data = data, inits = inits)
Cmodel <- compileNimble(Rmodel)
mcmcspec <- configureMCMC(Rmodel, print=FALSE,thin=thin)
Rmcmc <- buildMCMC(mcmcspec)
Cmcmc <- compileNimble(Rmcmc, project = Cmodel)
Cmcmc$run(n_iter)
samples <- as.data.frame(as.matrix(Cmcmc$mvSamples))
#samples <- samples[,1:(length(inits)-1)]
gather(samples)
}
df <- my_mcmc(code = code, constants = constants, data = data, inits = inits, n = 1e6)
Summary statistics
summarise(group_by(df, key), mean=mean(value), std=sqrt(var(value)))
Source: local data frame [2 x 3]
key mean std
1 l 49845.347322 29128.275365
2 sigma.n 2.188315 1.372436
Traces
ggplot(sample_n(df,500)) +
geom_line(aes(seq_along(value), value)) +
facet_wrap(~key, scale='free')
Posteriors
ggplot(df) +
geom_density(aes(value)) +
facet_wrap(~key, scale='free')
Time-series example
f <- function (x, p){ x * exp(p[1] * (1 - x / p[2]) * (x - p[3]) / p[2]) }
p <- c(2, 8, 5)
z_g <- function() rlnorm(1, 0, 0.05)
T <- 40
set.seed(1234)
x <- numeric(T)
x[1] <- 5.5
for(t in 1:(T-1))
x[t+1] = z_g() * f(x[t], p=p)
qplot(seq_along(x), x)
data <- data.frame(x=x)
model setup
obs <- data.frame(x=x[1:(T-1)], y = x[2:T])
N <- length(obs$x)
diff <- outer(obs$x, obs$x, function(xi, xj) (xi-xj)^2)
constants = list(N = N, x = obs$x, Mu = rep(0,N), diff = diff, I = diag(1,N))
inits <- list(l = 1, sigma.n = 10)
data <- data.frame(y = obs$y)
Estimate GP bm MCMC with Nimble
df <- my_mcmc(code = code, constants = constants, data = data, inits = inits, n = 1e6)
Summary statistics
summarise(group_by(df, key), mean=mean(value), std=sqrt(var(value)))
Source: local data frame [2 x 3]
key mean std
1 l 3.8059775 0.60843921
2 sigma.n 0.3641306 0.04565619
Traces
ggplot(sample_n(df,500)) +
geom_line(aes(seq_along(value), value)) +
facet_wrap(~key, scale='free')
Posteriors
ggplot(df) +
geom_density(aes(value)) +
facet_wrap(~key, scale='free')