Classical ML, validation, metrics, interpretation, debugging · insight-1169
Unit-test monotone constraints with paired counterfactual rows instead of trusting the parameter
- Evidence type
- practitioner heuristic
- Difficulty
- medium
- Roles
- Data scientist, ML engineer
- Industries
- banking, aviation, insurance
Summary: situation, action, reason, boundary
Situation
A boosted model carries monotone constraints (a higher fare must not raise predicted bookings) and is retrained often while columns, dtypes and library versions change.
Action
Key constraints by feature name, and add a CI test that takes real rows, steps the constrained feature through a grid with everything else fixed, and asserts predictions never move in the forbidden direction. Fail the retrain on any violation.
Reason
Documentation lists unsupported cases and the guarantee holds only when the configuration reached the training code; an end-to-end test is the only evidence the shipped artifact obeys the rule.
Boundary
Pricing, credit and risk models where direction is policy, not preference.
Symptom or risk
A constraint attached to the wrong column index, a feature type the library does not constrain, or a multiclass objective leaves the rule unenforced, and the violation is found by a customer.
Exceptions
Models with no constraints, or constraints enforced by a monotone parametric form such as a GLM.
Trade-offs
The test samples rows rather than proving the property everywhere, and constraints cost some accuracy.
Pitfalls
Testing on synthetic grids far from real data; one test row per feature is too few.
Lessons and concepts
Claims and their sources
scikit-learn's HistGradientBoosting monotonic_cst is set per feature, is not supported for multiclass classification or categorical features, and constrains the marginal effect only.
XGBoost accepts monotone_constraints as 1, -1 or 0 per feature, or keyed by feature name.