Skip to content

Monotone feature constraints in the distilled whitebox - #21

Merged
orgoca merged 1 commit into
mainfrom
feat/monotone-constraints
Aug 27, 2026
Merged

Monotone feature constraints in the distilled whitebox#21
orgoca merged 1 commit into
mainfrom
feat/monotone-constraints

Conversation

@orgoca

Copy link
Copy Markdown
Owner

Closes#8

What this adds

Trainingtrain_whitebox(monotone_constraints=...) accepts a per-feature sequence of -1/0/+1, an index-keyed dict, or a name-keyed dict when X is a DataFrame. Any nonzero sign switches the backend to HistGradientBoostingRegressor (the only sklearn GBM that enforces monotonic_cst during tree growth). Without constraints the classic GradientBoostingRegressor path is untouched — the committed reference artifact hash is unchanged.

Extraction — new sklearn_hist family walker with the same random-row parity gate as the other families (measured max error vs model.predict: 0.0 on 200 rows). HGB leaves arrive pre-shrunk (learning_rate=1.0 in the artifact); categorical splits are refused at the model level because they remap feature_idx inside the predictor nodes.

Verification, independent of the trainer — the design center of the PR. build_artifact(monotone_constraints=...) re-verifies the declaration against the quantized integer trees (per-tree, any depth — a sum of monotone trees is monotone) and refuses to build on any violation, whatever produced the model. Verified signs are recorded as model.monotone_constraints: optional, hash-covered, spec §3.1, schema_version unchanged.

Enforcement ladder — train (enforced) → build (verify-or-raise) → validation check 9 (re-verifies from the artifact alone, no data needed) → at depth ≤ 2, scorecard_monotone_report certifies the aggregate direction on the printed scorecard tables via worst-case bin-to-bin increments — a check a validator can repeat in a spreadsheet.

Measurementsweep_whitebox(monotone_constraints=...) for the monotonicity premium; the tuning guide shows the two-sweep diff.

Tests (17 new)

The fixture teacher has a deliberate local inversion (x0 − 1.2·sin(2.5·x0) dips while trending up), so the tests have teeth: the unconstrained whitebox provably violates and the verifier provably catches it; the constrained backend provably doesn't. Also covered: extraction parity, build refusal, hash coverage of the recorded field, constrained rebuild determinism (hash-identical), check 9 pass/skip/fail (fail via a hand-tampered declaration), scorecard certification both ways, categorical guard, and constraint-form normalization.

test_validate's fixture now declares the (genuinely monotone) teacher's directions so its all-nine-checks-run assertion holds.

Notes

)
Training: train_whitebox(monotone_constraints=...) switches the whitebox
backend to HistGradientBoostingRegressor (monotonic_cst enforced during
growth); the unconstrained GradientBoostingRegressor path is untouched.
New sklearn_hist extractor with random-row parity validation; categorical
splits are refused at the model level.
Verification is trainer-independent: build_artifact re-checks the declared
directions against the quantized integer trees (per-tree, any depth) and
refuses to build on violation, then records the signs as
model.monotone_constraints — optional, hash-covered, spec section 3.1.
Validation gains check 9, re-verifying from the artifact alone. At depth
<= 2, scorecard_monotone_report certifies the aggregate direction on the
printed scorecard tables via worst-case bin-to-bin increments.
sweep_whitebox(monotone_constraints=...) measures the monotonicity
premium. Docs: tuning guide section, FAQ entry, spec 3.1, nine-check
tables. Tests use a teacher with a deliberate local inversion so the
unconstrained whitebox provably violates and the verifier provably
catches it.
@orgoca
orgoca merged commit 1451de3 into mainAug 27, 2026
20 checks passed
@orgoca
orgoca deleted the feat/monotone-constraints branch August 27, 2026 18:50
@orgocaorgoca mentioned this pull request Aug 27, 2026
Sign up for freeto 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.

Support monotone feature constraints in the distilled whitebox

1 participant

@orgoca