Computes predictions from a bartisan() fit, at the data the model was fit
to or at new data, on any of several scales. Because every posterior draw of
every tree is retained, a prediction can be returned as its posterior mean or
as the draws themselves.
Usage
# S3 method for class 'bartisan_fit'
predict(
object,
newdata = NULL,
type = "response",
draws = FALSE,
iterations = NULL,
offset = NULL,
weights = NULL,
values = NULL,
log = FALSE,
times = NULL,
...
)Arguments
- object
a
<bartisan_fit>object; the output of a call tobartisan().- newdata
optional; a data frame at which to predict. Default is
NULLto use the data the model was fit to. Missing predictor values are allowed in the columns that had them when the model was fit, since only those columns' splitting rules carry an answer for one; a missing value anywhere else is an error. See section Missing Predictor Values in the Details ofbartisan().- type
string; the scale of the prediction. Allowable options include
"link","response"(the default),"prob","class","mean","stdlv","density", and"survival"."link"the additive predictor, one column per predictor for families that have more than one.
"response"the mean of the response; the median survival time for every survival family,
ph()included; and, for a response with categories, the category probabilities, since there is no single mean to report."prob"category probabilities, for the binomial, ordinal and multinomial families.
"class"the most probable category, as a factor, for the same families.
"mean"the mean of the response with the category labels read as numbers, for the same families, so that
"4"counts as four. This is the summary an ordinal outcome with numeric labels usually wants, and it needs no assumption at the modeling stage: the model is still ordinal and only the reporting treats the categories as numbers.valuessays what the categories are worth when the labels are not numbers, or are not the numbers intended."stdlv"the additive predictor divided by the standard deviation of the latent variable it indexes, for the ordinal and binomial families. Either response can be written as a threshold crossing of a continuous
y* = eta + e, and the link fixes the distribution ofeand so its variance; dividing by the standard deviation ofy*puts fits with different links, or different amounts of signal, on one scale, which is what a standardized effect size on such an outcome needs. Available for the probit, logit and complementary log-log links, which are the ones with a latent distribution to name. See Details."density"the conditional density of the outcome given the predictors, evaluated at the observed outcome. This requires the outcome, so
newdatamust contain it; leavingnewdataempty uses the data the model was fit to. The value is the likelihood contribution of the observation, so it is a density for a continuous response, a probability for a discrete one, and a survival probability for a censored survival time. Useful for held-out log scores and for posterior predictive checks. The measure differs across the survival families: the accelerated failure time families,dpm_aft()included, report the density of \(\log T\), whileph()reports the density of \(T\). The two differ by \(\sum \log t\), so log scores are comparable within each group and not across them;type = "survival"is comparable throughout."survival"the survival function \(S(t \mid x)\) at the times given in
times, for the accelerated failure time families andph(). This is the predictive distribution of a survival response, and the analogue of"prob"for a categorical one:"response"reports only the median. Returns one column per time, or a draws by rows by times array whendraws = TRUE. It is also what makes the usual survival estimand (a contrast in \(t\)-year survival) reachable through marginaleffects; see bartisan-marginaleffects.
- draws
logical; whether to return every posterior draw rather than the posterior mean. Default isFALSEto return the mean. IfTRUE, the result gains a leading dimension indexing the draws.- iterations
numeric; optional indices of the stored draws to use, between 1 and the number of draws the fit retains. Default isNULLto use all of them.- offset
numeric; an offset for the rows ofnewdata, on the link scale, given either as one value per row or as a matrix with one column per additive predictor. Used only whennewdatais supplied, and required there when the model was fit with an observation-level offset, since an offset is not a function of the predictors and so cannot be reconstructed. Default isNULLto add nothing.- weights
numeric; prior weights for the rows ofnewdata, used only bytype = "density"and ignored otherwise. For a binomial response given as proportions these are the numbers of trials, as instats::glm(). Default isNULL, which uses the weights the model was fit with whennewdatais omitted and a weight of 1 for every row when it is supplied.- values
numeric; fortype = "mean", what each response category is worth, given as a vector named for every level of the response. Default isNULLto read the level labels as numbers, which is an error rather than a guess when they cannot be read that way. Ignored with a warning for every othertype.- log
logical; fortype = "density", whether to return the log of the value. Default isFALSE. Summing the log density across observations gives a log score. Note that withdraws = FALSEthe density is averaged over the draws before the log is taken, so the result is the pointwise predictive density rather than the average log density.- times
numeric; fortype = "survival", the times at which to report the survival function, which must be finite and strictly positive. It has no default, because the horizon is a choice rather than a property of the fit. Ignored with a warning for every othertype.- ...
ignored; present for compatibility with the generic.
Value
With draws = FALSE, a vector with one element per observation for
"response", "mean" and "density", and for "link" and "stdlv" when
the family has a single additive predictor; a matrix of observations by
additive predictors for "link" and "stdlv" when it has more than one; a
matrix of observations by categories for "prob", and for "response" with
an ordinal or multinomial family; a matrix of observations by times for
"survival"; and a factor for "class", ordered when the family is
ordinal().
With draws = TRUE each of these gains a leading dimension indexing the
posterior draws, so that a vector becomes a matrix of draws by observations
and a matrix becomes an array of draws by observations by categories or by
times. On the "link" and "stdlv" scales a family with more than one
additive predictor returns a list with one draws-by-observations matrix per
predictor. "class" is a factor either way.
Details
Multinomial Probit Probabilities Are Simulated
The likelihood of a multinomial("probit") fit has no closed form: the
probability of a category is the chance that the largest of several correlated
Gaussian variables is the one belonging to it, which is a multivariate orthant
probability. So "prob", "class", "response" and "density" are all
simulated, using the number of replicates the family was given. Fresh draws
are taken on every call, so two calls differ by Monte Carlo error; that error
is per posterior draw and averages down over them, which makes draws = FALSE
much more accurate than any single row of draws = TRUE.
The Standardized Latent Variable
type = "stdlv" reports (eta - E[e]) / sd(y*) for the latent
y* = eta + e, following
WeightIt::predict.ordinal_weightit()
. Three parts of that need saying.
The scale is sd(y*) = sqrt(var(eta) + var(e)), where var(eta) is taken
over the sample the model was fitted to, per draw, so it is a property of the
model rather than of whatever is being predicted; the same divisor is used when
predicting new data. var(e) is whatever the link implies: 1 for the probit
link, \(\pi^2 / 3\) for the logit, \(\pi^2 / 6\) for the complementary log-log.
The location subtracts the latent error's mean, which shifts y* so that
its error is centered. That is invisible for the logit and probit links, whose
errors are already centered, and is the whole of the difference for the
complementary log-log link, whose error is a smallest extreme value variate.
The sign of that shift differs between the two families, and only for the
complementary log-log link. A normal or logistic error is symmetric, so it does
not matter whether e or -e is the thing added to the index. A smallest
extreme value error is not symmetric, and the two families add it with opposite
signs: an ordinal model has P(Y <= k) = G(c_k - eta), which is
P(eta + e <= c_k), so its error has mean -gamma; a binomial model has
P(Y = 1) = G(eta), which is P(e <= eta), so its latent is eta - e and the
error has mean +gamma. The two are different models rather than the same one
written twice, which is also why a two-category ordinal complementary log-log
fit is not the same as a binomial one.
Such a model is identified only up to a common shift of its thresholds and its predictor, so the location of this quantity is a convention rather than a fact, and the one used here is the same one the cutpoints use: a predictor centered over the fitted sample. Against WeightIt, which identifies by dropping the intercept column instead, the two agree on the scale and differ by a constant; measured on a linear truth, the standard deviations agree to under 1% and the difference is constant to three decimals. Differences on this scale, which is what a standardized quantity is for, are unaffected.
When the Density Is Undefined
type = "density" returns NaN for an observation whose density is
undefined at any of the draws, which happens when a link the package does not
compile has been composed onto the family's own scale and its inverse does not
cover the whole additive predictor (e.g., poisson("identity"), which gives a
positive mean only where the predictor is positive). A saved draw can imply a
parameter outside the family's support at a predictor the forest extrapolates
to, even though bartisan() warns about such a link at fit time and rejects
such proposals while sampling. The value stays NaN rather than becoming
zero, which would assert that the outcome is impossible and would read as a
legitimately terrible fit rather than an undefined one once logged, and a
warning reports how many draw-by-observation values were undefined and how
many returned values that made NaN. Note that the draws are averaged before
the log is taken, so one undefined draw is enough to make an observation
NaN.
See also
bartisan() for fitting the model; bartisan-marginaleffects for averages
and contrasts of these predictions; bartisan-interop for the methods that
let other packages assess the fit
Examples
data("rhc")
set.seed(123)
# Whether a patient died, with every other variable a candidate predictor
fit <- bartisan(death ~ . - days, data = rhc,
num_trees = 10, num_burn = 50, num_draws = 50)
#> ℹ Using `family = binomial()`.
#> ℹ Set `family` to choose another, which also silences this message.
# Fitted probabilities of death, averaged over the draws
head(predict(fit, type = "response"))
#> [1] 0.7860891 0.8385106 0.2271306 0.4409820 0.3670865 0.4670693
# The whole posterior for the first five patients rather than its mean
post <- predict(fit, newdata = rhc[1:5, ], draws = TRUE)
apply(post, 2, quantile, c(.025, .5, .975))
#> [,1] [,2] [,3] [,4] [,5]
#> 2.5% 0.7085616 0.7908357 0.1505209 0.3506389 0.2793308
#> 50% 0.7857738 0.8385867 0.2279566 0.4419846 0.3651961
#> 97.5% 0.8779175 0.8856130 0.3058042 0.5315154 0.4875912
# A held-out log score, which needs the outcome, so `newdata` carries it
sum(log(predict(fit, newdata = rhc[1:100, ], type = "density")))
#> [1] -59.99775