Hierarchical Piecewise Regression with Smoothed Change-Points
Overview
Fits Bayesian hierarchical piecewise regression models with multiple logistic-smoothed change-points. Non-linear parameters (change-point locations and transition sharpness) and linear parameters can each be conditioned on covariates and factors via flexible design matrices. A random-intercept structure is supported for any parameter. Spike-and-slab regularization is supported for selecting the number of breakpoints. Posterior inference uses a Metropolis-within-Gibbs sampler implemented in 'Rust' for speed. Methods are based on the smooth transition piecewise regression model of Bacon and Watts (1971) doi:10.2307/2334389 and variable selection spike-and-slab priors of Kuo and Mallick (1998) https://www.jstor.org/stable/25053023. Methods are described in Bindoff (2026) doi:10.48550/arXiv.2606.19044.
Sampler correctness
- Fixed the NUTS proposal rule in the random-effects sampler. The doubling loop updated its proposal from the newly built subtree without checking whether that subtree had terminated, omitting the
s' = 1guard of Hoffman and Gelman (2014, Algorithm 3). A subtree that ends on a U-turn contains states the reverse trajectory could not reach, so proposing from it breaks reversibility; because U-turn termination is the ordinary way the loop ends, this affected a large share of transitions rather than a rare tail. The effect is not subtle. Sampling a standard normal with the affected code returns a variance of 1.24 rather than 1.0, over-dispersed in the direction the bug predicts, since the wrongly admitted proposals come from beyond the U-turn. In fitted models the over-dispersed random effects degrade the fit and the residual scale absorbs it, which is how this surfaced:sigmawas systematically over-estimated in simulation-based calibration whileomega,deltaandsigma_relooked calibrated. **Any random change-point or random-slope fit produced by 0.2.x should be re-run.** Only the random-effects sampler is affected; the non-hierarchical entry points use fixed-length HMC with a single Metropolis correction and are unaffected, which simulation-based calibration confirms.
Show all changes in 0.2.8Hide the rest of the changes in 0.2.8
- Fixed the change-point translation move under
reparameterise = "omega".omega_translation_step()rescaled the random-effect columns bysigma_re, but those columns always hold centred values. Every other sampling step converts back on write-back, andomega_vec()feeds them straight into the likelihood. The move therefore shifted the subject-level change-points instead of leaving them invariant, while still being accepted with probability one. Results computed withreparameterise = "omega"and a random change-point should be regarded as unreliable and re-run. The default,reparameterise = "none", was never affected.
Sampler efficiency
- The change-point update is now collapsed (Rao-Blackwellised): the linear block (
b0,b1, the slope changes) is integrated out analytically beforeomegais drawn, then resampled from its full conditional given the newomega. Previouslyomegawas drawn conditional on a single draw of those coefficients and vice versa, so the chain traversed the strongomega-deltadependence one axis at a time. On a single-change-point model this raised bulk ESS foromegafrom a median of 394 to 5588 out of 5000 posterior draws, cut the worst R-hat from 1.090 to 1.006, and cost about 14% more time per fit. Posterior marginals are unchanged; only the efficiency differs. Note that the collapse necessarily runs in this direction.omegacannot be integrated out of thedeltaupdate, since it enters throughd = t - omegaand the transition weights(d; rho)and that integral has no closed form. The linear block can be integrated out of theomegaupdate because it is conditionally Gaussian, and that breaks the same dependence. Models that place finite bounds on a linear coefficient (prior_normal(lb=, ub=)onb0,b1ordeltas) keep the previous conditional update, because the marginal likelihood of a box-truncated Gaussian is not available in closed form. - Added a joint translation move for the population intercept and the group-level random intercepts,
b0 -> b0 + candu_j -> u_j - c. Only the sumb0 + u_jis identified within a group, so updating the fixed coefficients conditional on the random intercepts and vice versa could not traverse the ridge between them:b0reached a bulk effective sample size of 91 out of 4000 draws on the vignette's random-intercept model while every other parameter mixed freely. The move raises that to 3558 at no measurable cost in run time. The shift leaves the mean function exactly invariant, socis drawn from its prior-only conditional and accepted outright; it is skipped when invariance would not hold (no intercept column, or observations outside every group). Note that the package documentation previously described the fixed and group-level intercepts as being updated in a single joint block. They were not, which is what the low effective sample size reflected. - The spike-and-slab inclusion indicators now use a collapsed (Rao-Blackwellised) update: the slab coefficient is integrated out analytically before the indicator is drawn, then resampled given the new indicator. Previously each indicator was drawn at the current coefficient, so an excluded coefficient sat wherever the diffuse slab put it, fitted badly, and rarely re-entered. The indicator and its coefficient locked together and indicator ESS fell into the tens. This targets the same posterior as before (it is a better sampler of it, not a different model), so posterior inclusion probabilities keep their meaning.
- The collapsed update also honours bounded slabs (
prior_normal(lb=, ub=)ondeltasorb1), which the previous indicator update ignored, and uses the learnedsigma_rerather than the fixed-effect prior as the slab for random-effect columns.
Validation
tools/sbc_ecdf_bands.Rnow puts every estimated parameter on the SBC figure and writes PASS/FAIL, interval-coverage and run-regime tables totools/part3_results/. Previouslyb0,b1andsigmawere checked only on the console and left no artefact, which is why a systematicsigmamiscalibration went unnoticed.- The calibration evidence for this release is four independent SBC runs of 500 replicates each:
rhoestimated,rhofixed at its generating value,rhofixed underreparameterise = "omega", and a random-intercept run with a population change-point. Every estimated parameter passes in all four on the full sample of 500 fits. The fourth run exists because the other three useb0 = ~ 1, so the newb0/utranslation move never fires in them and they carry no evidence about it. - The simultaneous ECDF confidence band is now drawn from a seed derived from its own shape rather than from the ambient RNG stream. The band is itself a Monte Carlo object, and left unseeded it moved enough between runs that reported deviations drifted by a few hundredths, so a table typed from one run no longer reproduced from the same saved ranks. Consecutive runs now write byte-identical tables.
- Every arm now writes a regime record. The random-intercept arm previously wrote none, which left the one run that exercises the
b0/utranslation move as the only one whose priors and design were unrecorded. - The rank, ECDF, coverage and regime files for all four arms are tracked in the repository, each rank file stamped with the
smoothbpversion that produced it, so the reported numbers can be checked against the source without rerunning 2000 fits.
From NEWS.md in the release
Install
Health
- OK13 OK2026-08-04
- NOTE12 OK, 1 NOTE2026-08-01
- OK13 OK2026-07-30
- NOTE12 OK, 1 NOTE2026-07-29
- OK13 OK2026-06-17
Show 6 earlier changesHide 6 earlier changes
- ERROR12 OK, 1 ERROR2026-06-14
- OK13 OK2026-06-09
- ERROR12 OK, 1 ERROR2026-06-08
- WARNING12 OK, 1 WARNING2026-06-07
- OK8 OK2026-06-03
- ERROR5 OK, 2 ERROR2026-06-02
Documentation
- Help pages
- 34 (2 internal)
- Examples that run
- 14%1 run in a plain check · 6 never run
- Exported functions with examples
- 32%
- Documented parameters
- 98%
- Return-value docs
- 95%
- Help pages citing references
- 3%
Downloads
Repository
- PRs merged (all time)
- 100%
- Median days to close, 50 most recently updated closed issues
- 9
- Median days to close, 50 most recently updated closed PRs
- 0
Stars over time
Releases over time
Issues over time
Commits over time
4 development-tooling and community-health practices detected across 2 families in the upstream repository
Checks run against github.com/abindoff/smoothbp on 2026-10-18.
This repository shows signs of AI coding tools.
- Claude Codefirst seen on or before 2026-04-29Named in .Rbuildignore: .claudePull request it wrote: opened by a project memberCommits: at least 28 crediting it in the message
- Claude Sonnet 4.627 commits · May to Jun 2026
- Claude Fable 51 commit · Aug 2026
Dependencies
Installing smoothbp adds 49 packages (25 with compiled code, 46 MB of source tarballs). Heaviest: stringi 11 MB, ggplot2 6.0 MB, bayesplot 5.0 MB.
Code & Tests
People & History
Pick two releases to compare their code metrics.
- 0.2.8Latest
- 0.2.7
- 0.2.4
- 0.2.22026-06-02 · diff ↗
- 0.2.12026-06-01
- RR 4.6.0 released · 2026-04-24
Package metadata
- First published
- 2026-06-01
- Total releases
- 5 / 1 yrs
- License
- MIT + file LICENSE OSI
- Minimum R
- ≥ 4.2
- Download size
- 2.9 MB
Cite
Cite this package
Run in R for the authors' entry:
citation("smoothbp")The package provides a citation file, so citation() returns the authors' own entry.
It points to 10.48550/arxiv.2606.19044.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-21, which the citation names so these numbers can be found later. More on citing and the projects behind them.