| wMix {bisque} | R Documentation |
Construct a weighted mixture object
Description
For a Bayesian model
X ~ f(X | \theta_1, \theta_2)
(\theta_1, \theta_2) ~ f(\theta_1, \theta_2),
the marginal posterior f(\theta_1 | X) distribution can be
approximated via weighted mixtures via
f(\theta_1 | X) \approx \sum_{j=1}^K f(\theta_1 | X, \theta_2) w_j
where w_j is based on f(\theta_2^{(j)} | X) and weights
\tilde w_j, where \theta_2^{(j)} and \tilde w_j are
nodes and weights for a sparse-grid quadrature integration scheme.
The quadrature rule is developed by finding the posterior mode of
f(\theta_2|X), after transforming \theta_2 to an unconstrained
support. For best results, \theta_2 should be a continuous random
variable, or be able to be approximated by one.
Usage
wMix(
f1,
f2,
w,
f1.precompute = function(x, ...) { x },
spec = "ff",
level = 2,
c.int = NULL,
c.level = 2,
c.init = NULL,
c.link = rep("identity", length(c.init)),
c.link.params = rep(list(NA), length(c.init)),
c.optim.control = list(maxit = 5000, method = "BFGS"),
ncores = 1,
quadError = TRUE,
...
)
Arguments
f1 |
evaluates
|
f2 |
evaluates |
w |
|
f1.precompute |
function that pre-computes parameters for evaluating
|
spec |
Specification of whether |
level |
accuracy level of the numerical approximation (typically number of grid points for the underlying 1D quadrature rule) [description from mvQuad::createNIGrid] |
c.int |
If |
c.level |
accuracy level of the numerical approximation for |
c.init |
initial guess for mode of |
c.link |
character vector that specifies transformations used during
optimization and integration of |
c.link.params |
Optional list of additional parameters for link
functions used with |
c.optim.control |
Arguments used to find mode of |
ncores |
number of cores used to parallelize computation of parameters
for |
quadError |
TRUE if integration nodes and weight should be computed for
the |
... |
Additional arguments to pass to |
Value
A list with class wMix, which contains the following items.
fFunction for evaluating the posterior density
f(\theta_1|X).fis callable viaf(theta1, log, ...).mixA matrix containing the pre-computed parameters for evaluating the mixture components
f(\theta_1 | \theta_2, X). Each row of the matrix contains parameters for one of theKmixture components.wtsIntegration weights for each of the mixture components. Some of the weights may be negative.
expectationList containing additional tools for computing posterior expectations of
f(\theta_2|X). However, posterior expectations off(\theta_1|X)can also be computed when expectations off(\theta_1|\theta_2, X)are known. The elements ofexpectationareEhFunction to compute
E[h(\theta_2)|X].Ehis callable viaEh(h, ...), wherehis a function callable viah(theta2, ...)and...are additional arguments to the function. The functionhis evaluated at the quadrature nodes\theta_2^{(j)}.Eh.precomputeExactly the same idea as
Eh, but the functionhis evalauted at the quadrature nodes after being passed through the functionf1.precompute.gridThe sparse-quadrature integration grid used. Helpful for seeing the quadrature nodes
\theta_2^{(j)}.wtsThe integration weights for approximating the expectation
E[h]. Note that these integration weights may differ from the main integration weights for evaluating the posterior densityf(\theta_1|X).
Examples
# Use BISQuE to approximate the marginal posterior distribution for unknown
# population f(N|c, r) for the fur seals capture-recapture data example in
# Givens and Hoeting (2013), example 7.10.
data('furseals')
# define theta transformation and jacobian
tx.theta = function(theta) {
c(log(theta[1]/theta[2]), log(sum(theta[1:2])))
}
itx.theta = function(u) {
c(exp(sum(u[1:2])), exp(u[2])) / (1 + exp(u[1]))
}
lJ.tx.theta = function(u) {
log(exp(u[1] + 2*u[2]) + exp(2*sum(u[1:2]))) - 3 * log(1 + exp(u[1]))
}
# compute constants
r = sum(furseals$m)
nC = nrow(furseals)
# set basic initialization for parameters
init = list(U = c(-.7, 5.5))
init = c(init, list(
alpha = rep(.5, nC),
theta = itx.theta(init$U),
N = r + 1
))
post.alpha_theta = function(theta2, log = TRUE, ...) {
# Function proportional to f(alpha, U1, U2 | c, r)
alpha = theta2[1:nC]
u = theta2[-(1:nC)]
theta = itx.theta(u)
p = 1 - prod(1-alpha)
res = - sum(theta)/1e3 - r * log(p) + lJ.tx.theta(u) -
nC * lbeta(theta[1], theta[2])
for(i in 1:nC) {
res = res + (theta[1] + furseals$c[i] - 1)*log(alpha[i]) +
(theta[2] + r - furseals$c[i] - 1)*log(1-alpha[i])
}
if(log) { res } else { exp(res) }
}
post.N.mixtures = function(N, params, log = TRUE, ...) {
# The mixture component of the weighted mixtures for f(N | c, r)
dnbinom(x = N-r, size = r, prob = params, log = log)
}
mixparams.N = function(theta2, ...) {
# compute parameters for post.N.mixtures
1 - prod(1 - theta2[1:nC])
}
w.N = wBuild(f = post.alpha_theta, init = c(init$alpha, init$U),
approx = 'gauss', link = c(rep('logit', nC), rep('identity', 2)))
m.N = wMix(f1 = post.N.mixtures, f1.precompute = mixparams.N,
f2 = post.alpha_theta, w = w.N)
# compute posterior mean
m.N$expectation$Eh.precompute(h = function(p) ((1-p)*r/p + r),
quadError = TRUE)
# compute posterior density
post.N.dens = data.frame(N = r:105)
post.N.dens$d = m.N$f(post.N.dens$N)
# plot posterior density
plot(d~N, post.N.dens, ylab = expression(f(N~'|'~bold(c),r)))