Repository navigation
Use ucminf() with forward differences in the clmm() submodel fits - #596
Merged
Merged
Conversation
aloctavodia
approved these changes
Nov 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was assisted by Claude.
Speedup
projpred fits multilevel submodels of
brms::cumulative()reference models withordinal::clmm().clmm()has no analytic gradient, so its default optimizernlminb()computes the gradient by finite differences. In a benchmark, 186 of the 230 objective evaluations of a submodel fit were for such gradients. Withmethod = "ucminf"andgrad = "forward"(seeordinal::clmm.control()), a fit needs about 133 evaluations.Change
This PR makes
fit_cumul_mlvl()use these settings when the submodel has a single group-level term(1 | <group>).clmm()can useucminf()only for such models. For other models,clmm()switches tonlminb()with a warning, so the PR keepsnlminb()for them. Amethodorcontrolthat the user gives in...replaces the default. If theucminf()fit fails or does not converge,fit_cumul_mlvl()refits with the default settings ofclmm()and drops the warnings of the first fit.check_conv_s()needs a new rule forucminf()fits, becauseucminf()never returns thenlminb()success code 0. The new rule accepts the codes 1 (small gradient), 2 (small step) and 4 (zero step in the line search). It also requires that the largest absolute gradient after the fit is below 1e-3;clmm()stores the gradient infit$gradient. Code 4 is common with forward differences near the optimum. A probe with 300 submodel fits had 13 code-4 fits, with a median largest absolute gradient of 7e-6. Thenlminb()fits that the check on master accepts had largest absolute gradients up to 1.9e-3.Speed benchmark
The table gives run times on simulated data with 300 observations, 4 response categories, 6 predictors and one grouping factor (
(1 | g)). "LOO" iscv_varsel()withvalidate_search = TRUE,refit_prj = TRUE,nloo = 10andnterms_max = 4;varsel()usesnterms_max = 6. One SLURM job ran each version twice on the same node; the speedup compares the runs with the same run number. The node had a high load from other jobs, so the times vary. Two earlier jobs with intermediate commits of this branch gave speedups of 1.5 to 1.7.varsel()Tests
Both versions give the same predictor rankings (full data and CV folds) and the same suggested sizes. Over all submodel sizes, the elpd differs by at most 1e-4. In the LOO run, 52 of the 21,120
ucminf()fits did not passcheck_conv_s(); the refits withnlminb()passed for 26 of them. projpred's warnings about submodel fits that "might not have converged" count 26 fits with this PR and 30 fits with master.The new file
test_fit_cumul_mlvl.Rchecks the default and the user settings, the models withoutucminf(), the refit, and the new rule ofcheck_conv_s(). It needs no reference model fits, so it also runs on CRAN. Without this change, 5 of its expectations fail and one test stops with an error. The full test suite passes after a merge of the current master (R 4.5.3, testthat 3.3.2, 58,933 expectations).