Builds prior specifications with brms spelling:
set_prior("normal(0, 5)", class = "b"). Combine several with + or
c(). Distributions: normal(mu, sd), student_t(df, mu, sd),
cauchy(mu, sd), exponential(rate), logistic(mu, s),
gamma(shape, rate), inv_gamma(shape, scale), beta(a, b),
uniform(lb, ub), lognormal(mu, sd), lkj(eta), dirichlet(alpha);
an empty string sets bounds only.
Usage
set_prior(
prior = "",
class = "b",
coef = "",
group = "",
resp = "",
dpar = "",
nlpar = "",
lb = NA,
ub = NA
)Arguments
- prior
Distribution string, e.g.
"normal(0, 5)", or aprior_normal()/prior_t()/prior_lkj()object, or""for bounds only.- class
"b","Intercept","sd","sds","cor","theta", one of the residual-structure classes"ar","ma","cosy","cortime"and"rescor", the simplex classes"simo"and"sbhaz", theme()classes"meanme","sdme"and"corme", or a distributional parameter's own name ("sigma","shape", ...). See A distributional parameter's own class.- coef
Restrict to one coefficient (classes
"b"/"Intercept"), to the standard deviation of one coefficient (class"sd", withgroup), to one smooth term (class"sds"), name the simplex of class"simo", name oneme()variable of class"meanme"or"sdme", or name one internal parameter of class"theta". A coefficient is named as brms names it and asdefault_prior()lists it:logxpfor the column oflog(xp),IxE2forI(x^2). The name of the design column,log(xp), also works.- group
Restrict class
"sd"or"cor"to one grouping factor, or class"corme"to theme()terms of onegr =variable.- resp
Response of a multivariate model. Required there for every class except
"cor","rescor","theta"and theme()classes; refused on a model with one response and on classes"rescor","meanme","sdme"and"corme".- dpar
Distributional parameter (default: the location parameters).
- nlpar
Nonlinear parameter of an
nl = TRUEformula. See Nonlinear parameters.- lb, ub
Optional hard bounds, on the scale described in Hard bounds.
Details
Classes and their scales:
"b": population-level coefficients ofdpar(default: the location parameters), excluding the intercept; narrow to one coefficient withcoef. Link scale."Intercept": the intercept ofdpar, at the MEAN of that sub-formula's predictors, which is the intercept brms's ownInterceptprior constrains. Link scale. See Where an intercept prior lands. On an ordinal family the thresholds are the intercept, here as in brms, so this class addresses the whole threshold vector; see Ordinal thresholds."sd": random-effect standard deviations, on the NATURAL sd scale with the log-Jacobian applied, soset_prior("exponential(1)", class = "sd")means what it says; narrow withgroup, and to one coefficient's standard deviation withgroupandcoef(coef = "x"for thexcolumn of(1 + x | g), asdefault_prior()lists it). See Group-level standard deviations. As in brms,resp,dparandnlparselect the standard deviations of that response, distributional parameter and nonlinear parameter only, and leaving one empty selects the empty one: with nodparthe specification reaches the location parameter's blocks and not aphi ~ (1 | g)block, and in a multivariate model a specification with norespreaches nothing and is refused. A block that spans several predictors,(1 | q | g)in bothmuandsigma, is the one exception, as it is in brms: there a specification that leaves a field empty reaches every standard deviation of the block, and a more specific one takes over its own."cor": the CORRELATION of a random-effect block, as a whole.lkj(eta)only, and it addresses a BLOCK the way class"sd"does, bygroup;set_prior("lkj(2)", class = "cor")covers every correlated block of the model, which is brms's spelling. See The LKJ prior below."ar","ma","cosy","cortime": the R-side residual correlation of anar(),ma(),arma(),cosy()orunstr()term, under brms's own class names."ar","ma"and"cosy"take an ordinary density on the NATURAL coefficient with that map's Jacobian applied, as class"sd"does;"cortime"takeslkj(eta)on anunstr()time correlation as a whole. Narrow to one response withresp. See Residual correlation below."rescor": the residual correlation BETWEEN responses of a multivariate model (set_rescor(TRUE)), as a whole.lkj(eta)only, as brms spells it, and noresp."lncor": the correlation matrix of the log ratios of alogistic_normal()response with three or more categories, as a whole, brms's class of the same name.lkj(eta)only."delta": the distance between neighboring thresholds of an ordinal family withthreshold = "equidistant", brms's class of the same name, on its own scale;groupselects the vector of one level ofthres(gr = ). See Ordinal thresholds."simo": the simplex of onemo()term,dirichlet(alpha)only, addressed by brms's coef: the term's label with1appended ("mox1","mox:fb1", asget_prior()lists them), and bydparfor a term outside the location parameter.alphais one number or one per weight. On a MAP fit the density carries the Jacobian of the coordinates the simplex is held in, so the mode underdirichlet(a)is the mode ofdirichlet(a + 1/2)on the weights, pulled further toward the uniform simplex; see "Monotonic effects" infrm()."sbhaz": the baseline-hazard simplex of acox()response (frmtmb.survival), or the simplex a family declares under that name (frmtmb_family(simplex_pars =));dirichlet(alpha)only, brms's class of the same name; nocoef."meanme","sdme","corme": the hyperparameters of the latent values of me() terms, brms's classes of the same names."meanme"is a density on the latent mean,"sdme"one on the latent standard deviation itself, with the log-Jacobian of the log map, as class"sd".coefnames oneme()variable asdefault_prior()lists it ("mex"forme(x, sdx)), and neither class takes agroup."corme"takeslkj(eta)on the correlation matrix of theme()terms that share agr =, as a whole:groupselects thegr =variable, and nocoef. The three take noresp,dparornlpar, because one set of latent values serves the whole model."theta": frmtmb's own class, for the internal covariance parameters that no brms class names, on the internal scale: atoep()correlation, the parameter of a covariance structure an extension registers (acar()dependence), and a residual term's parameter without an interval.coefnames one by its internal name ("theta_12","thetaac_1"), asdefault_prior()lists it; with nocoefthe class covers every random-effect parameter of that kind. A parameter that a class reaches has that class as its one slot, as in brms, which has no class"theta": a standard deviation ("sd","sdgp"), agp()length scale ("lscale"), a correlation an LKJ density fits ("cor"), a residual correlation ("rescor","ar","ma","cosy","cortime", frmtmb.spatial's"lagsar"), the SD of a latent residual ("sderr"). Its internal row is not listed, and a class"theta"prior on it is refused with the class to use.a DISTRIBUTIONAL parameter's own name (
"sigma","shape","phi","zi","nu", ...): a density on that parameter ITSELF, on its NATURAL scale, with the inverse link's log-Jacobian applied, soset_prior("student_t(3, 0, 2.5)", class = "sigma")means what it says. Available where the parameter has no predictor of its own; see A distributional parameter's own class.
In a MULTIVARIATE model, every specification of class "b",
"Intercept", "sd", "ar", "ma", "cosy" or "cortime", and
every distributional parameter's own class, names its response with
resp. A specification without resp is refused, as brms refuses
it: write one specification per response. Classes "rescor" and
"theta" take no resp, and "cor" needs none. On a model with ONE
response, resp is refused, as in brms.
Two spellings are frmtmb's own, and brms refuses both: "cor" with
resp, which narrows the prior to that response's blocks, and
"Intercept" with nlpar, which is stored as brms's slot of the same
parameter, class "b" with coef = "Intercept" and that nlpar
(see Nonlinear parameters). A centered intercept has one slot, class
"Intercept": class "b" with coef = "Intercept" there is
refused, as brms refuses it. A class "b"
specification that reaches no coefficient, because the predictor it
names has no population-level slope (y ~ 1), is refused, as in
brms. In the same way, a class
"b" or "Intercept" specification on a NONLINEAR location names
its nonlinear parameter with nlpar; see Nonlinear parameters.
And where a family's location is SEVERAL distributional parameters,
as in categorical(), multinomial() and mixture(), a class
"b", "Intercept" or "sd" specification names one of them with
dpar ("mub", "mu1"), and default_prior() lists the rows that
way, as brms does.
Two specifications for the same slot (the same class, coef, group,
resp, dpar and nlpar) are refused wherever a prior is passed in, as
brms refuses them; that includes a density followed by a bounds-only
specification, so write the density and its bounds in one call.
When specifications for DIFFERENT slots reach the same parameter,
the more specific one applies whatever order they are written in, as
in brms: a coef specification over its class, and a group
specification over a class-wide "sd" or "cor" one. No
parameter has two classes: each is reached by one class, and the
other spelling is refused, so the order between classes decides
nothing.
lb/ub become hard bounds. See Hard bounds.
Group-level standard deviations
set_prior(class = "sd", group = "g", coef = "x") puts the density
on one standard deviation: that of the x column of the g block.
brms puts the same prior on sd_g__x. The other standard deviations
of the block keep the prior of the group or of the class. A coef
without a group is refused, because brms has no such row.
The density is on the standard deviation itself, with the
log-Jacobian of the log map. frmtmb holds a correlated block as log
standard deviations and separate correlation parameters. It does not
hold a Cholesky factor. So each standard deviation is one parameter,
and the prior on it is exact. The prior does not change the
correlations. A class "cor" prior addresses those. In a Student-t
block (gr(g, dist = "student")), the parameter is the scale. That
is also what brms's sd is in that term.
Some structures give their columns one shared standard deviation,
for example homdiag(), ar1() and homcs(). They have no standard
deviation per coefficient. A coef that names one of their columns
is refused by name. Drop the coef to put the prior on the shared
standard deviation. A block of another response, distributional
parameter or nonlinear parameter does not cause this refusal.
The group labels are brms's. A nested (1 | g1/g2) has the groups
g1 and g1:g2. A multi-membership (1 | mm(m1, m2)) has the group
mmm1m2. default_prior() lists them so.
Where an intercept prior lands
brms centers its design matrix and constrains the intercept at the
MEAN of the predictors, recovering the reported one as
b_Intercept = Intercept - dot_product(means_X, b). frmtmb
parameterizes by the intercept at zero and evaluates a class
"Intercept" density at b0 + means_X'b, so the two packages
constrain the same quantity. The map between the two
parameterizations is unit triangular and carries no Jacobian.
This matters whenever a predictor is not centered. On
Reaction ~ Days, where mean(Days) is 4.5, the intercept at zero
is strongly correlated with the slope and the intercept at the mean
is orthogonal to it, so a prior on the first biases the slope and a
prior on the second does not. Earlier releases used the intercept
at zero, and brms::get_prior()'s own default there moved the slope
by 0.068 standard errors; it now moves it by 0.00003.
Every sub-formula with an intercept is centered separately, as brms
does (means_X, means_X_sigma, ...). A NONLINEAR parameter's
sub-formula is not centered on either side, and neither are a
smooth's unpenalized columns or a mo() term, which sit outside
brms's Xc as well. To put a density on the intercept at zero, name
it as a coefficient instead: class = "b", coef = "Intercept".
A formula written 0 + Intercept + x, or bf(center = FALSE), makes
that the intercept's only prior slot, as brms does: the intercept is
then class "b" and a class "b" prior without a coef reaches it
too, while class "Intercept" has no slot and is refused.
Ordinal thresholds
cumulative(), sratio(), cratio() and acat() have no intercept
column: the thresholds replace it. brms priors them as its
Intercept class and so does frmtmb, so
set_prior("student_t(3, 0, 2.5)", class = "Intercept") on an
ordinal model addresses the whole threshold vector. It addresses the
THRESHOLDS, at the mean of the predictors (at zero under
bf(center = FALSE), as in brms), with the log-Jacobian of
the map from frmtmb's internal storage. cumulative() holds
(tau_1, log increments), which is the same map Stan's ordered
type applies to brms's ordered thresholds. sratio(), cratio() and
acat() hold the thresholds themselves, which brms declares as an
unconstrained vector, so there is no Jacobian. lb/ub are refused
there, because one number cannot box a whole vector of thresholds.
One threshold is addressed by its number, as brms lists it:
set_prior("normal(0, 1)", class = "Intercept", coef = "2") is a
density on the second threshold, and it replaces a class-wide
density there and only there. The vector stays one entry, so the
log-Jacobian of cumulative()'s map enters once. Under
thres(gr = ) a threshold is named by its level and its number,
group = "a", coef = "2". brms has no per-threshold parameter
under threshold = "equidistant", and the row is refused there, as
in brms.
The threshold structure changes what class "Intercept" addresses,
as it does in brms. Under threshold = "equidistant" it is the
first threshold alone, at the mean of the predictors, and class
"delta" is the distance between thresholds: on delta itself,
with the log-Jacobian of the log that cumulative() and
hurdle_cumulative() hold it on, since brms bounds it below by 0
there. Under threshold = "sum_to_zero" class "Intercept" is
refused: brms's prior there is on thresholds it declares before
centering them, whose common location only that prior places, and
frmtmb estimates the centered thresholds directly, so the parameter
does not exist.
Hard bounds
lb/ub are how a box constraint is written. A specification may
carry bounds alone (prior = ""), a distribution alone, or both. A
bounds-only specification for a slot another specification already
gives a density is refused as a duplicate, as in brms; a bound on a
coefficient beside a class-wide density is a different slot and
boxes that coefficient under the class density.
A bound is addressed exactly like the distribution beside it, so
set_prior("", nlpar = "guess", lb = 0, ub = 1) bounds the nonlinear
parameter guess, and dpar, resp, group and coef narrow a
bound the same way they narrow a density. As with a distribution,
class "b" with nlpar covers EVERY coefficient of that parameter;
coef picks out one.
A bound on one coefficient is frmtmb's own on frm(), a box on the
maximum-likelihood fit. brms refuses it ("Prior argument 'coef' may
not be specified when using boundaries."), and so does
frmtmb.sample::frm_sample(), which samples brms's model: there a
bound goes on the class row.
The scale is the parameter's own: class "sd" bounds a standard
deviation on the sd scale (frmtmb stores its log), classes "ar",
"ma" and "cosy" bound the natural coefficient of a residual
structure, and class "theta" bounds an internal covariance
parameter itself, one position at a time with coef = "theta_12",
where no class reaches that parameter (see class "theta" above).
A correlation takes no bound, as in brms: a correlation matrix's
entries are not free of one another, and brms writes a Stan program
that does not parse for lb on class "cor". Everything else is
bounded on the
internal (link) scale, so a bound on a log-linked dispersion is a
bound on its logarithm.
In frm() a bound is a box constraint handed to the optimizer; in
frmtmb.sample::frm_sample() it becomes one of Stan's constrained
transforms. Both take this spelling and no other: the lower/upper
arguments of releases before 0.49 are gone rather than aliased, and a
call still using them fails as an unused argument. Every outer
parameter they could reach has a class here, down to a single
internal covariance parameter.
Where the two spellings differed, this one broadcasts: a bound
carried by nlpar = covers every coefficient of that parameter, the
way a prior does, and coef narrows it to one. When a class-wide
and a coefficient-specific specification both bound a parameter, the
coefficient-specific one applies.
Residual correlation
On a family with no residual y - mu these terms are brms's latent
residuals (frmtmb-autocor), and class "sderr" is the standard
deviation of the latents, written and carried as class "sd" is. Their
coefficients take the classes below, on brms's intervals: (-1, 1) on ar
and ma, each entry on its own under cov = FALSE, and (0, 1) on cosy.
frmtmb holds an ar(), ma(), arma(), cosy() or unstr()
residual block in one unconstrained vector, chosen so the optimizer
cannot step outside the stationary and invertible region. A prior is
still written about the parameter brms names, and carried onto that
vector with the log Jacobian of the map, exactly as class "sd"
carries a density on a standard deviation onto its logarithm. So
set_prior("normal(0, 0.5)", class = "ar") is a density on the AR
coefficient itself, and summary() reports the parameter the prior
was written about.
Bounds behave the same way where the map allows it. A first-order
ar, ma or cosy coefficient is a monotone function of one
internal parameter, so lb/ub map exactly onto a box. At order two
and above they do not: ar[1] is a function of every internal
parameter of the block at once, so no box in internal space is the
box asked for, and lb/ub are refused rather than approximated.
Little is lost, because the parameterization already guarantees
stationarity and invertibility, which is what such a bound is usually
for, and brms's cov = TRUE form is of order one only. Under
cov = FALSE the coefficients are unconstrained and are the internal
parameters, so lb/ub apply at any order, as in brms. A bound at
an end of the parameter's own interval, such as brms's lb = -1 on a
first-order ar, bounds nothing and is accepted, so a
default_prior() table can be passed back as prior =.
cosy is bounded below at -1/(d - 1) for d time points, where a
compound-symmetric matrix stops being positive definite, and a bound
outside that window is refused rather than clamped. brms bounds
cosy on [0, 1] instead, so a negative estimate here has no brms
counterpart. frmtmb.sample::frm_sample() samples cosy on brms's
[0, 1]: its default prior there is brms's flat one, and a cosy
prior that sets no lb keeps lb = 0, as brms keeps the bound it
declares. default_prior(route = "sample") lists that interval, and
the default route lists frm()'s window.
Under a cov = TRUE ar(), ma() or arma(), sigma is the
innovation sd, as in brms (frmtmb-autocor). So a prior on class
"sigma", its lb and ub, and under sigma ~ x a prior on the
intercept of sigma (class = "Intercept", dpar = "sigma", the log
innovation sd), are brms's priors on the same parameter.
The LKJ prior
lkj(eta) is the density det(C)^(eta - 1) over a block's
correlation matrix C, normalized: eta = 1 is uniform over
correlation matrices, larger eta concentrates toward the identity.
frmtmb holds a correlation as an unconstrained row-normalized
Cholesky parameter rather than as C, so the density is carried onto
those parameters with the exact Jacobian of that map (the derivation
is in the source of R/priors.R; tests/testthat/test-lkj.R checks
the sampled correlations against the closed-form LKJ marginals). The
prior a FLAT correlation parameter carries instead is
(1 - rho^2)^(-3/2), which is improper.
It fits us() and gr(cov = ) blocks of two or more terms, which
hold a whole correlation matrix, and the one-parameter structures
cs(), ar1() and hetar1(), whose single bounded correlation
takes the LKJ marginal (1 - rho^2)^(eta - 1) with that structure's
own Jacobian. A cs() correlation is bounded below at -1/(d - 1),
where a compound-symmetric matrix stops being positive definite, and
the density is renormalized over that window. toep() is refused:
its parameterization is not positive definite everywhere, so it has
no correlation matrix to put a density on.
Nonlinear parameters
nlpar addresses one parameter of an nl = TRUE formula, brms's
spelling: set_prior("normal(5000, 1000)", nlpar = "ult"), or
prior(normal(5000, 1000), nlpar = "ult"). Class "b" there covers
EVERY coefficient of that parameter, its intercept included, because
a nonlinear parameter's sub-formula is not centered and brms holds
its intercept in the same coefficient vector as its slopes. That is
why the vignette spelling above lands on ult_(Intercept) rather
than on nothing. Narrow to one column with coef ("Intercept" and
"(Intercept)" both name the intercept), or write
class = "Intercept", nlpar = "ult", which frmtmb stores as that
same slot, class "b" with coef = "Intercept", so the two
spellings are one slot; brms does not take the second. nlpar narrows
classes "sd" and "cor" to the random-effect blocks of that
parameter as well.
A class "b" or "Intercept" specification without nlpar does not
reach a nonlinear parameter. On a model whose location is nonlinear,
such a specification addresses no parameter, and it is refused, as
in brms. A distributional parameter keeps its own spelling there:
set_prior("student_t(3, 0, 2.5)", class = "sigma") needs no
nlpar.
A prior with a location places frm()'s start for a nonlinear
parameter. normal(), student_t() and cauchy() all carry one,
and where start does not set a nonlinear coefficient, that
coefficient begins at the prior's location, reported in a message.
Other parameters keep their usual starts: a prior is a penalty, not
a claim about where to begin. Without a located prior a nonlinear
model still needs start, because frm() evaluates the objective
AT the starting values; par_template() names them.
resp picks one response of a multivariate model, and a nonlinear
parameter of one response is addressed with both resp and
nlpar.
Translating a brms prior
frm(prior = ) takes a brmsprior object directly, whether it came
from brms::set_prior(), brms::prior() or brms::get_prior(). A
row applies whatever its prior string says, which is brms's own
rule; an empty string is brms's flat default and applies nothing.
The source column is not read. Earlier releases dropped rows marked
source == "default" were dropped, which lost a prior the user had
edited into a get_prior() table in place, because brms does not
update source after that edit.
A specification means here what the same words mean in brms.
Every class brms writes that frmtmb can honor is a class
set_prior() takes under the same name and with the same meaning,
so a table and a hand-written specification reach one code path:
b,Intercept,sd,cor,ar,ma,cosy,cortimeandrescorare frmtmb's own class names and keep their meaning.a DISTRIBUTIONAL parameter's own class (
sigma,shape,phi,nu,kappa,sigma1, ...) is a density on that parameter ITSELF, through the dpar's inverse link with that map's log-Jacobian, which is the change of variables class"sd"performs. A bound travels with it, solb = 0on a log-linked dispersion becomes no constraint rather than a floor of 1.simoandsbhazkeep their meaning too: adirichlet()on amo()simplex and on acox()baseline. So domeanme,sdmeandcorme, the hyperparameters of ame()term, brms'slkj(1)default oncormeincluded.sdsis the standard deviation of a smooth's penalized part, brms's class of the same name.coefnames one smooth term asdefault_prior()lists it ("s(x)","t2(x, z)","s(x, by = f)"), and a term with several standard deviations (at2()or a by-smooth) takes the density on each of them, as in brms. Class"sd"does not reach a smooth.theta/theta1/theta2,sdcarandcarare refused by name, each saying where frmtmb keeps that quantity instead. A refusal is deliberate: translating one of them would produce a different model rather than no model.a
coefon asdorcorrow is refused for the same reason. brms narrows such a row to one coefficient of a block; frmtmb resolves those classes per BLOCK, so applying the row without itscoefwould put the density on every standard deviation of the block, which is a wider prior than the one written.coefon class"b"narrows as it does in brms and is unaffected.
Every refused row of a table is named in ONE message, because a table is edited as a whole and stopping at the first bad row costs a round trip per bad row.
brms's tag and check have no counterpart: tag names a prior
for reuse inside a Stan program, and check passes an unchecked
string through to one. frmtmb compiles no Stan program, so both are
omitted rather than accepted and ignored.
A distributional parameter's own class
A distributional parameter has TWO spellings, and which one applies is decided by the model rather than by taste. They are brms's own two, and brms accepts each only on the model the other does not:
class = "sigma"a density on sigma ITSELF, on its natural scale. Available when sigma has no predictor of its own, which is the model where sigma is a single number.
class = "Intercept", dpar = "sigma"a density on the LINK-scale intercept of sigma's linear predictor. Available when the model gives sigma a formula,
sigma ~ 1included.
Writing a formula for a parameter is what replaces the parameter
with a linear predictor, so bf(y ~ x, sigma ~ 1) has no sigma to
put a density on, and bf(y ~ x) has no Intercept_sigma. Each
spelling is refused by name on the other's model, naming the one
that applies, because a silently retargeted prior is a different
model rather than no model.
class = "b", dpar = "sigma" addresses that predictor's SLOPES and
is on the link scale, in both packages. It needs slopes to exist: on
sigma ~ 1 the predictor is an intercept only, so the row addresses
nothing, and it is refused rather than accepted as a silent no-op.
brms refuses it there too.
A distributional class names ONE parameter, so it takes resp and
neither coef nor group; both are refused rather than dropped.
On a multivariate model it needs resp, as it does in brms: without
it, the specification is refused.
get_prior() lists whichever of the two spellings a model offers.
Where a parameter has NEITHER, because frmtmb refuses its class by
name, the table leaves it out rather than advertising a slot nothing
can fill: a mixture proportion with no predictor of its own is one,
and ?set_prior's refusal says where that quantity lives.
Examples
set.seed(1)
dd <- data.frame(x = rnorm(100), z = rnorm(100),
g = factor(rep(1:10, 10)))
dd$y <- rnorm(100, 1 + 0.5 * dd$x + rnorm(10, 0, 0.8)[dd$g], 1)
# `+` combines specifications; the class-wide one goes first so the
# coefficient-specific one can override it
pr <- set_prior("normal(0, 1)", class = "b") +
set_prior("normal(0, 0.2)", class = "b", coef = "z") +
set_prior("exponential(1)", class = "sd", group = "g")
pr
#> prior class coef group resp dpar nlpar lb ub source
#> normal(0, 1) b <NA> <NA> user
#> normal(0, 0.2) b z <NA> <NA> user
#> exponential(1) sd g <NA> <NA> user
# the priors penalize the likelihood: the fit is a MAP estimate
fit <- frm(bf(y ~ x + z + (1 | g)) + gaussian(), data = dd, prior = pr)
fixef_by_dpar(fit)$mu
#> (Intercept) x z
#> 1.43923097 0.56382980 0.05323068
# the tight prior on z shrinks it toward zero
fixef_by_dpar(frm(bf(y ~ x + z + (1 | g)) + gaussian(), data = dd))$mu
#> (Intercept) x z
#> 1.43901107 0.57151174 0.06947068
# an empty distribution string sets a hard bound only
set_prior("", class = "b", coef = "x", lb = 0)
#> <lower=0> b_x ~ (flat)
# a distributional parameter's own class is a density on the
# parameter itself, on its own scale, where the model gives that
# parameter no predictor. This model does not, so this is the
# spelling it offers, and get_prior() lists it
fit_s <- frm(bf(y ~ x + z) + gaussian(), data = dd,
prior = set_prior("student_t(3, 0, 2.5)",
class = "sigma"))
sigma(fit_s)
#> [1] 1.336249
# with sigma ~ 1 the model has a log-scale intercept instead, and
# that is the slot the prior addresses. brms draws the same line
set_prior("student_t(3, 0, 2.5)", class = "Intercept",
dpar = "sigma")
#> Intercept_sigma ~ student_t(3, 0, 2.5)
# bounds address a nonlinear parameter the way a distribution does,
# so a guessing rate is held in [0, 1]
set_prior("", nlpar = "guess", lb = 0, ub = 1)
#> <lower=0,upper=1> b_guess ~ (flat)
# the residual-correlation classes are brms's own names
set_prior("normal(0, 0.5)", class = "ar")
#> ar ~ normal(0, 0.5)
set_prior("lkj(2)", class = "rescor")
#> rescor ~ lkj(2)
# and one internal covariance parameter that no class names, such
# as a toep() correlation, by its name as get_prior() lists it
set_prior("", class = "theta", coef = "theta_12", lb = -2, ub = 2)
#> <lower=-2,upper=2> theta_theta_12 ~ (flat)
# class "cor" addresses a correlated block as a whole, brms's
# spelling; eta > 1 pulls the correlation toward zero
dd$z <- rnorm(100)
dd$y2 <- dd$y + rnorm(10, 0, 0.6)[dd$g] * dd$z
fitc <- frm(bf(y2 ~ x + z + (z | g)) + gaussian(), data = dd,
prior = set_prior("lkj(4)", class = "cor"))
VarCorr(fitc)
#> $g
#> $g$sd
#> Estimate Est.Error Q2.5 Q97.5
#> Intercept 0.8478602 0.2064028 0.4433182 1.252402
#> z 0.7600990 0.1980361 0.3719555 1.148243
#>
#> $g$cor
#> , , Intercept
#>
#> Estimate Est.Error Q2.5 Q97.5
#> Intercept 1.0000000 0.0000000 1.0000000 1.0000000
#> z 0.3342666 0.2368202 -0.1298924 0.7984256
#>
#> , , z
#>
#> Estimate Est.Error Q2.5 Q97.5
#> Intercept 0.3342666 0.2368202 -0.1298924 0.7984256
#> z 1.0000000 0.0000000 1.0000000 1.0000000
#>
#>
#> $g$cov
#> , , Intercept
#>
#> Estimate Est.Error Q2.5 Q97.5
#> Intercept 0.7188669 0.3500014 0.03287685 1.4048570
#> z 0.2154207 0.1706862 -0.11911814 0.5499595
#>
#> , , z
#>
#> Estimate Est.Error Q2.5 Q97.5
#> Intercept 0.2154207 0.1706862 -0.11911814 0.5499595
#> z 0.5777505 0.3010540 -0.01230454 1.1678056
#>
#>
#>
#> $residual__
#> $residual__$sd
#> Estimate Est.Error Q2.5 Q97.5
#> 0.9763468 0.07648279 0.8264433 1.12625
#>
#>
# get_prior() shows which rows a design offers
get_prior(bf(y ~ x + z + (1 | g)) + gaussian(), data = dd)
#> route = "fit": the prior defaults frm() applies
#> prior class coef group resp dpar nlpar lb ub source
#> 1 (flat) Intercept NA NA default
#> 2 (flat) b NA NA default
#> 3 (flat) b x NA NA default
#> 4 (flat) b z NA NA default
#> 5 (flat) sd NA NA default
#> 6 (flat) sd g NA NA default
#> 7 (flat) sd Intercept g NA NA default
#> 8 (flat) sigma NA NA default
# prior() quotes its first argument, brms's spelling, and reaches
# the same machinery
prior(normal(0, 1), class = "b")
#> b ~ normal(0, 1)