Skip to content

Don't match auxiliary parameter names fuzzily - #1225

Open
DominiqueMakowski wants to merge 1 commit into
mainfrom
fix-fuzzy-sigma-components
Open

Don't match auxiliary parameter names fuzzily#1225
DominiqueMakowski wants to merge 1 commit into
mainfrom
fix-fuzzy-sigma-components

Conversation

@DominiqueMakowski

Copy link
Copy Markdown
Member

Fixes #1224, and the related component grouping in easystats/parameters#1247.

find_auxiliary() hallucinated sigma

The residual SD was detected by looking for the string "sigma" anywhere in the stan-model's parameter names:

if (any(startsWith(fe, "sigma_") | grepl("sigma", fe, fixed = TRUE))) {
  out <- c(out, "sigma")
}

Custom brms-families whose auxiliary parameters merely contain that string therefore faked a sigma component. The ddm() family from cogmod estimates sigmadrift, sigmabias and sigmandt as constants, so:

m <- readRDS(url("https://raw.github.com/DominiqueMakowski/cogmod/main/vignettes/models/m_ddm.rds"))
insight::find_auxiliary(m)
#> before: "boundary" "bias" "ndt" "sigma"
#> after:  "boundary" "bias" "ndt"

sigma is now matched exactly, and only when it isn't already covered by the model's pforms:

  • sigma — univariate models with a constant residual SD
  • sigma_<response> — multivariate models, validated against the actual response names (both the raw and brms' "cleaned" ones, e.g. sigma_SepalLength for Sepal.Length)
  • sigma1, sigma2, … — mixture models

clean_parameters() lumped sigmabias into sigma

Same root cause, different code path. .get_stan_params() mapped find_parameters() element names to components with a substring test, so the element named sigmabias matched grepl("sigma", ...) and its parameters were labelled Component = "sigma" — even though find_parameters() had correctly returned sigma and sigmabias as separate elements. That is what surfaces as easystats/parameters#1247; parameters itself needed no change, its output is downstream of clean_parameters().

Component names are now compared for exact matches, after stripping the _random suffix that marks the group-level part of a component. The grepl branches for conditional, priors, smooth_terms and dispersion become redundant once that suffix is stripped, since they fall through to the identity default — so they are gone too, which removes the same fuzziness for those.

m_lba <- readRDS(url("https://raw.github.com/DominiqueMakowski/cogmod/main/vignettes/models/m_lba1.rds"))
parameters::parameters(m_lba)
#> before: b_sigmabias_Intercept -> Component = sigma
#> after:  b_sigmabias_Intercept -> Component = sigmabias

Note this model genuinely has an exact sigma parameter (fixed to 1), so the find_auxiliary() fix alone did not address it; it still shows up as its own sigma component, correctly.

Verification

  • Old vs. new find_auxiliary() output compared across 19 downloadable brms models (univariate, mv with dotted response names, mixture, zi, zoib, ordinal, distributional sigma ~ x, sigma with random effects, custom chocomini family) — identical in every case.
  • New tests/testthat/test-brms_dpars.R covers both bugs with lightweight brmsfit mockups (formula + stan parameter names), so no fitting or downloading is needed; the mockups reproduce the real models' output exactly. It also unit-tests the .get_stan_params() component mapping over the element names produced by all five classes that share the helper — brmsfit, stanreg, stanfit, stanmvreg, bamlss — since rstanarm isn't available locally to exercise those paths end-to-end.
  • Full local test suite: no new failures. The three that remain (two lavaan GFI values in test-export_table.R, and rt/RT in test-get_predicted.R:904) reproduce unchanged on main.
  • parameters' own brms|stan|bayes tests pass against this branch.

🤖 Generated with Claude Code

`find_auxiliary()` detected the residual SD by looking for the string
"sigma" anywhere in the names of the stan-model's parameters. Custom
brms-families whose auxiliary parameters merely *contain* that string
(e.g. the "sigmadrift", "sigmabias" and "sigmandt" parameters of the
`ddm()` family from *cogmod*) hence produced a "sigma" component that
does not exist in the model. Sigma is now matched exactly, and only
when it isn't already covered by the model's "pforms": as "sigma" for
univariate models, "sigma_<response>" for multivariate models, and
"sigma1", "sigma2" etc. for mixture models.

`clean_parameters()` had the same problem when mapping the elements of
`find_parameters()` to components: the element named "sigmabias" matched
`grepl("sigma", ...)`, so its parameters were lumped into the "sigma"
component, although `find_parameters()` correctly returned the two as
separate elements. Component names are now compared for exact matches,
after stripping the "_random" suffix that marks the group-level part of
a component. This also fixes the related grouping in
easystats/parameters#1247.

Fixes #1224

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 7, 2026 20:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The changes are narrowly scoped, improve correctness without altering intended outputs for valid sigma parameters, and are backed by targeted regression tests.

Pull request overview

This PR fixes incorrect fuzzy matching of auxiliary/distributional parameter names in brms models, which previously caused "sigma" to be detected/assigned when parameter names merely contained the substring "sigma" (e.g. "sigmabias"), addressing insight#1224 and the downstream grouping issue seen in easystats/parameters#1247.

Changes:

  • Tighten find_auxiliary.brmsfit() to add "sigma" only when an actual sigma parameter is present (univariate, multivariate sigma_<response>, or mixture sigma1, sigma2, …) and not already covered by pforms.
  • Make .get_stan_params() (used by clean_parameters()) map components via exact name matching after stripping the "_random" suffix, eliminating substring-based component lumping.
  • Add focused unit tests with lightweight brmsfit mock objects; document the fixes in NEWS.md and bump the dev version.
File summaries
File Description
tests/testthat/test-brms_dpars.R Adds unit tests that reproduce and prevent the sigma substring mis-detection/regression without requiring fitted/downloaded models.
R/find_auxiliary.R Replaces fuzzy "sigma" detection with exact matching via a dedicated .brms_has_sigma() helper.
R/clean_parameters.R Switches component mapping to exact matches after removing "_random" suffix, preventing mis-grouping of custom auxiliary parameters.
NEWS.md Notes both bug fixes in the current (devel) section.
DESCRIPTION Bumps package dev version to 1.5.4.1 for the user-visible bug fix.
Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

find_auxiliary() hallucinates sigma parameters

2 participants