Add within-group lengthscale shrinkage prior for the strength GP - #20
Merged
Conversation
SebastianAment
force-pushed
the
within-group-lengthscale-prior
branch
2 times, most recently
from
May 13, 2026 20:59
05eb009 to
f54fb2e
Compare
In the strength GP fit on the public dataset, the Matern ARD
lengthscales for Fly Ash and Coarse Aggregates rail to the upper
cap (~1000): both features are under-sampled relative to Cement and
Fine Aggregate, so the marginal likelihood is essentially flat in
their lengthscale direction and the optimiser drifts to the constraint
boundary. This makes the strength surface look insensitive to those
two ingredients in the explorer UI, even though concrete chemistry
clearly says it isn't.
This PR introduces `WithinGroupShrinkagePrior` — a soft hard-tying
prior that ties Matern ARD lengthscales within material groups. The
production setting (`sigma=0.001`) ties members of {Cement, Fly Ash,
Slag} to a single binder lengthscale, and {Fine, Coarse} aggregates
to a single aggregate lengthscale, encoding the domain prior that
ingredients of the same material class should share kernel smoothness.
The structural prior:
* Beats the no-prior baseline on held-out LOO CV RMSE — 725 vs
772 psi on the 647 public strength rows, via the GP's closed-form
LOO identity.
* Encodes only group structure (a public, ASTM-defined fact about
cementitious vs aggregate materials), not any numeric values.
* Makes Fly Ash and Coarse Aggregate sliders responsive in the
explorer UI: both lengthscales now sit at 4.79 and 6.67
respectively, well below the cap and within the same range as
the previously-identifiable features.
Adds 11 regression tests in `test/test_lengthscale_identifiability.py`
covering identifiability against the cap, within-group tying on both
the committed and freshly-fit GP, prior installation by
`fit_strength_gp`, an LOO-CV ceiling that catches the no-prior baseline,
and unit tests for the prior class. A reproducible empirical sweep
(`scripts/lengthscale_prior_study.py`) lets users re-run the variant
comparison on their own machine. `docs/model/{strength,compositions,
test_vectors}.json` are regenerated with the new fit; the JS GP
inference and JS<->Python parity tests stay green. All LOO computation
re-uses `boxcrete.compute_loo_cv` (now also re-exported from the
package root).
See `WithinGroupShrinkagePrior` docstring in `boxcrete/models.py` for
the full empirical comparison and methodology.
SebastianAment
force-pushed
the
within-group-lengthscale-prior
branch
from
May 13, 2026 21:08
f54fb2e to
d617837
Compare
SebastianAment
added a commit
that referenced
this pull request
May 13, 2026
Brings every PR-blocking GitHub Actions check under a single `make` invocation so contributors can reproduce CI locally before pushing. Why --- The Tests workflow installs `black` via `pip install black` (latest available), which silently drifted from contributors' environments and caused two force-pushes on #20 to chase formatting fixes the local `black` couldn't see. CI also has four other workflows (js-sync, e2e, notebooks, lighthouse) with no documented local equivalent. What ---- * `Makefile` with one target per workflow: - `lint` / `test-py` / `test-js` / `test-notebook-fmt` (fast) - `test-notebooks` / `test-e2e` / `test-lighthouse` (slow) - `check` = lint + fast tests; `check-all` = full CI parity. * `.pre-commit-config.yaml` runs the same black + flake8 checks that CI does, automatically on every commit. * `pyproject.toml`: black bumped from `>=23.0.0` to `==26.3.1` (the current CI version) and `pre-commit` added to `[dev]` extras. * `.github/workflows/tests.yml`: lint job now `pip install -e ".[dev]"` so CI uses the pinned version too — eliminates the drift class of failure. * `CONTRIBUTING.md`: one-time setup, daily-use, before-push, and a per-target table mapping each Make target to its CI workflow. Bumping black requires updating .pre-commit-config.yaml + pyproject.toml + running `make lint` in lockstep.
SebastianAment
added a commit
that referenced
this pull request
May 13, 2026
Brings every PR-blocking GitHub Actions check under a single `make` invocation so contributors can reproduce CI locally before pushing. Why --- The Tests workflow installs `black` via `pip install black` (latest available), which silently drifted from contributors' environments and caused two force-pushes on #20 to chase formatting fixes the local `black` couldn't see. CI also has four other workflows (js-sync, e2e, notebooks, lighthouse) with no documented local equivalent. What ---- * `Makefile` with one target per workflow: - `lint` / `test-py` / `test-js` / `test-notebook-fmt` (fast) - `test-notebooks` / `test-e2e` / `test-lighthouse` (slow) - `check` = lint + fast tests; `check-all` = full CI parity. * `.pre-commit-config.yaml` runs the same black + flake8 checks that CI does, automatically on every commit. * `pyproject.toml`: black bumped from `>=23.0.0` to `==26.3.1` (the current CI version) and `pre-commit` added to `[dev]` extras. * `.github/workflows/tests.yml`: lint job now `pip install -e ".[dev]"` so CI uses the pinned version too — eliminates the drift class of failure. * `CONTRIBUTING.md`: one-time setup, daily-use, before-push, and a per-target table mapping each Make target to its CI workflow. Bumping black requires updating .pre-commit-config.yaml + pyproject.toml + running `make lint` in lockstep.
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.
In the strength GP fit on the public dataset, the Matern ARD lengthscales for Fly Ash and Coarse Aggregates rail to the upper cap (~1000): both features are under-sampled relative to Cement and Fine Aggregate, so the marginal likelihood is essentially flat in their lengthscale direction and the optimiser drifts to the constraint boundary. This makes the strength surface look insensitive to those two ingredients in the explorer UI, even though concrete chemistry clearly says it isn't.
This PR introduces
WithinGroupShrinkagePrior— a soft hard-tying prior that ties Matern ARD lengthscales within material groups. The production setting (sigma=0.001) ties members of {Cement, Fly Ash, Slag} to a single binder lengthscale, and {Fine, Coarse} aggregates to a single aggregate lengthscale, encoding the domain prior that ingredients of the same material class should share kernel smoothness. The structural prior:Adds 11 regression tests in
test/test_lengthscale_identifiability.pycovering identifiability against the cap, within-group tying on both the committed and freshly-fit GP, prior installation byfit_strength_gp, an LOO-CV ceiling that catches the no-prior baseline, and unit tests for the prior class. A reproducible empirical sweep (scripts/lengthscale_prior_study.py) lets users re-run the variant comparison on their own machine.docs/model/{strength,compositions, test_vectors}.jsonare regenerated with the new fit; the JS GP inference and JS<->Python parity tests stay green. All LOO computation re-usesboxcrete.compute_loo_cv(now also re-exported from the package root).See
WithinGroupShrinkagePriordocstring inboxcrete/models.pyfor the full empirical comparison and methodology.