Repository navigation
Conversation
The B/M/I, cubic-regression and natural-cubic splines asked their target-aware selector for a fixed 3-15 basis-function window and then reduced the result to the needed count with select_knots, which keeps evenly spaced indices of the sorted list. That positional trim routinely discarded the split where the target changes, and capped adaptive widths at 15 (14 / 12 for the cubic families); a window lying entirely above the cap collapsed to min_output_dim. SplinePlacementAdapter.get_knot_locations now accepts a per-call min_knots / max_knots window, and the transformers pass the window resolved from output_dim or [min_output_dim, max_output_dim], so the selector's importance ranking keeps the most informative splits. The spline and adapter docstrings describe the window, and the adaptive tutorial output is updated (both signals now reach the [5, 20] bound). Fixes #69
This was referenced Oct 16, 2026
This branch has not been deployed
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.
Fixes #69.
With
target_aware=True, the B/M/I, cubic-regression and natural-cubic splines cut the selector's knots down to the needed count by position. The knot where the target changes was routinely discarded: atoutput_dim=6, a CART B-spline missed a single step in 199 of 200 simulated datasets. Adaptive widths were also capped at 15 basis functions (14 for cubic regression, 12 for natural cubic) whatevermax_output_dimwas. This affectsPreprocessor(numerical_method="bspline"), which the regression presets select.Root cause
SplinePlacementAdapter.get_knot_locationsalways searched the fixed default window of 3-15 basis functions, independent of the transformer's resolved width.BaseSplineTransformer._adjust_internal_knotsandSplineBasisMixin._clamp_interior_knotsthen reduced the result withselect_knots, which keeps evenly spaced indices of the sorted knot list and ignores the selector's importance ranking. The fixed window also capped adaptive widths, and a window lying entirely above 15 collapsed tomin_output_dim.Fix
SplinePlacementAdapter.get_knot_locationsgains keyword-onlymin_knots/max_knots, which override the adapter's default window for that call.BaseSplineTransformer._column_knotspasses the interior-knot window resolved fromoutput_dimor from[min_output_dim, max_output_dim]on the selector path. When the adaptive distinct-value cap pushesmax_knotsbelowmin_knots,min_knotsis lowered tomax_knotsfirst.SplineBasisMixin._place_interior_knots, used by the cubic-regression and natural-cubic splines, resolves the fixed or adaptive window before calling the selector and passes it.select_knots/ top-up steps stay in place for selectors that return too few or too many knots.The fix in #75 also changed the top-up in
SplineBasisMixin._clamp_interior_knotsto callsupplement_interior_knots, so that every selector knot is kept. That helper is introduced by the PR for #56 (#101) and is not onmain, so this PR keepsmain's top-up there. See Merge notes.Behaviour changes
Preprocessor(numerical_method="bspline")with target-aware placement.max_output_dim. A window lying above 15 no longer collapses tomin_output_dim. On the issue's sine data,[5, 50]now gives 34 for the B/M/I splines, 33 for cubic regression and 31 for natural cubic.docs/tutorials/adaptive_resolution.mdnow printsselected width 20for both signals instead of 15.SplinePlacementAdapter.get_knot_locationstakes two new optional keyword-only arguments. Calls without them use the 3-15 default window as before.knot_locationsand the feature maps are unchanged, and the golden regression baselines pass unchanged.Documentation
SplinePlacementAdapter: class docstring and module comment say that the 3-15 window is only the standalone default.get_knot_locationsgets a NumPy docstring with the new parameters.adaptiveparameter ofBaseSplineTransformer(B-, M- and I-spline),CubicRegressionSplineTransformerandNaturalCubicSplineTransformer: a target-aware selector searches exactly this window (or theoutput_dimwidth) and keeps its most informative splits.docs/tutorials/adaptive_resolution.md: the printed widths change from 15 / 15 to 20 / 20, and the explanation now says that both signals reach the upper bound.Tests
test_target_aware_bmi_spline_keeps_the_dominant_split[{5,6}-{B,M,I}SplineTransformer]: the interior-knot count is exact and one knot lies within 0.1 of the step at 5.0. Fails onmain, passes here.test_target_aware_cubic_families_keep_the_dominant_split[{CubicRegression,NaturalCubic}SplineTransformer]: atoutput_dim=5, one knot lies within 0.1 of the step. Fails onmain, passes here.test_adaptive_spline_width_is_not_capped_at_the_legacy_window[{5-40,20-50}-{BSpline,CubicRegressionSpline,NaturalCubicSpline}Transformer]: the width lies in(max(15, low), high]. Fails onmain, passes here;maingives 15, 14 or 12, and 20 for[20, 50].test_get_knot_locations_window_override(tests/placement/test_spline_placement_adapter.py): a one-knot window returns the step. Fails onmain, passes here.The first three are in
tests/expansion/spline/test_spline_expansions.py.Reproduction
Output of the script from #69 on this branch, with
LeakageWarnings filtered. The script is extended with the per-family adaptive widths, including the[20, 50]window, and the simulation script from the issue:The B-spline now misses the step exactly as often as the RBF with the same number of centers. On
mainit missed 199 and 137 of 200. The remaining misses come from the CART selector's spacing filter, which is #70.Checks
just test: 1453 passed, 59 skipped, 7 xfailed; coverage 93.57% (gate 90%).scripts/quickstart.pypasses.just docs: strict build succeeds.just check: all pre-commit and pre-push hooks pass (ruff format, ruff lint, prettier, file hygiene, pyright with 0 errors).Merge notes
main.BaseSplineTransformer._column_knots, B/M/I spline knot_locations are sized by output_dim and clipped to the data range instead of used as given #81 removes the oldknot_locationsbranch and turnselif selector is not None:intoif selector is not None:right where this PR passes the window. Resolve by dropping the old explicit-knot branch and the secondx_min/x_maxassignment, and keeping this PR's selector branch (min_knots = min(min_knots, max_knots)and themin_knots/max_knotsarguments) asif selector is not None:.tests/expansion/spline/test_spline_expansions.py. Keep both blocks; the import additions merge cleanly.tests/expansion/spline/test_spline_expansions.py. This is an append/append conflict; keep both blocks. Its change topretab/expansion/spline/base.pymerges cleanly.SplineBasisMixin._clamp_interior_knotstoknots = supplement_interior_knots(x, knots, min_count)in place of its top-up block, and update its docstring to match. This is the part of the original change left out here. With it, a short selector set keeps every selector knot instead of being down-sampled together with the quantile / uniform candidates. It only matters for target-aware cubic splines on tied data, where the selector returns fewer interior knots than the window's minimum. The B/M/I splines pick up the same keep-every-knot top-up from Spline knots on tied data land on the range boundary or repeat, producing dead columns and all-zero rows #56's_adjust_internal_knotswithout a follow-up.This change was previously part of #75, which is closed in favour of one pull request per issue.