us_sigma(theta, d) builds the d x d covariance matrix that the
parameter vector of a us() block of frmtmb encodes, and
us_theta(S) is its inverse: the parameter vector whose us_sigma()
is S.
Arguments
- theta
A numeric vector or an RTMB advector of length
d + d * (d - 1) / 2.- d
The dimension of the matrix, a positive whole number.
- floored
FALSE(the default) takes each standard deviation asexp()of its entry.TRUEfloors the scale as the random-effect blocks of frmtmb do, so that a variance the optimizer drives toward zero keeps a finite log-density: it adds1e-150to each standard deviation whend >= 2, and1e-300to the variance whend = 1.- S
A symmetric positive definite numeric matrix.
Value
us_sigma(): a d x d matrix, an advector matrix when
theta is one. us_theta(): a numeric vector of length
d + d * (d - 1) / 2, the inverse of us_sigma(floored = FALSE).
Details
The first d entries of theta are the log standard deviations. The
other d * (d - 1) / 2 entries fill the strict lower triangle of a
unit-diagonal factor L in column-major order: L[2, 1], L[3, 1],
..., L[d, 1], L[3, 2], and so on. Each row of L is then scaled
to unit length, and the correlation matrix is L L'. So every real
vector gives a valid covariance matrix, and a vector of zeros gives
the identity. For d up to 3 this is the same map as glmmTMB's us
structure. From d = 4 the order differs: glmmTMB fills the same
triangle in row-major order, so a glmmTMB theta must be reordered
first.
us_sigma() is AD-safe, so a family can call it inside its density
while the objective is taped. That gives a family a free covariance
matrix as a family-level extra parameter (extra_pars of
frmtmb_family()): declare d + d * (d - 1) / 2 values, start them
at us_theta() of a starting covariance, and read them through
us_sigma() in lpdf and in the simulator. The mixture_mvn()
family of frmtmb.latent builds its class covariances this way. Off
the tape, as.matrix() of the result is an ordinary numeric matrix.
us_theta() is numeric only; it runs off the tape.
See also
frmtmb_family() for extra_pars, frmtmb-robust-dpars
for the other helpers a density can call while it is taped, and
frmtmb_register_covstruct() for a covariance structure whose
lpdf or from_natural can use the same map.
Examples
# standard deviations 2 and 0.5, and one correlation parameter
S <- us_sigma(c(log(2), log(0.5), 1), 2)
S
#> [,1] [,2]
#> [1,] 4.0000000 0.7071068
#> [2,] 0.7071068 0.2500000
cov2cor(as.matrix(S)) # the correlation is 1 / sqrt(2)
#> [,1] [,2]
#> [1,] 1.0000000 0.7071068
#> [2,] 0.7071068 1.0000000
# zero correlation parameters give a diagonal matrix
us_sigma(c(0, 0, 0, 0, 0, 0), 3)
#> [,1] [,2] [,3]
#> [1,] 1 0 0
#> [2,] 0 1 0
#> [3,] 0 0 1
# the parameters of a given covariance, and back
S3 <- matrix(c(4, 1, 0.5, 1, 2, 0.3, 0.5, 0.3, 1), 3)
th <- us_theta(S3)
th
#> [1] 0.6931472 0.3465736 0.0000000 0.3779645 0.2606430 0.1379193
all.equal(as.matrix(us_sigma(th, 3)), S3)
#> [1] TRUE