Models each node's conditional mean as an exact Gaussian process of its
parents, with a squared-exponential (ARD) kernel - one lengthscale per parent,
which captures non-linearity and interactions automatically. Kernel
hyperparameters (lengthscales, signal and noise variance) are point-estimated
by type-II maximum likelihood (hyper = "ml") or maximum a posteriori
(hyper = "map") under the priors in gp_prior(); there is no MCMC. A node
with no parents is modelled by its marginal (a Normal). This is Kagu's
default and only mechanism.
The default gp_prior() is log-uniform over the box the likelihood search is
bounded to, so the default ML fit is the MAP fit under that prior. Supplying
any other prior switches the default to hyper = "map", so the prior you
check with $prior_predictive() is the prior the fit actually uses.
Structure discovery uses the exact GP log marginal likelihood, which - in contrast to fast basis/eigenfunction approximations - is well calibrated: for a genuinely unidentifiable (e.g. linear-Gaussian) edge it does not manufacture spurious confidence about direction.
Posterior function samples for effect propagation are drawn by pathwise / decoupled sampling (a random-feature prior plus the exact data update), so each draw is a coherent function evaluable at any point - giving correctly correlated uncertainty for do-calculus contrasts.
Super class
Mechanism -> GPMechanism
Public fields
num_resultsInteger - number of posterior draws to keep (default 1000).
n_featuresInteger - random Fourier features for pathwise sampling (default 300).
jitterNumeric - diagonal jitter for numerical stability (default 1e-6).
priorA
gp_prior()- priors on the (standardised) hyperparameters.hyperCharacter -
"ml"(type-II maximum likelihood) or"map".
Methods
GPMechanism$new()
Create a new GPMechanism.
Usage
GPMechanism$new(
num_results = 1000L,
n_features = 300L,
jitter = 1e-06,
prior = gp_prior(),
hyper = NULL
)Arguments
num_resultsInteger - number of posterior draws to keep.
n_featuresInteger - number of random Fourier features.
jitterNumeric - diagonal jitter added to the kernel.
priorA
gp_prior()object (default: the implicit log-uniform box).hyper"ml"or"map".NULL(default) picks"ml"when every kernel prior is log-uniform (where ML and MAP coincide) and"map"otherwise.
GPMechanism$predict_mean()
Conditional mean draws (see Mechanism).
GPMechanism$log_marglik()
Exact GP log marginal likelihood (see Mechanism).
GPMechanism$node_terms()
Per-node summary rows: each parent's direct local effect (function gradient at the parent means) plus the residual noise sd.
GPMechanism$simulate_prior()
Prior predictive draws (see Mechanism). Each draw samples
hyperparameters from prior, an exact GP function at the parents' rows,
and observation noise - on the standardised scale - then maps back to the
data's location and scale.
Arguments
nodeCharacter scalar - the node name.
parentsCharacter vector of parent node names.
parent_valuesNamed list of
[ndraws, n]matrices of simulated parent values, one per parent (empty for a root node).dataA
data.frame- sets the node's location/scale andn.ndrawsInteger - number of prior predictive draws.
GPMechanism$simulate_posterior()
Posterior predictive draws (see Mechanism): the matched
pathwise function draw at each row's parents plus noise, with the noise
sd drawn as in $node_terms().
Arguments
nodeCharacter scalar - the node name.
parentsCharacter vector of parent node names.
parent_valuesNamed list, one entry per parent: either a length-
nvector shared by every draw (e.g. the observed parents) or a[length(draws), n]matrix with one row per draw.fitA fit object from
$fit().drawsInteger vector - which posterior draws to use.
nInteger - number of observations to simulate per draw.
GPMechanism$function_draws()
Prior or posterior function draws on a grid (see Mechanism).
Examples
mech <- GPMechanism$new()
# Weakly informative priors, fitted by MAP
mech <- GPMechanism$new(prior = gp_prior(lengthscale = prior_lognormal(0, 0.5)))
mech$hyper
#> [1] "map"