Title: | Implementations of Various Slice Samplers |
Version: | 0.3.1 |
Description: | Implementations of the quantile slice sampler of Heiner et al. (2024+, in preparation) as well as other popular slice samplers are provided. Helper functions for specifying pseudo-target distributions are included, both for diagnostics and for tuning the quantile slice sampler. Other implemented methods include the generalized elliptical slice sampler of Nishihara et al. (2014)<https://jmlr.org/papers/v15/nishihara14a.html}, latent slice sampler of Li and Walker (2023)<doi:10.1016/j.csda.2022.107652>, and stepping-out slice sampler of Neal (2003)<doi:10.1214/aos/1056562461>, and independence Metropolis-Hastings sampler. |
License: | MIT + file LICENSE | Apache License 2.0 |
Depends: | R (≥ 4.1.0) |
Encoding: | UTF-8 |
Suggests: | knitr, rmarkdown |
VignetteBuilder: | knitr |
RoxygenNote: | 7.3.1 |
NeedsCompilation: | no |
Packaged: | 2024-05-29 22:50:32 UTC; dahl |
Author: | Matthew Heiner |
Maintainer: | David B. Dahl <dahl@stat.byu.edu> |
Repository: | CRAN |
Date/Publication: | 2024-05-30 08:00:02 UTC |
Area Under the Curve (histogram)
Description
Calculate the histogram approximation to the area under the curve after restricting the curve to fit within the unit square. Specifically, the highest histogram bar reaches 1 and the support is the unit interval. See Heiner et al. (2024+).
Usage
auc(u = NULL, x = NULL, y = NULL, nbins = 30)
Arguments
u |
Numeric vector of samples supported on unit interval with which to
create a histogram (use |
x |
Numeric vector of histogram locations. (Not used if |
y |
Numeric vector of histogram heights OR function evaluating the curve
for a given value of |
nbins |
Number of histogram bins to use (defaults to 30). |
Details
Accepts either samples u
or a function y
representing a (possibly
unnormalized) probability density supported on the unit interval.
Value
The (approximate) area under the curve as a numeric value of length one.
References
Heiner, M. J., Johnson, S. B., Christensen, J. R., and Dahl, D. B. (2024+), "Quantile Slice Sampling," arXiv preprint arXiv:###.
Examples
u_samples <- rbeta(10e3, 2, 2)
auc(u = u_samples)
auc(u = u_samples, nbins = 50)
auc(y = function(x) {dbeta(x, 2, 2)}, nbins = 30)
auc(y = function(x) {dbeta(x, 2, 2)}, nbins = 300)
xx <- seq(0.001, 0.999, length = 1000)
auc(x = xx, y = function(x) {dbeta(x, 2, 2)})
auc(x = xx, y = dbeta(xx, 2, 2))
Independence Metropolis-Hastings
Description
Independence Metropolis-Hastings
Usage
imh_pseudo(x, log_target, pseudo)
Arguments
x |
The current state (scalar or numeric vector). |
log_target |
A function taking a scalar or numeric vector that evaluates the log-target density, returning a numeric scalar. |
pseudo |
List specifying the pseudo-target (proposal distribution). If the list length is
equal to the number of dimensions in If |
Value
A list containing the new state, x
, and whether the proposed value was accepted, logical accpt
.
Examples
lf <- function(x) dbeta(x[1], 3, 4, log = TRUE) + dbeta(x[2], 5, 3, log = TRUE)
n_iter <- 100 # set to 1e3 for more complete illustration
draws <- matrix(0.2, nrow = n_iter, ncol = 2)
nAccpt <- 0L
pseudo <- list( list(ld = function(x) dbeta(x, 2, 2, log = TRUE),
q = function(u) qbeta(u, 2, 2)),
list(ld = function(x) dbeta(x, 2, 2, log = TRUE),
q = function(u) qbeta(u, 2, 2))
)
for (i in seq.int(2, n_iter)) {
out <- imh_pseudo(draws[i - 1, ], log_target = lf, pseudo = pseudo)
draws[i,] <- out$x
nAccpt <- nAccpt + out$accpt
cat(i, '\r')
}
nAccpt / (nrow(draws) - 1)
plot(draws[,1], draws[,2], xlim = c(0, 1))
hist(draws[,1], freq = FALSE); curve(dbeta(x, 3, 4), col = "blue", add = TRUE)
hist(draws[,2], freq = FALSE); curve(dbeta(x, 5, 3), col = "blue", add = TRUE)
Pseudo-target from Laplace Approximation
Description
Find the location and scale for an approximating pseudo-target via Laplace approximation.
Usage
lapprox(
log_target,
init,
family = "t",
params = NULL,
sc_adj = 1,
lb = -Inf,
ub = Inf,
maxit = 100,
...
)
Arguments
log_target |
Univariate function evaluating the unnormalized log density to approximate. |
init |
Numeric scalar for an initial value (used in optimization). |
family |
String specifying the family of distributions for the pseudo-target. Can be any of the families accepted by pseudo_list. |
params |
List specifying the parameters for the pseudo-target to be used. The location and scale parameters will be replaced with the Laplace approximation and others (e.g., degrees of freedom) will be retained. |
sc_adj |
Positive numeric scalar; manual multiplicative adjustment to the scale of the output pseudo-target. |
lb |
Numeric scalar giving the value of left truncation of the resulting pseudo-target.
Defaults to |
ub |
Numeric scalar giving the value of right truncation of the resulting pseudo-target.
Defaults to |
maxit |
See optim. |
... |
See optim. |
Value
A list with the same outputs as pseudo_list; also includes
opt
, which gives output of optim.
Examples
pseu <- lapprox(function(x) dnorm(x, log = TRUE),
family = "t",
params = list(loc = NA, sc = NA, degf = 5.0),
init = 0.5, lb = -1.0)
curve(dnorm(x)/(1- pnorm(-1)), from = -1, to = 6, col = "blue")
xx <- seq(-1, 6, length = 500)
lines(xx, sapply(xx, FUN = pseu$d))
Sequence of conditional pseudo-targets from a realization
Description
Given a realization of a random vector, generate a the corresponding sequence of conditional pseudo-target inverse CDFs (Heiner et al., 2024+). The pseudo-target is specified as a sequence of growing conditional distributions.
Usage
pseudo_condseq(x, pseudo_init, loc_fn, sc_fn, lb, ub)
Arguments
x |
A numeric vector of values between 0 and 1. |
pseudo_init |
A list output from pseudo_list describing the
marginal pseudo-target for |
loc_fn |
A function that specifies the location of a conditional
pseudo-target given the elements in |
sc_fn |
A function that specifies the scale of a conditional
pseudo-target given the elements in |
lb |
A numeric vector (same length as |
ub |
A numeric vector (same length as |
Details
See the documentation for slice_quantile_mv_seq for examples.
Value
A list containing a sequence of pseudo-targets, each from pseudo_list.
References
Heiner, M. J., Johnson, S. B., Christensen, J. R., and Dahl, D. B. (2024+), "Quantile Slice Sampling," arXiv preprint arXiv:###
Examples
# Funnel distribution from Neal (2003).
K <- 10
n_iter <- 50 # MCMC iterations; set to 10e3 for more complete illustration
n <- 100 # number of iid samples from the target; set to 10e3 for more complete illustration
Y <- matrix(NA, nrow = n, ncol = K) # iid samples from the target
Y[,1] <- rnorm(n, 0.0, 3.0)
for (i in 1:n) {
Y[i, 2:K] <- rnorm(K-1, 0.0, exp(0.5*Y[i,1]))
}
ltarget <- function(x) {
dnorm(x[1], 0.0, 3.0, log = TRUE) +
sum(dnorm(x[2:K], 0.0, exp(0.5*x[1]), log = TRUE))
}
pseudo_control <- list(
loc_fn = function(x) {
0.0
},
sc_fn = function(x) {
if (is.null(x)) {
out <- 3.0
} else {
out <- exp(0.5*x[1])
}
out
},
pseudo_init = pseudo_list(family = "t",
params = list(loc = 0.0, sc = 3.0, degf = 20),
lb = -Inf, ub = Inf),
lb = rep(-Inf, K),
ub = rep(Inf, K)
)
x0 <- runif(K)
draws <- matrix(rep(x0, n_iter + 1), nrow = n_iter + 1, byrow = TRUE)
draws_u <- matrix(rep(x0, n_iter), nrow = n_iter, byrow = TRUE)
n_eval <- 0
for (i in 2:(n_iter + 1)) {
tmp <- slice_quantile_mv_seq(draws[i-1,],
log_target = ltarget,
pseudo_control = pseudo_control)
draws[i,] <- tmp$x
draws_u[i-1,] <- tmp$u
n_eval <- n_eval + tmp$nEvaluations
}
# (es <- coda::effectiveSize(coda::as.mcmc(draws)))
# mean(es)
n_eval / n_iter
sapply(1:K, function (k) auc(u = draws_u[,k]))
hist(draws_u[,1])
plot(draws[,1], draws[,2])
points(Y[,1], Y[,2], col = "blue", cex = 0.5)
Inverse transform from sequence of conditional pseudo-targets
Description
Given a vector of from a unit hypercube, map to the original (back-transformed) vector using a sequence of conditional pseudo-target inverse CDFs. The pseudo-target is specified as a sequence of growing conditional distributions.
Usage
pseudo_condseq_XfromU(u, pseudo_init, loc_fn, sc_fn, lb, ub)
Arguments
u |
A numeric vector of values between 0 and 1. |
pseudo_init |
A list output from pseudo_list describing the
marginal pseudo-target for |
loc_fn |
A function that specifies the location of a conditional
pseudo-target given the elements in |
sc_fn |
A function that specifies the scale of a conditional
pseudo-target given the elements in |
lb |
A numeric vector (same length as |
ub |
A numeric vector (same length as |
Details
See the documentation for slice_quantile_mv_seq for examples.
Value
A list containing x
obtained from the sequence of inverse
CDFs, and pseudo_seq
, a list of the corresponding sequential
pseudo-targets output from pseudo_list.
Examples
# Funnel distribution from Neal (2003).
K <- 10
n_iter <- 50 # MCMC iterations; set to 10e3 for more complete illustration
n <- 100 # number of iid samples from the target; set to 10e3 for more complete illustration
Y <- matrix(NA, nrow = n, ncol = K) # iid samples from the target
Y[,1] <- rnorm(n, 0.0, 3.0)
for (i in 1:n) {
Y[i, 2:K] <- rnorm(K-1, 0.0, exp(0.5*Y[i,1]))
}
ltarget <- function(x) {
dnorm(x[1], 0.0, 3.0, log = TRUE) +
sum(dnorm(x[2:K], 0.0, exp(0.5*x[1]), log = TRUE))
}
pseudo_control <- list(
loc_fn = function(x) {
0.0
},
sc_fn = function(x) {
if (is.null(x)) {
out <- 3.0
} else {
out <- exp(0.5*x[1])
}
out
},
pseudo_init = pseudo_list(family = "t",
params = list(loc = 0.0, sc = 3.0, degf = 20),
lb = -Inf, ub = Inf),
lb = rep(-Inf, K),
ub = rep(Inf, K)
)
x0 <- runif(K)
draws <- matrix(rep(x0, n_iter + 1), nrow = n_iter + 1, byrow = TRUE)
draws_u <- matrix(rep(x0, n_iter), nrow = n_iter, byrow = TRUE)
n_eval <- 0
for (i in 2:(n_iter + 1)) {
tmp <- slice_quantile_mv_seq(draws[i-1,],
log_target = ltarget,
pseudo_control = pseudo_control)
draws[i,] <- tmp$x
draws_u[i-1,] <- tmp$u
n_eval <- n_eval + tmp$nEvaluations
}
# (es <- coda::effectiveSize(coda::as.mcmc(draws)))
# mean(es)
n_eval / n_iter
sapply(1:K, function (k) auc(u = draws_u[,k]))
hist(draws_u[,1])
plot(draws[,1], draws[,2])
points(Y[,1], Y[,2], col = "blue", cex = 0.5)
Specify a pseudo-target within a given class
Description
Create a list of functions to evaluate a pseudo-target in a given class with supplied parameters (usually location and scale). The distribution is optionally truncated to specified bounds (and renormalized). See Heiner et al. (2024+).
Usage
pseudo_list(family, params, lb = -Inf, ub = Inf, log_p = FALSE, name = NULL)
Arguments
family |
String identifying the distribution family. One of |
params |
Named list identifying parameters, which vary by distribution family.
|
lb |
Numeric scalar giving the value of left truncation. Defaults to |
ub |
Numeric scalar giving the value of right truncation. Defaults to |
log_p |
(Not implemented) Logical: evaluate distribution and quantile functions using the log probability. |
name |
String appending optional message to the textual name of the distribution. |
Details
The supported classes of pseudo-targets include: t
, cauchy
,
normal
, logistic
, and beta
.
Value
A list with named components:
d
: function to evaluate the density
ld
: function to evaluate the log density
q
: function to evaluate the quantile function
p
: function to evaluate the distribution function
txt
: text description of the distribution
params
: repeats the params
argument
lb
: lower boundary of support
ub
: upper boundary of support
References
Heiner, M. J., Johnson, S. B., Christensen, J. R., and Dahl, D. B. (2024+), "Quantile Slice Sampling," arXiv preprint arXiv:###
Examples
pseu <- pseudo_list(family = "t", params = list(loc = 0.0, sc = 1.0, degf = 5),
lb = 0.0, ub = Inf) # half t
str(pseu)
pseu$d(1.5)
pseu$ld(1.5)
pseu$p(1.5)
pseu$q(0.8060963)
pseu <- pseudo_list(family = "cauchy", params = list(loc = 0.0, sc = 1.0),
lb = 0.0, ub = Inf) # half Cauchy
str(pseu)
pseu$d(1.5)
pseu$ld(1.5)
pseu$p(1.5)
pseu$q(0.6256659)
pseu <- pseudo_list(family = "normal", params = list(loc = 0.0, sc = 1.0),
lb = 0.0, ub = Inf) # half normal
str(pseu)
pseu$d(1.5)
pseu$ld(1.5)
pseu$p(1.5)
pseu$q(0.8663856)
pseu <- pseudo_list(family = "logistic", params = list(loc = 0.0, sc = 1.0),
lb = 0.0, ub = Inf) # half logistic
str(pseu)
pseu$d(1.5)
pseu$ld(1.5)
pseu$p(1.5)
pseu$q(0.635149)
pseu <- pseudo_list(family = "beta", params = list(shape1 = 2.0, shape2 = 1.0))
str(pseu)
pseu$d(0.5)
pseu$ld(0.5)
pseu$p(0.5)
pseu$q(0.25)
Optimal pseudo-target for a given target
Description
Find an optimal pseudo-target in a specified family to approximate the given (unnormalized) target (Heiner et al., 2024+). Optimize over the selected utility function.
Usage
pseudo_opt(
log_target = NULL,
samples = NULL,
type = "samples",
family = "t",
degf = c(1, 5, 20),
lb = -Inf,
ub = Inf,
utility_type = "AUC",
nbins = 100,
tol_opt = 1e-06,
tol_int = 0.001,
plot = TRUE,
verbose = FALSE
)
Arguments
log_target |
Function to evaluate the log density of the unnormalized target. |
samples |
Optional numeric vector providing samples from the target distribution
(for use as alternative to |
type |
String specifying the input type. One of "function", "samples", or "grid". Default is to use "samples". Use of "function" requires specification of Use of "samples" requires specification of |
family |
String specifying the family of distributions for the pseudo-target. Can be any of the families accepted by pseudo_list. |
degf |
Numeric vector of degrees of freedom values to try (only if |
lb |
Numeric scalar giving the value of left truncation. Defaults to |
ub |
Numeric scalar giving the value of right truncation. Defaults to |
utility_type |
String identifying utility type, either AUC (default) or MSW. |
nbins |
Positive integer specifying the number of histogram bins if using "samples" or "grid". Defaults to 100. |
tol_opt |
Positive numeric scalar that passes to |
tol_int |
Positive numeric scalar that passes to |
plot |
Logical for whether to generate two plots:
Defaults to |
verbose |
Logical for whether to print intermediate steps of optimization.
Defaults to |
Details
Optionally supply samples from the target distribution.
Value
A list with named components:
pseudo
: a list with functions corresponding to the selected pseudo-target;
output of pseudo_list.
utility
: value of the utility function using the selected pseudo-target;
output of utility_pseudo.
utility_type
: repeats the input specifying the utility type.
opt
: output of optim.
Other outputs repeating inputs.
References
Heiner, M. J., Johnson, S. B., Christensen, J. R., and Dahl, D. B. (2024+), "Quantile Slice Sampling," arXiv preprint arXiv:###
Examples
(pseu <- pseudo_opt(samples = rnorm(1e3), type = "samples",
family = "t", utility_type = "AUC",
nbins = 10, plot = TRUE,
verbose = FALSE))
oldpar <- par(mfrow = c(1,2))
(pseu <- pseudo_opt(log_target = function(x) dnorm(x, log = TRUE),
type = "function",
family = "logistic", utility_type = "AUC",
nbins = 100, plot = TRUE,
verbose = FALSE))
(pseu <- pseudo_opt(log_target = function(x) dbeta(x, 4, 2, log = TRUE),
lb = 0, ub = 1,
type = "function",
family = "cauchy", utility_type = "AUC",
nbins = 30, plot = TRUE,
verbose = FALSE))
par(oldpar)
Univariate Elliptical Slice Sampler
Description
Algorithm 1 of Nishihara et al. (2014) of the elliptical slice sampler of Murray et al. (2010).
Usage
slice_elliptical(x, log_target, mu, sigma)
Arguments
x |
The current state (as a numeric scalar). |
log_target |
A function taking numeric scalar that evaluates the (potentially unnormalized) log-target density, returning a numeric scalar. |
mu |
A numeric scalar with the mean of the supporting normal distribution. |
sigma |
A numeric scalar with the standard deviation of the supporting normal distribution. |
Value
A list with two elements:
x
is the new state.
nEvaluations
is the number of evaluations of the target function used to obtain the new
state.
References
Murray, I., Adams, R., and MacKay, D., (2010), "Elliptical Slice Sampling," in Proceedings of the Thirteenth International Conference on Artificial Intelligence and Statistics, JMLR Workshop and Conference Proceedings. https://proceedings.mlr.press/v9/murray10a
Nishihara, R., Murray, I., and Adams, R. P. (2014), "Parallel MCMC with Generalized Elliptical Slice Sampling," Journal of Machine Learning Research, 15, 2087-2112. https://jmlr.org/papers/v15/nishihara14a.html
Examples
lf <- function(x) dbeta(x, 3, 4, log = TRUE)
draws <- numeric(10) # set to numeric(1e3) for more complete illustration
nEvaluations <- 0L
for (i in seq.int(2, length(draws))) {
out <- slice_elliptical(draws[i - 1], log_target = lf, mu = 0.5, sigma = 1)
draws[i] <- out$x
nEvaluations <- nEvaluations + out$nEvaluations
}
nEvaluations / (length(draws) - 1)
plot(density(draws), xlim = c(0, 1))
curve(exp(lf(x)), 0, 1, col = "blue", add = TRUE)
Multivariate Elliptical Slice Sampler
Description
Algorithm 1 of Nishihara et al. (2014) of the elliptical slice sampler of Murray et al. (2010).
Usage
slice_elliptical_mv(x, log_target, mu, Sig, is_chol = FALSE)
Arguments
x |
The current state (as a numeric scalar). |
log_target |
A function taking numeric scalar that evaluates the (potentially unnormalized) log-target density, returning a numeric scalar. |
mu |
Numeric vector with the mean of the supporting normal distribution. |
Sig |
Positive definite covariance matrix. Alternatively, a lower-triangular matrix with the Cholesky factor of the covariance matrix (for faster computation). |
is_chol |
Logical, is the supplied |
Value
A list with two elements:
x
is the new state.
nEvaluations
is the number of evaluations of the target function used to obtain the new
state.
References
Murray, I., Adams, R., and MacKay, D., (2010), "Elliptical Slice Sampling," in Proceedings of the Thirteenth International Conference on Artificial Intelligence and Statistics, JMLR Workshop and Conference Proceedings. https://proceedings.mlr.press/v9/murray10a
Nishihara, R., Murray, I., and Adams, R. P. (2014), "Parallel MCMC with Generalized Elliptical Slice Sampling," Journal of Machine Learning Research, 15, 2087-2112. https://jmlr.org/papers/v15/nishihara14a.html
Examples
lf <- function(x) dbeta(x[1], 3, 4, log = TRUE) + dbeta(x[2], 5, 3, log = TRUE)
n_iter <- 10 # set to 1e3 for more complete illustration
draws <- matrix(0.3, nrow = n_iter, ncol = 2)
nEvaluations <- 0L
for (i in seq.int(2, n_iter)) {
out <- slice_elliptical_mv(draws[i - 1,], log_target = lf,
mu = c(0.5, 0.5), Sig = matrix(c(0.5, 0.25, 0.25, 0.5), nrow = 2))
draws[i,] <- out$x
nEvaluations <- nEvaluations + out$nEvaluations
}
nEvaluations / (n_iter - 1)
plot(draws[,1], draws[,2], xlim = c(0, 1))
hist(draws[,1], freq = FALSE); curve(dbeta(x, 3, 4), col = "blue", add = TRUE)
hist(draws[,2], freq = FALSE); curve(dbeta(x, 5, 3), col = "blue", add = TRUE)
Generalized Elliptical Slice Sampler (univariate)
Description
Single update using the generalized elliptical slice sampler of Nishihara et al. (2014).
Usage
slice_genelliptical(x, log_target, mu, sigma, df)
Arguments
x |
The current state (as a numeric scalar). |
log_target |
A function taking numeric scalar that evaluates the (potentially unnormalized) log-target density, returning a numeric scalar. |
mu |
A numeric scalar with the mean of the supporting normal distribution. |
sigma |
A numeric scalar with the standard deviation of the supporting normal distribution. |
df |
Degrees of freedom of Student t pseudo-target. |
Value
A list contains two elements:
x
is the new state.
nEvaluations
is the number of evaluations of the target function used to obtain the new
state.
References
Nishihara, R., Murray, I., and Adams, R. P. (2014), "Parallel MCMC with Generalized Elliptical Slice Sampling," Journal of Machine Learning Research, 15, 2087-2112. https://jmlr.org/papers/v15/nishihara14a.html
Examples
lf <- function(x) dbeta(x, 3, 4, log = TRUE)
draws <- numeric(10) # set to numeric(1e3) for more complete illustration
nEvaluations <- 0L
for (i in seq.int(2, length(draws))) {
out <- slice_genelliptical(draws[i - 1], log_target = lf,
mu = 0.5, sigma = 1, df = 5)
draws[i] <- out$x
nEvaluations <- nEvaluations + out$nEvaluations
}
nEvaluations / (length(draws) - 1)
plot(density(draws), xlim = c(0, 1))
curve(exp(lf(x)), 0, 1, col = "blue", add = TRUE)
Generalized Elliptical Slice Sampler (Multivariate)
Description
Generalized Elliptical Slice Sampler, Algorithm 2 of Nishihara et al. (2014)
Usage
slice_genelliptical_mv(x, log_target, mu, Sig, df, is_chol = FALSE)
Arguments
x |
The current state (as a numeric scalar). |
log_target |
A function taking numeric scalar that evaluates the (potentially unnormalized) log-target density, returning a numeric scalar. |
mu |
Numeric vector with the mean of the supporting normal distribution. |
Sig |
Positive definite covariance matrix. Alternatively, a lower-triangular matrix with the Cholesky factor of the covariance matrix (for faster computation). |
df |
Degrees of freedom of Student t pseudo-target. |
is_chol |
Logical, is the supplied |
Value
A list contains two elements: x
is the new state and nEvaluations
is the number of evaluations of the target function used to obtain the new
state.
References
Nishihara, R., Murray, I., and Adams, R. P. (2014), "Parallel MCMC with Generalized Elliptical Slice Sampling," Journal of Machine Learning Research, 15, 2087-2112. https://jmlr.org/papers/v15/nishihara14a.html
Examples
lf <- function(x) dbeta(x[1], 3, 4, log = TRUE) + dbeta(x[2], 5, 3, log = TRUE)
n_iter <- 10 # set to 1e4 for more complete illustration
draws <- matrix(0.3, nrow = n_iter, ncol = 2)
nEvaluations <- 0L
for (i in seq.int(2, n_iter)) {
out <- slice_genelliptical_mv(draws[i - 1,], log_target = lf,
mu = c(0.5, 0.5), Sig = matrix(c(0.5, 0.25, 0.25, 0.5), nrow = 2),
df = 5)
draws[i,] <- out$x
nEvaluations <- nEvaluations + out$nEvaluations
}
nEvaluations / (n_iter - 1)
plot(draws[,1], draws[,2], xlim = c(0, 1))
hist(draws[,1], freq = FALSE); curve(dbeta(x, 3, 4), col = "blue", add = TRUE)
hist(draws[,2], freq = FALSE); curve(dbeta(x, 5, 3), col = "blue", add = TRUE)
Multivariate Slice Sampler with Shrinking Hyperrectangle
Description
Multivariate slice sampler in Algorithm 8 of Neal (2003) using the "shrinkage" procedure.
Usage
slice_hyperrect(x, log_target, w = NULL, L = NULL, R = NULL)
Arguments
x |
The current state (as a numeric vector). |
log_target |
A function taking numeric vector that evaluates the log-target density, returning a numeric scalar. |
w |
A numeric vector tuning the algorithm which gives the typical slice
width in each dimension. This is a main tuning parameter of the algorithm.
If |
L |
Numeric vector giving the lower boundary of support in each dimension. |
R |
Numeric vector giving the upper boundary of support in each dimension.
Will be used if |
Value
A list contains two elements: "x" is the new state and "nEvaluations" is the number of evaluations of the target function used to obtain the new state.
References
Neal, R. M. (2003), "Slice sampling," The Annals of Statistics, 31, 705-767. doi:10.1214/aos/1056562461
Examples
lf <- function(x) dbeta(x[1], 3, 4, log = TRUE) + dbeta(x[2], 5, 3, log = TRUE)
n_iter <- 10 # set to 1e4 for more complete illustration
draws <- matrix(0.2, nrow = n_iter, ncol = 2)
nEvaluations <- 0L
for (i in seq.int(2, n_iter)) {
out <- slice_hyperrect(draws[i - 1, ], log_target = lf, w = c(0.5, 0.5))
draws[i,] <- out$x
nEvaluations <- nEvaluations + out$nEvaluations
cat(i, '\r')
}
nEvaluations / (nrow(draws) - 1)
plot(draws[,1], draws[,2], xlim = c(0, 1))
hist(draws[,1], freq = FALSE); curve(dbeta(x, 3, 4), col = "blue", add = TRUE)
hist(draws[,2], freq = FALSE); curve(dbeta(x, 5, 3), col = "blue", add = TRUE)
Latent Slice Sampler
Description
Single update using the latent slice sampler of Li and Walker (2023).
Usage
slice_latent(x, s, log_target, rate)
Arguments
x |
The current state (as a numeric scalar). |
s |
A random variable that determines the length of the initial shrinking interval. |
log_target |
A function taking numeric scalar that evaluates the (potentially unnormalized) log-target density, returning a numeric scalar. |
rate |
The rate parameter for the distribution of |
Value
A list containing three elements:
x
is the new state of the target variable.
s
is the new state of the latent scale variable.
nEvaluations
is the number of evaluations of the
target function used to obtain the new state.
References
Li, Y. and Walker, S. G. (2023), "A latent slice sampling algorithm," Computational Statistics and Data Analysis, 179, 107652. doi:10.1016/j.csda.2022.107652
Examples
lf <- function(x) dbeta(x, 3, 4, log = TRUE)
draws <- numeric(10) # set to numeric(1e3) for more complete illustration
nEvaluations <- 0L
s <- 0.5
for (i in seq.int(2, length(draws))) {
out <- slice_latent(draws[i - 1], s, log_target = lf, rate = 0.3)
draws[i] <- out$x
s <- out$s
nEvaluations <- nEvaluations + out$nEvaluations
}
nEvaluations / (length(draws) - 1)
plot(density(draws), xlim = c(0, 1))
curve(exp(lf(x)), 0, 1, col = "blue", add = TRUE)
Quantile Slice Sampler
Description
Single update using a quantile slice sampler of Heiner et al. (2024+).
Usage
slice_quantile(x, log_target, pseudo)
Arguments
x |
The current state (as a numeric scalar). |
log_target |
A function taking numeric scalar that evaluates the (potentially unnormalized) log-target density, returning a numeric scalar. |
pseudo |
List containing two functions specifying the pseudo-target distribution:
|
Value
A list containing three elements:
x
is the new state.
u
is the value of the CDF of the psuedo-target associated with the
returned value (also referred to as psi).
nEvaluations
is the number of evaluations of the
target function used to obtain the new state.
References
Heiner, M. J., Johnson, S. B., Christensen, J. R., and Dahl, D. B. (2024+), "Quantile Slice Sampling," arXiv preprint arXiv:###.
Examples
lf <- function(x) dbeta(x, 3, 4, log = TRUE)
pseu <- list(ld = function(x) dbeta(x, shape1 = 1, shape2 = 1, log = TRUE),
q = function(u) qbeta(u, shape1 = 1, shape2 = 1))
draws <- numeric(10) # set to numeric(1e3) for more complete illustration
nEvaluations <- 0L
for (i in seq.int(2, length(draws))) {
out <- slice_quantile(draws[i - 1], log_target = lf, pseudo = pseu)
draws[i] <- out$x
nEvaluations <- nEvaluations + out$nEvaluations
}
nEvaluations / (length(draws) - 1)
plot(density(draws), xlim = c(0, 1))
curve(exp(lf(x)), 0, 1, col = "blue", add = TRUE)
Multivariate Quantile Slice Sampler
Description
Quantile slice sampler for a random vector (Heiner et al., 2024+). The pseudo-target is specified through independent univariate distributions.
Usage
slice_quantile_mv(x, log_target, pseudo)
Arguments
x |
The current state (as a numeric vector). |
log_target |
A function taking numeric vector that evaluates the log-target density, returning a numeric scalar. |
pseudo |
List of length equal to the number of dimensions in |
Value
A list containing three elements: "x" is the new state, "u" is the value of the CDF of the psuedo-target associated with the returned value, inverse CDF method, and "nEvaluations is the number of evaluations of the target function used to obtain the new state.
References
Heiner, M. J., Johnson, S. B., Christensen, J. R., and Dahl, D. B. (2024+), "Quantile Slice Sampling," arXiv preprint arXiv:###
Examples
lf <- function(x) dbeta(x[1], 3, 4, log = TRUE) + dbeta(x[2], 5, 3, log = TRUE)
ps_shsc <- list(c(2, 2), c(2, 1))
ps <- list(
list(ld = function(x) dbeta(x, ps_shsc[[1]][1], ps_shsc[[1]][2], log = TRUE),
p = function(x) pbeta(x, ps_shsc[[1]][1], ps_shsc[[1]][2]),
q = function(x) qbeta(x, ps_shsc[[1]][1], ps_shsc[[1]][2]) ),
list(ld = function(x) dbeta(x, ps_shsc[[2]][1], ps_shsc[[2]][2], log = TRUE),
p = function(x) pbeta(x, ps_shsc[[2]][1], ps_shsc[[2]][2]),
q = function(x) qbeta(x, ps_shsc[[2]][1], ps_shsc[[2]][2]) )
)
n_iter <- 10 # set to 1e4 for more complete illustration
draws <- matrix(0.2, nrow = n_iter, ncol = 2)
draws_u <- draws
draws_u[1,] <- sapply(1:length(ps), function(k) ps[[k]]$p(draws[1,k]))
nEvaluations <- 0L
for (i in seq.int(2, n_iter)) {
out <- slice_quantile_mv(draws[i - 1, ], log_target = lf, pseudo = ps)
draws[i,] <- out$x
draws_u[i,] <- out$u
nEvaluations <- nEvaluations + out$nEvaluations
cat(i, '\r')
}
nEvaluations / (nrow(draws) - 1)
plot(draws[,1], draws[,2], xlim = c(0, 1))
hist(draws[,1], freq = FALSE); curve(dbeta(x, 3, 4), col = "blue", add = TRUE)
hist(draws[,2], freq = FALSE); curve(dbeta(x, 5, 3), col = "blue", add = TRUE)
plot(draws_u[,1], draws_u[,2], xlim = c(0, 1))
hist(draws_u[,1], freq = FALSE)
hist(draws_u[,2], freq = FALSE)
auc(u = draws_u[,1])
auc(u = draws_u[,2])
Multivariate Quantile Slice Sampler from a sequence of conditional pseudo-targets
Description
Quantile slice sampler for a random vector (Heiner et al., 2024+). The pseudo-target is specified as a sequence of growing conditional distributions.
Usage
slice_quantile_mv_seq(x, log_target, pseudo_control)
Arguments
x |
The current state (as a numeric vector). |
log_target |
A function taking numeric vector that evaluates the log-target density, returning a numeric scalar. |
pseudo_control |
A list with
|
Value
A list containing three elements: "x" is the new state, "u" is a vector of values of the sequence of conditional CDFs of the psuedo-targets associated with the returned value, and "nEvaluations is the number of evaluations of the target function used to obtain the new state.
References
Heiner, M. J., Johnson, S. B., Christensen, J. R., and Dahl, D. B. (2024+), "Quantile Slice Sampling," arXiv preprint arXiv:###
Examples
# Funnel distribution from Neal (2003).
K <- 10
n_iter <- 50 # MCMC iterations; set to 10e3 for more complete illustration
n <- 100 # number of iid samples from the target; set to 10e3 for more complete illustration
Y <- matrix(NA, nrow = n, ncol = K) # iid samples from the target
Y[,1] <- rnorm(n, 0.0, 3.0)
for (i in 1:n) {
Y[i, 2:K] <- rnorm(K-1, 0.0, exp(0.5*Y[i,1]))
}
ltarget <- function(x) {
dnorm(x[1], 0.0, 3.0, log = TRUE) +
sum(dnorm(x[2:K], 0.0, exp(0.5*x[1]), log = TRUE))
}
pseudo_control <- list(
loc_fn = function(x) {
0.0
},
sc_fn = function(x) {
if (is.null(x)) {
out <- 3.0
} else {
out <- exp(0.5*x[1])
}
out
},
pseudo_init = pseudo_list(family = "t",
params = list(loc = 0.0, sc = 3.0, degf = 20),
lb = -Inf, ub = Inf),
lb = rep(-Inf, K),
ub = rep(Inf, K)
)
x0 <- runif(K)
draws <- matrix(rep(x0, n_iter + 1), nrow = n_iter + 1, byrow = TRUE)
draws_u <- matrix(rep(x0, n_iter), nrow = n_iter, byrow = TRUE)
n_eval <- 0
for (i in 2:(n_iter + 1)) {
tmp <- slice_quantile_mv_seq(draws[i-1,],
log_target = ltarget,
pseudo_control = pseudo_control)
draws[i,] <- tmp$x
draws_u[i-1,] <- tmp$u
n_eval <- n_eval + tmp$nEvaluations
}
# (es <- coda::effectiveSize(coda::as.mcmc(draws)))
# mean(es)
n_eval / n_iter
sapply(1:K, function (k) auc(u = draws_u[,k]))
hist(draws_u[,1])
plot(draws[,1], draws[,2])
points(Y[,1], Y[,2], col = "blue", cex = 0.5)
Slice sampler using the Stepping Out and Shrinkage Procedures
Description
Single update for the univariate slice sampler of Neal (2003) using the "stepping out" procedure, followed by the "shrinkage" procedure.
Usage
slice_stepping_out(x, log_target, w, max = Inf)
Arguments
x |
The current state (as a numeric scalar). |
log_target |
A function taking numeric scalar that evaluates the (potentially unnormalized) log-target density, returning a numeric scalar. |
w |
A numeric scalar tuning the algorithm which gives the typical slice width. This is a main tuning parameter of the algorithm. |
max |
The maximum number of times to step out. Setting |
Value
A list with two elements:
x
is the new state.
nEvaluations
is the number of evaluations of the target function used to obtain the new
state.
References
Neal, R. M. (2003), "Slice sampling," The Annals of Statistics, 31, 705-767. doi:10.1214/aos/1056562461
Examples
lf <- function(x) dbeta(x, 3, 4, log = TRUE)
draws <- numeric(10) + 0.5 # set to numeric(1e3) for more complete illustration
nEvaluations <- 0L
for (i in seq.int(2, length(draws))) {
out <- slice_stepping_out(draws[i - 1], log_target = lf, w = 0.7, max = Inf)
draws[i] <- out$x
nEvaluations <- nEvaluations + out$nEvaluations
}
nEvaluations / (length(draws) - 1)
plot(density(draws), xlim = c(0, 1))
curve(exp(lf(x)), 0, 1, col = "blue", add = TRUE)
Utility for a given target and pseudo-target
Description
Takes a pseudo-target and target (or samples from the target) and evaluates the utility function for the transformed target, which can be one of Area Under the Curve (AUC) and Mean Slice Width (MSW). See Heiner et al. (2024+).
Usage
utility_pseudo(
pseudo,
log_target = NULL,
samples = NULL,
type = "samples",
x = NULL,
nbins = 30,
plot = TRUE,
utility_type = "AUC",
tol_int = 0.001
)
Arguments
pseudo |
List containing the following functions with scalar input:
|
log_target |
Function to evaluate the log density of the unnormalized target. |
samples |
Numeric vector of samples from the target distribution. |
type |
String specifying the input type. One of "function", "samples", or "grid". Default is to use "samples". Use of "function" requires specification of Use of "samples" requires specification of Use of "grid" requires specification of |
x |
Numeric vector specifying grid (on (0,1)) over which to evaluate
the transformed target. Defaults to |
nbins |
Number of histogram bins to use (defaults to 30). Must match the length
of |
plot |
Logical for whether to generate two plots:
Defaults to |
utility_type |
String identifying utility type, either AUC (default) or MSW. |
tol_int |
Positive numeric scalar that passes to |
Details
Optionally plot the target and pseudo-target densities as well as the transformed tartet.
Value
Scalar value of the utility function evaluation.
References
Heiner, M. J., Johnson, S. B., Christensen, J. R., and Dahl, D. B. (2024+), "Quantile Slice Sampling," arXiv preprint arXiv:###.
Examples
pseu <- pseudo_list(family = "logistic", params = list(loc = 0.0, sc = 0.66))
ltarg <- list(ld = function(x) dnorm(x, log = TRUE))
oldpar <- par(mfrow = c(1,2))
utility_pseudo(pseudo = pseu, log_target = ltarg$ld, type = "function",
nbins = 100, utility_type = "MSW")
samp <- rnorm(10e3)
utility_pseudo(pseudo = pseu, samples = samp, type = "samples", utility_type = "AUC")
utility_pseudo(pseudo = pseu, samples = samp, type = "samples", utility_type = "MSW")
par(oldpar)