Changelog
Source:NEWS.md
frmtmb.latent 0.7.3
-
hmm_starts()compares the refits on the value that each one maximized,frmtmb::logLik_penalized(). Under a prior, frmtmb’slogLik()no longer holds the log prior, so a comparison on it would rank the modes on a value that no refit maximized. Needs frmtmb 0.80.0, which addslogLik_penalized().
frmtmb.latent 0.7.2
Needs frmtmb 0.79.0. The package itself is unchanged, and one of its tests pins the interval of fitted() on a mixture_mvn() fit that frmtmb 0.79.0 gives.
frmtmb.latent 0.7.1
Needs frmtmb 0.75.0. The package itself is unchanged, and one of its tests pins the predict(newdata = ) message that frmtmb 0.75.0 gives.
Other changes
The
mixture_mvn()tests compare each result as a ratio to a quantity the run measures, not to an absolute tolerance. The quantity is a log-likelihood’s size, a standard error or the unit roundoff. Each test still fails on a constructed wrong answer. The prior tests read which parameters a prior reaches through frmtmb’s exported functions only.predict(newdata = )of amixture_mvn()fit says why it is refused: the family draws its whole response at once. Through frmtmb 0.74.0 the message named a hidden state sequence, a latent class or a correlated residual. The text is frmtmb’s; a test here pins it.
frmtmb.latent 0.7.0
Needs frmtmb 0.74.0. This package uses the us_sigma() and us_theta() that frmtmb 0.74.0 exports, and its rules name the mixture_mvn feature that this package now supplies. With an older frmtmb, the package does not install.
New features
-
mixture_mvn()moved here from frmtmb (BREAKING for a user of frmtmb: runlibrary(frmtmb.latent)to use it). It fits mixtures of multivariate normal distributions to an n x D matrix response. It has mclust’s eight covariance models, class means that take covariates, and covariate-dependent mixing weights. Nothing about the family changed in the move. On the 59 fits of its tests, these are identical to the last bit to the ones frmtmb gave, on the same machine: the log-likelihood, the estimates, the standard errors,predict(),fitted(),mixture_probs()andsimulate(). Its tests came with it, and they are checked against mclust, which is now in Suggests. Its nine rules of the compatibility matrix are registered when the package loads.
Other changes
-
hmm()reads core’s one list of field terms when it decides whether a distributional parameter is constant. That list holdscar()andspde(), which core now parses through its covariance-structure registry. So the package needs frmtmb 0.74.0, which hasfrmtmb_register_covstruct().
frmtmb.latent 0.6.2
Needs frmtmb 0.72.0: hmm_starts() refits through that release’s update().
Bug fixes
hmm()draws each state at its own rows’ addition terms. The simulator gave the state-dependent family the whole term list. So the j-th row of a state read thetrials()of the j-th row of the data. Take a binomialhmm(K = 2)withNof 2 and 50. In itssimulate(), 26% of the draws exceededN, and theN = 2rows averaged 12.2 wherefitted()says 0.91. The likelihood was not affected.hmm_starts()refits withupdate(), which takes the data, the formula, the family and the control from the fit. Now a fit refits in three cases: its data object is gone from the workspace, it was saved and read back in a new session, or it was made inside a function. Sincehmm_starts()was added (0.55.2 of frmtmb) such a fit stopped with “the model’s own call could not be re-evaluated from here”. Some symbols of the call are not taken from the fit, such asna.action. They still have to be visible from wherehmm_starts()is called. This needs frmtmb 0.72.0.
frmtmb.latent 0.6.1
No change to the package’s code. frmtmb 0.71.0 changes what a model of this package may write.
Breaking changes
-
A constant on a location of
hmm()orlca()is refused, by frmtmb 0.71.0.bf(y ~ x, mu2 = 3)onhmm(2)andbf(Y ~ 1, theta2 = 0.5)onlca(3)used to fit, and the location was estimated anyway: the constant had no effect. The refusal says to write a formula that estimates it, or an offset-only formula (mu2 ~ 0 + offset(o)) that holds it at a known value. This package’s code is unchanged.
frmtmb.latent 0.6.0
frm_compat()recordsautoscaleas working forhmm()andlca(), which frmtmb’s default now engages below a column spread of 1e-3: measured at 1e-6, both reach the scale-1 log-likelihood on 3 of 3 seeds (dev/predfix-p1-ext.Rin the frmtmb repository).BREAKING: a prior on the location of
lca()orhmm()names its class or state withdpar:set_prior("normal(0, 1)", class = "b", dpar = "theta1")for a latent class’s gate,dpar = "mu1"for a hidden state’s mean. A class"b"or"Intercept"prior withoutdparis now refused by frmtmb. Until now it reached every class’s or every state’s coefficients at once.default_prior()lists the rows perdpar. This is frmtmb’s rule for every family whose location is several distributional parameters, the one brms applies to its categorical and mixture families. Requires the frmtmb release that carries it.
frmtmb.latent 0.5.0
-
hmm_starts()’s scale check readsfrmtmb::vcov_estimated()rather thanstats::vcov()on a frmtmb fit.vcov()is brms’s population-level block in frmtmb 0.61.0: it names its rows brms’s way and drops an intercept-only distributional parameter, so the check’s name intersection would have been empty and it would have fallen back to a unit scale without saying why. Requires frmtmb 0.61.0.
frmtmb.latent 0.4.0
Requires frmtmb 0.60.0, for
frm_stop()and the other condition helpers.Requires the frmtmb release that exports
frm_stop(); thefrmtmb (>= 0.59.0)floor must move to it.BREAKING: every error, warning and message that frmtmb.latent raises is classed. An error has the class
c("frmtmb_latent_error", "frmtmb_error", "error", "condition"), and warnings and messages follow the same pattern, sotryCatch(frmtmb_error = )catches any refusal. The class vector no longer containssimpleError,simpleWarningorsimpleMessage. See?frmtmb::frmtmb-conditions.BREAKING: a value that matches none of the choices of
hmm(init =)is refused with afrmtmb_latent_errorthat names the argument, the value and the choices. The old text was'arg' should be one of .... A partial value still matches.hmm_starts()and the otherhmm_*()readers refuse an object that is not a fit by name.hmm_starts(1)used to fail with$ operator is invalid for atomic vectors.The refusals that
hmm()andlca()write infrmtmb_structure(refusals =), such asfrm(..., family = hmm(...), REML = TRUE), are afrmtmb_latent_error. frmtmb raises them, and before they had no subclass.
frmtmb.latent 0.3.1
- Requires frmtmb 0.59.0.
-
hmm()marks its transition parameterstr<i><j>as read on the link scale (a new family field,link_scale_dpars), so frmtmb 0.59.0 reports them as coefficientsb_tr12_Interceptrather than under a probability-like name holding a logit. - Tests follow frmtmb 0.59.0’s brms names and
varcorr_matrices().
frmtmb.latent 0.3.0
hmm_starts()refits from jittered starting values and reports the spread of the optima. The default cold start has been measured converging 8.099 log-likelihood units below the optimum withconvergence0, a positive definite Hessian, anddiagnose()printing “No convergence problems detected”;frm_allfit()reaches that same wrong optimum on all four optimizers with a spread of 7.8e-07, so agreement between optimizers is not evidence here.hmm_starts()recovers from it on 5 of 5 seeds at jitter 1 and above. It costs about 176 seconds per refit at 50 sequences by 500 steps, so?hmmdeliberately recommends no defaultn.-
BREAKING:
lca()’s starting values changed, and a fit can move. The old rule cut subjects on the mean of their item codes, which is blind to any design whose classes differ in WHICH items they endorse rather than how many. On the realistic-scale design that score explains 0.000814 of its own variance between the true classes, and the old rule reached a local optimum 243 to 284 log-likelihood units belowpoLCA(nrep = 10)on 8 of 200 replicates, with a positive definite Hessian on seven of the eight. On at least two of those the cause was the start and not the surface: all 10 of 10 poLCA single random starts found the global optimum there.The rule now clusters on the response pattern and shrinks each class profile nine tenths of the way toward the pooled one. It reaches poLCA’s optimum on 200 of 200 replicates of the block its one constant was tuned on, and on 200 of 200 of a second block of seeds it never saw.
A fit therefore moves where the two starts differ, and it moves to the better optimum. Class 1 is still the low-score end wherever that score means anything; where it does not, the labeling is deterministic but need not match 0.2.2. A 0.2.2 fit can be reproduced:
?lcacarries the old rule as ten lines of R, checked to reproduce the old starting values and the old log-likelihood at a relative difference of exactly 0. Two coefficients under-cover, and there is no remedy yet. Pooled over 400 replicates of the realistic-scale design,
class3:x2covers 91.75 percent andclass4:x290.75 against a nominal 95, while the third binary gating slope and the other six coefficients contain 95. A profile interval was measured and does not help, 103 of 118 both ways, because the standardized error has no heavy tail and no curvature: the shortfall is in the magnitude of the standard error rather than the shape of the likelihood.?lcasays so rather than recommending a remedy nobody has measured.
frmtmb.latent 0.2.2
- Requires frmtmb 0.55.1. A scale row in the gated measurement tier, which finds the hidden Markov post-fit passes are 0.25 and 0.09 seconds at 50 sequences by 500 steps, so the R loops there are not a cost worth removing.
frmtmb.latent 0.2.1
Requires frmtmb 0.55.0, for the hazard-container lint that now runs in this package’s own check.
frmtmb.latent 0.2.0
hmm() declares the per-sequence log-likelihood, so frm(importance = ) and loo() on draws reach it. Requires frmtmb 0.53.0 for the factorization slot.
hmm()declaresfrmtmb_structure(loglik_group = ): the log-likelihood of every sequence, which the forward recursion already produces on its way to the total.frm(importance = )can correct an hmm() fit whose grouping factor is its own sequence variable, andloo()on sampled draws has one column per sequence instead of a refusal. There is nologlik_row, and its absence is the answer rather than an omission: a row’s emission density is not its contribution to the likelihood, because the state that emitted it was reached through every earlier row.residuals(type = "deviance")stays refused for exactly that reason, in the words it already used.lca()declares neither slot, and says why in the source: its likelihood IS rowwise, because one row is one subject’s whole item response pattern, soloo()andfrm(importance = )reach it through the ordinary path and a slot would be a second definition of the same numbers.
frmtmb.latent 0.1.0
First release. hmm() and lca() were part of frmtmb through v0.47.0 and move here unchanged, as step 10 (the last) of dev/structured-family-protocol.md.
hmm(K, family)fits hidden Markov models: covariate-dependent transitions, a choice of initial distribution, the forward algorithm for the exact likelihood, andhmm_probs()andhmm_viterbi()for the smoothed occupancies and the decoded path.lca(K)fits latent class analysis in the manner of poLCA: conditionally independent polytomous items, class-conditional item profiles as family extra parameters, and a multinomial logit on the class membership so that latent class REGRESSION is the ordinary fixed-effect machinery.lca_probs()andlca_profiles()read the fit.Both reach frmtmb only through its exported extension API, and the suite asserts it:
test-structure-latent.Rscans every function in this namespace and fails if one reaches a frmtmb internal.The compatibility rules that name either family register from
.onLoad(), sofrm_compat()gains their rows when this package is loaded and carries no dangling reference when it is not.No behavior changed in the move. Every test came over with its assertions intact.