The parameter vector a model optimizes, as an editable named list:
one component per parameter block (beta, betad, theta, ...),
each a named numeric vector. It answers "what do I call these?"
before there is a fit to ask, which is what frm(start =),
frm_simulate()'s newparams =, and every box constraint all need:
these are the names a bound resolves to, and the names
set_prior()'s coef takes for a covariance parameter that no brms
class names (class = "theta", coef = "theta_12").
Arguments
- object
A
frmtmb_fit, or abf()formula or plain formula.- ...
Refused: an argument the method does not have is an error naming it, rather than silently changing nothing.
- data
Model data. Required when
objectis a formula.- family
Family, when
objectdoes not carry one.- start
Optional
startlist, applied exactly asfrm()would, so the result shows the starting values a fit with thatstartuses. Formula method only.- prior
Optional
set_prior()specification, so the result shows the nonlinear starting values its locations place. Formula method only.- na.action, data2
As in
frm(). Formula method only.
Value
A frmtmb_par_template: a named list of named numeric
vectors, accepted directly as frm(start =) and as
frm_simulate(newparams =).
Details
On a fitted model the values are the estimates. On a formula and
data the frame is assembled but nothing is fitted, and the values are
the ones frm() would start from, start = and prior = included.
Either way the result can be edited and passed straight back:
The names
Fixed-effect components (beta, betad) carry the design-matrix
column names, so they agree with fixef() and summary(), and the
intercept is spelled "(Intercept)". Covariance components
(theta, thetaac, thetar) have no design of their own and are
spelled theta_1, theta_2, ... - the same names confint(parm =)
reports. When you supply names BACK, the parentheses may be dropped:
"Intercept" and "(Intercept)" address the same coefficient.
The default starting values
For most location-scale families the coefficients of mu start at a
least-squares fit on its fixed design, and the scale (sigma,
shape or phi) starts at the spread of that fit's residuals. Thus
a covariate that explains most of the response does not start the
scale at the spread of the response. The families are gaussian(),
student(), skew_normal(), exgaussian(), asym_laplace(),
zero_inflated_asym_laplace(), huber(), lognormal(),
shifted_lognormal() and hurdle_lognormal() with the identity link of
mu, Gamma() and weibull() and negbinomial() with the log link, and
Beta() with the logit link. Every other fit, and every fit with a
nonlinear or intercept-only mu, a smooth or gp() term in mu, an
ill-conditioned design, a censored, truncated or se() response, or a
scale held at a constant, starts each intercept at the family's
initializer. A nonlinear coefficient starts at 0, or at the location
of a prior on it. Where the body is defined at those values and the
link cannot evaluate it, as under the default links of Gamma() and
inverse.gaussian(), one intercept the body reads moves to where the
body equals the response mean, and a message says so. The entries you
name in start replace these values. The random-effect standard
deviations start at the response's unit.
A body can be constant across the rows at these values and stationary
there, as b1 * exp(b2 * x) is at 0. frm() then restarts from moved
coefficients of every such body and keeps a higher point, and it does the
same for a fit from the default start that runs along a flat direction. A
message says so. If no restart leaves a constant body, a warning names it:
the data may simply have no effect there, and a start can test that. A
message names a constant body that is a local maximum along its coefficients.
A body can also have more than one true maximum, and a default start finds
one of them. Nothing in that fit marks it. So from the default start
frm() also fits from each sign pattern of the coefficients that the body
does not read as an added term, and returns the highest point. With four
such coefficients or fewer that is every pattern; with more, every
pattern of the four the body moves most by, so the order of the terms
does not change the answer. A coefficient inside a curve starts where it
moves the curve's argument by about 3 (b2 near 1e-3 in
b1 * exp(b2 * x) with x in the thousands), and one the body is linear
in where it moves the body by about two of the response's units, each
only where that is far from 1, else at 1. A message (class
frmtmb_nl_multistart) says so when that point is higher than the first
fit by more than 0.01. b1 * exp(b2 * x) under bernoulli() on one data
set reads -193.4967 from the default start alone and -189.999 with the
patterns. This makes a fit 1.2 to 2.8 times as slow with two or three such
coefficients, 3.5 to 5.4 times with four, and up to 47 times with five. A
start, or options(frmtmb.nl_sign_probe = FALSE), skips it; a located
prior does not. The patterns are not a proof: a start elsewhere, or a
located prior, can still show a higher maximum. frm_allfit() cannot, as
its optimizers start from one point.
A nonlinear coefficient that the body reads as an added term (a and b
of a + b * x) is stepped in the units by which it moves the body, where
these are 16 or more times from 1: a * x with x near 1e-20 reaches
the maximum of y ~ 0 + x. The curvature of a normal, Student t or
logistic prior on it is added; under another prior with a curved density,
such as a gamma or lognormal prior, it keeps its old steps. In the sign
patterns' runs and the refit of their winner, a coefficient inside a curve
is stepped in its start size where that is 16 or more times from 1 and no
prior reaches it, so b2 of b1 * (1 - exp(-b2 * x)) fits alike with x
near 1 and near 1e-6.
Two vocabularies, one model
This is the flat internal parameterization. get_prior() describes
the same model in the structured class/coef/group/dpar/nlpar
vocabulary that set_prior() addresses, and frm_simulate() also
accepts a natural-scale spelling (sigma, sd_g__Intercept). Use
get_prior() to write priors and par_template() to write starting
values and box constraints.
brms has no counterpart for starting values: brm(init =) takes a
list of Stan program names and its own documentation calls it mainly
an internal testing facility. brms does not need one, because it
initializes at random in a bounded range and its priors carry
location information. frm() optimizes rather than samples, so it
evaluates the objective AT the starting values; this is the discovery
step that makes that survivable.
See also
frm() for start =, get_prior() for the prior
addressing vocabulary, frm_simulate() for newparams =.
Examples
dd <- data.frame(x = rnorm(30), g = factor(rep(1:5, 6)))
dd$y <- 1 + 2 * dd$x + rnorm(30)
# before fitting: the names and the cold starting values
par_template(bf(y ~ x + (1 | g)) + gaussian(), data = dd)
#> <frmtmb parameter template> starting values
#> $beta (2)
#> (Intercept) x
#> 0.9122575 2.4075210
#> $betad (1)
#> sigma_(Intercept)
#> -0.1233936
#> $b (5)
#> b_1 b_2 b_3 b_4 b_5
#> 0 0 0 0 0
#> $theta (1)
#> theta_1
#> 0
#> Edit and pass back as frm(start = ) or frm_simulate(newparams = ). Parentheses are optional in names you supply.
# after fitting: the same layout, holding the estimates
fit <- frm(bf(y ~ x + (1 | g)) + gaussian(), dd)
#> Boundary (singular) fit: sd_g__Intercept is at zero. The likelihood does not change as it moves further that way, so it has no standard error (NaN in summary(), vcov() and confint()); the other standard errors are kept. lme4 reports such a fit as singular; diagnose() lists the components at the boundary
par_template(fit)
#> <frmtmb parameter template> estimates
#> $beta (2)
#> (Intercept) x
#> 0.9122575 2.4075210
#> $betad (1)
#> sigma_(Intercept)
#> -0.1233936
#> $b (5)
#> b_1 b_2 b_3 b_4 b_5
#> -1.642655e-10 9.540896e-10 -2.353597e-10 -9.755872e-10 4.211229e-10
#> $theta (1)
#> theta_1
#> -10.91995
#> Edit and pass back as frm(start = ) or frm_simulate(newparams = ). Parentheses are optional in names you supply.
# discover, edit, fit
st <- par_template(bf(y ~ x) + gaussian(), data = dd)
st$beta["x"] <- 2
frm(bf(y ~ x) + gaussian(), dd, start = st)
#> Family: gaussian
#> Links: mu = identity; sigma = log
#>
#> Formula: y ~ x
#> Data: dd (Number of observations: 30)
#> Method: ML logLik: -38.8663 AIC: 83.7327 BIC: 87.9363
#>
#> Regression Coefficients:
#> Estimate Est.Error l-95% CI u-95% CI z value Pr(>|z|)
#> Intercept 0.91 0.16 0.60 1.23 5.65 1.6e-08
#> x 2.41 0.16 2.09 2.72 15.02 < 2e-16
#>
#> Further Distributional Parameters:
#> Estimate Est.Error l-95% CI u-95% CI
#> sigma 0.88 0.11 0.69 1.14