Skip to content

fix(feature-maps): drop the unsupervised relu center at the data maximum - #120

Open
ChrisW09 wants to merge 1 commit into
mainfrom
fix/83-relu-dead-center
Open

ChrisW09 wants to merge 1 commit into
mainfrom
fix/83-relu-dead-center

Conversation

@ChrisW09

@ChrisW09 ChrisW09 commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #83.

With unsupervised placement (target_aware=False, "uniform" or "quantile"), ReLUExpansionTransformer put its last center exactly at the training maximum. The ramp max(0, x - c) of that center was zero on every training row, so output_dim=k gave only k - 1 informative columns per feature. This happened on every fit of the standalone transformer, whose default placement is unsupervised "quantile", and of Preprocessor(numerical_method="relu", target_aware=False, ...).

Root cause

BaseCenterExpansion.fit placed the centers of every feature map through RBFPlacementAdapter.get_centers, which uses endpoint-inclusive locations (include_endpoints=True). That convention suits kernels that respond on both sides of a center (RBF, sigmoid, tanh). For the one-sided ReLU ramp, a center at the maximum is degenerate.

Fix

  • BaseCenterExpansion.fit takes the unsupervised centers from a new hook, _unsupervised_centers(adapter, x, n_centers). The default implementation makes the same adapter.get_centers(x, None, n_centers, n_centers) call as before. The target-aware path still calls adapter.get_centers with the adaptive bounds.
  • ReLUExpansionTransformer._unsupervised_centers places n_centers + 1 range-spanning locations and drops the right endpoint. The first center stays at the training minimum, which gives the linear term, and no ramp starts at the maximum.

Behaviour changes

  • Unsupervised ReLU centers move. Uniform centers are linspace(min, max, output_dim + 1)[:-1], and quantile centers are the matching quantiles without the 100th percentile. Every column is now non-zero on the training data.
  • The output width is unchanged. A zero-range feature still gets output_dim equal centers.
  • RBF, sigmoid, tanh and the target-aware ReLU path are unchanged, and the golden regression baselines pass unchanged.

Documentation

  • ReLUExpansionTransformer docstring: on the unsupervised path, the centers are the first output_dim of output_dim + 1 range-spanning locations, and why the right endpoint is dropped.
  • docs/representations/functional_expansions.md, ReLU entry: the same in prose.
  • Docstrings of the new hook BaseCenterExpansion._unsupervised_centers and of the ReLU override.

Tests

All tests are in tests/expansion/functional/test_reluexpansion_transformer.py.

  • test_unsupervised_relu_has_no_dead_column[uniform, quantile]: all 6 columns are non-zero on the training data and have rank 6, the first center is at the minimum and the last is below the maximum. A zero-range feature keeps output_dim equal centers. Fails on main, passes here.
  • test_unsupervised_relu_uniform_centers_drop_the_right_endpoint: the centers equal linspace(min, max, 7)[:-1]. Fails on main, passes here.
  • test_preprocessor_relu_has_no_constant_column[uniform, quantile]: the issue's Preprocessor case with output_dim=7 gives no constant column and rank 7. Fails on main, passes here.

Reproduction

Output of the script from #83 on this branch:

centers: [3.000e-03 1.907e+00 3.884e+00 5.580e+00 7.034e+00 8.513e+00] | training max: 9.972
per-column max on the training data: [9.969 8.065 6.089 4.392 2.938 1.459]
Preprocessor relu: constant columns [] | rank 7

Checks

  • just test: 1443 passed, 59 skipped, 7 xfailed; coverage 93.66% (gate 90%).
  • Minimum dependencies (CI job: Python 3.10, numpy 1.24.4, pandas 2.0.3, scipy 1.10.1, scikit-learn 1.6.0): 1430 passed, 72 skipped, 7 xfailed; scripts/quickstart.py passes.
  • 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).
  • Import direction between subpackages is unchanged.

Merge notes

This change was previously part of #86, which is closed in favour of one pull request per issue.

On the uniform / quantile path the ReLU expansion reused the feature
maps' endpoint-inclusive centers, so its last ramp max(0, x - c) started
at the training maximum and was identically zero on every training row:
output_dim=k gave only k - 1 informative columns.

The ReLU now places output_dim + 1 range-spanning locations and drops
the right endpoint, so the first center stays at the minimum and no ramp
starts at the training maximum. A zero-range feature keeps output_dim
equal centers. RBF / sigmoid / tanh and the target-aware path are
unchanged. The ReLU docstring and the functional-expansions page
describe the placement.

Fixes #83

This branch has not been deployed

No deployments
Sign up for free to 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.

Unsupervised ReLUExpansionTransformer puts its last center at the training maximum, giving a dead column

1 participant