Regression priors are generated for fixed offset() terms and explicit offset priors are silently ignored
- Dominant language
- Python
- Stars
- 124
- Forks
- 24
- Avg merge
- 19h 32m
- Merged PRs (30d)
- 60
Description
## Summary
HSSM generates and displays regression priors for `offset()` terms even though Formulae/Bambi define an offset as a fixed addition with coefficient one. Exact user priors for offsets are likewise retained in HSSM's prior dictionary but silently ignored when Bambi builds the model.
The likelihood contribution is correct; model reporting and explicit-prior handling are not.
This was reproduced against HSSM `main` at `5e8610b9`, Bambi 0.20, and Bambi current `main`.
## Reproducer
```python
model = hssm.HSSM(
data=data,
include=[{"name": "v", "formula": "v ~ 1 + offset(exposure)"}],
prior_settings="safe",
)
model.params["v"].prior["offset(exposure)"]
# Normal(mu=0, sigma=0.25)
model.model.components["v"].terms["offset(exposure)"].prior
# 1
```
No coefficient random variable is created. If an exact prior such as `Normal(10, 1)` is supplied for `offset(exposure)`, HSSM displays it but Bambi still fixes the coefficient to one.
## Root cause
HSSM's safe-prior loop treats every non-HSGP, non-intercept common Formulae term as an estimated coefficient. It does not special-case `term.kind == "offset"`.
Bambi intentionally:
- constructs an `OffsetTerm` with prior `1`;
- skips offsets during prior construction/update;
- adds the offset column directly to the linear predictor.
Thus generated and exact offset priors can never affect the graph.
## Expected behavior
- HSSM should not generate a prior for an offset.
- An exact explicit prior key for an offset should fail early with an explanation instead of being silently discarded.
- A `"common"` wildcard should remain valid for ordinary common terms and should not be rejected merely because the formula also contains an offset.
- Bambi's fixed coefficient-one offset contribution must remain unchanged.
## Proposed commit plan
This work should start after #1227 because it uses the always-run Formulae metadata preparation introduced there.
### 1. `refactor: cache fixed Formulae offset terms (#1234)`
- Extend `RegressionParam`'s prepared metadata with exact offset-term names.
- Cache strings only; do not retain Formulae objects or matrices.
- Preserve the existing public/private `terms` behavior.
- Test one offset, multiple offsets, transformed offset expressions, RHS-only formula shorthand, and formulas mixing offsets with ordinary/HSGP/group terms.
### 2. `fix: exclude fixed offsets from regression priors (#1234)`
- Skip offset terms during safe-prior generation, analogous to the HSGP special case.
- Validate exact user prior keys for offsets under both `prior_settings="safe"` and `None`.
- Raise an actionable error explaining that `offset(x)` has coefficient one and that an estimated coefficient should be written as an ordinary term.
- Preserve exact-over-wildcard precedence for ordinary terms and do not reject the `"common"` wildcard.
- Assert that Bambi still stores prior `1`, creates no offset coefficient RV, and preserves the raw offset contribution in predictions.
### 3. `docs: document fixed offset semantics (#1234)`
- Explain that offsets are fixed additions on the linear-predictor scale.
- Contrast `offset(exposure)` with an estimated `exposure` coefficient.
- Add an Unreleased changelog entry.
- Note a possible Bambi follow-up to reject exact offset priors upstream as well.
## Acceptance criteria
- Safe HSSM prior dictionaries contain no offset keys.
- Exact offset priors fail early under both prior modes.
- Bambi retains coefficient one and no offset free RV appears.
- Ordinary exact/common-wildcard priors and HSGP handling remain unchanged.
- Predictions retain the offset contribution exactly.
- Focused Formulae/model-structure tests, the non-slow suite, Ruff, Pyrefly, mypy, and strict docs pass.
## Related work
- #1227 provides the structural metadata path this fix should extend.
- Closed #851 concerns non-centered latent variables named `*_offset` and is unrelated to formula offsets.
Contributor guide
Research direction
Start with RegressionParam's prepared Formulae metadata and the safe-prior loop described in the issue; trace how offset terms and exact or wildcard prior keys are handled. Extend the metadata and prior validation while preserving Bambi's coefficient-one offset behavior, then run the focused Formulae/model-structure tests and the non-slow suite. Update the documentation and Unreleased changelog, and verify Ruff, Pyrefly, mypy, and strict docs checks pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- machine-learning
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100