Nothing
#' @title Prior Normal
#' @param mean prior mean
#' @param sd prior standard deviation
#' @param target apply prior on coefficient scale (`"coef"`) or field scale (`"field"`)
#' @return prior specification
#' @export
prior_normal <- function(mean = 0, sd = 1, target = "coef") {
target <- .validate_prior_target(target)
stopifnot(
is.numeric(mean), length(mean) == 1, is.finite(mean),
is.numeric(sd), length(sd) == 1, is.finite(sd), sd > 0
)
structure(
list(dist = "normal", hyper = c(mean = mean, sd = sd), target = target),
class = "ngme_prior_spec"
)
}
#' @title Prior PC-SD
#' @param u tail event threshold
#' @param alpha tail probability
#' @param target apply prior on coefficient scale (`"coef"`) or field scale (`"field"`)
#' @return prior specification
#' @export
prior_pc_sd <- function(u, alpha, target = "coef") {
target <- .validate_prior_target(target)
stopifnot(
is.numeric(u), length(u) == 1, is.finite(u), u > 0,
is.numeric(alpha), length(alpha) == 1, is.finite(alpha),
alpha > 0, alpha < 1
)
structure(
list(dist = "pc.sd", hyper = c(u = u, alpha = alpha), target = target),
class = "ngme_prior_spec"
)
}
#' @title Prior Half-Cauchy
#' @param scale half-Cauchy scale
#' @param target apply prior on coefficient scale (`"coef"`) or field scale (`"field"`)
#' @return prior specification
#' @export
prior_half_cauchy <- function(scale = 1, target = "coef") {
target <- .validate_prior_target(target)
stopifnot(
is.numeric(scale), length(scale) == 1, is.finite(scale), scale > 0
)
structure(
list(dist = "half.cauchy", hyper = c(scale = scale), target = target),
class = "ngme_prior_spec"
)
}
#' @title Prior Inverse-Exponential
#' @description Prior induced by \eqn{\kappa = 1 / \nu \sim \mathrm{Exp}(\lambda)},
#' giving \eqn{p(\nu) = \lambda \exp(-\lambda / \nu)\nu^{-2}} for \eqn{\nu > 0}.
#' Internally this prior is applied to \eqn{\nu = \mathrm{lower} + \exp(\theta)}.
#' @param lambda exponential rate on \eqn{\kappa = 1/\nu}
#' @param lower lower shift used in \eqn{\nu = \mathrm{lower} + \exp(\theta)}
#' @param target apply prior on coefficient scale (`"coef"`) or field scale (`"field"`)
#' @return prior specification
#' @export
prior_inv_exponential <- function(lambda = 1, lower = 0, target = "coef") {
target <- .validate_prior_target(target)
stopifnot(
is.numeric(lambda), length(lambda) == 1, is.finite(lambda), lambda > 0,
is.numeric(lower), length(lower) == 1, is.finite(lower), lower >= 0
)
structure(
list(
dist = "inv.exponential",
hyper = c(lambda = lambda, lower = lower),
target = target
),
class = "ngme_prior_spec"
)
}
#' @rdname prior_inv_exponential
#' @export
prior_inv_exp <- function(lambda = 1, lower = 0, target = "coef") {
prior_inv_exponential(lambda = lambda, lower = lower, target = target)
}
#' @title Prior None
#' @param target apply prior on coefficient scale (`"coef"`) or field scale (`"field"`)
#' @return prior specification
#' @export
prior_none <- function(target = "coef") {
target <- .validate_prior_target(target)
structure(
list(dist = "none", hyper = double(0), target = target),
class = "ngme_prior_spec"
)
}
#' @title Prior Container
#' @param ... named prior specifications
#' @return named prior container
#' @export
priors <- function(...) {
ps <- list(...)
if (length(ps) == 0) {
return(structure(ps, class = "ngme_priors"))
}
nms <- names(ps)
stopifnot(
"priors(...) requires named entries." = !is.null(nms) &&
all(nzchar(nms)) &&
length(unique(nms)) == length(nms),
"All entries in priors(...) must be prior_*() objects." =
all(vapply(ps, inherits, logical(1), what = "ngme_prior_spec"))
)
structure(ps, class = "ngme_priors")
}
.validate_prior_target <- function(target) {
stopifnot(
is.character(target),
length(target) == 1,
target %in% c("coef", "field")
)
target
}
is_prior_spec <- function(x) inherits(x, "ngme_prior_spec")
is_prior_collection <- function(x) inherits(x, "ngme_priors")
as_internal_prior <- function(prior) {
stopifnot("prior must be a prior_*() object." = is_prior_spec(prior))
target <- .validate_prior_target(prior$target)
dist <- prior$dist
hyper <- prior$hyper
internal <- switch(dist,
"none" = list(type = "none", param = double(0), target = target),
"normal" = {
mean <- as.numeric(hyper["mean"])
sd <- as.numeric(hyper["sd"])
list(type = "normal", param = c(mean, 1 / (sd * sd)), target = target)
},
"pc.sd" = {
u <- as.numeric(hyper["u"])
alpha <- as.numeric(hyper["alpha"])
lambda <- -log(alpha) / u
list(type = "pc.sd", param = c(lambda), target = target)
},
"half.cauchy" = {
list(type = "half.cauchy", param = c(as.numeric(hyper["scale"])), target = target)
},
"inv.exponential" = {
lambda <- as.numeric(hyper["lambda"])
lower <- as.numeric(hyper["lower"])
list(type = "inv.exponential", param = c(lambda, lower), target = target)
},
stop("Unknown prior dist: ", dist)
)
internal
}
default_noise_priors <- function() {
priors(
mu = prior_normal(0, 10, target = "coef"),
sigma = prior_normal(0, 10, target = "coef"),
nu = prior_normal(0, 10, target = "coef")
)
}
default_operator_prior <- function() {
prior_normal(0, 10, target = "coef")
}
default_beta_prior <- function() {
prior_normal(0, 10, target = "coef")
}
default_beta_prior_for_param <- function(param_name) {
if (!is.null(param_name) && startsWith(param_name, "(Intercept)")) {
return(prior_none(target = "coef"))
}
default_beta_prior()
}
default_beta_priors <- function(param_names) {
lapply(param_names, default_beta_prior_for_param)
}
compile_noise_priors <- function(prior) {
if (is.null(prior)) prior <- default_noise_priors()
if (is_prior_spec(prior)) {
prior <- priors(mu = prior, sigma = prior, nu = prior)
}
stopifnot("noise prior must be priors(...)." = is_prior_collection(prior))
allowed <- c("mu", "sigma", "nu")
bad <- setdiff(names(prior), allowed)
if (length(bad) > 0) {
stop("Unknown noise prior names: ", paste(bad, collapse = ", "))
}
defaults <- default_noise_priors()
for (nm in names(prior)) defaults[[nm]] <- prior[[nm]]
list(
mu = as_internal_prior(defaults$mu),
sigma = as_internal_prior(defaults$sigma),
nu = as_internal_prior(defaults$nu)
)
}
compile_operator_priors <- function(prior, param_names) {
if (is.null(param_names) || length(param_names) == 0) {
return(list())
}
if (is.null(prior)) {
return(rep(list(as_internal_prior(default_operator_prior())), length(param_names)))
}
if (is_prior_spec(prior)) {
prior <- priors(theta = prior)
}
stopifnot("operator prior must be prior_*() or priors(...)." = is_prior_collection(prior))
unknown <- setdiff(names(prior), c("theta", param_names))
if (length(unknown) > 0) {
stop("Unknown operator prior names: ", paste(unknown, collapse = ", "))
}
per_param <- rep(list(default_operator_prior()), length(param_names))
if ("theta" %in% names(prior)) {
per_param <- rep(list(prior$theta), length(param_names))
}
for (i in seq_along(param_names)) {
nm <- param_names[[i]]
if (nm %in% names(prior)) per_param[[i]] <- prior[[nm]]
}
lapply(per_param, as_internal_prior)
}
compile_beta_priors <- function(prior, param_names) {
if (is.null(param_names) || length(param_names) == 0) {
return(list())
}
if (is.null(prior)) {
return(lapply(default_beta_priors(param_names), as_internal_prior))
}
if (is_prior_spec(prior)) {
prior <- priors(beta = prior)
}
stopifnot("beta prior must be prior_*() or priors(...)." = is_prior_collection(prior))
index_names <- paste0("feff_", seq_along(param_names))
unknown <- setdiff(names(prior), c("beta", param_names, index_names))
if (length(unknown) > 0) {
stop("Unknown beta prior names: ", paste(unknown, collapse = ", "))
}
per_param <- default_beta_priors(param_names)
if ("beta" %in% names(prior)) {
per_param <- rep(list(prior$beta), length(param_names))
}
for (i in seq_along(param_names)) {
nm <- param_names[[i]]
idx_nm <- index_names[[i]]
if (idx_nm %in% names(prior)) per_param[[i]] <- prior[[idx_nm]]
if (nm %in% names(prior)) per_param[[i]] <- prior[[nm]]
}
internal <- lapply(per_param, as_internal_prior)
bad_target <- which(vapply(internal, function(x) x$target != "coef", logical(1)))
if (length(bad_target) > 0) {
stop("beta prior currently supports target='coef' only.")
}
internal
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.