Apply regression target transforms to the unnormalized target [RES-2639] - #1196
Apply regression target transforms to the unnormalized target [RES-2639]#1196bejaeger wants to merge 2 commits into
Conversation
The regressor z-normalises the target before the ensemble preprocessing, so every target transform used to act on standardized values: `1_plus_log` was log1p of a z-score rather than of the target, undefined wherever the z-score drops below -1 (15% of the rows for a symmetric target in a quick check), and those NaNs went to the model unguarded. Each transform is now composed into a pipeline that undoes the z-normalisation, applies the transform to the target in its original units, and standardizes the result, which is the scale the bar distribution expects. The pipeline's input and output stay in the z-normalised space, so the border mapping in `predict` -- and the z-unit sanity limits applied to those borders -- are unchanged. This changes the predictions of the v2, v2.5 and v3 defaults, whose ensembles use `safepower` for half of their estimators. The v2.6 default (`"none"`, now treated as no transform) and estimators without a target transform stay bit-identical. Also fixes the docstring of `_transform_labels_one`, which called its input "unprocessed". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit bf24f1d. Configure here.
| [c.target_transform for c in conf], | ||
| mean=float(train_mean), | ||
| std=float(train_std), | ||
| ) |
There was a problem hiding this comment.
Finetuning skips fitted target transforms
Medium Severity
RegressorBatch still ships list(conf) for border mapping, not the configs returned on ensemble_members after fit_transform_ensemble_members. With n_preprocessing_jobs > 1, wrap_target_transform's outer StandardScaler is fitted only on the worker copy, so finetuning inverse_transform on bar borders can hit an unfitted pipeline or decode with the wrong scale. predict_batched already takes member configs for this reason.
Additional Locations (1)
Triggered by learned rule: Use executor_.ensemble_members configs, not ensemble_configs_, for fitted transforms
Reviewed by Cursor Bugbot for commit bf24f1d. Configure here.
|
Superseded by the #1198 → #1199 stack, which removes the estimator's up-front z-normalisation of the target instead of composing it into each target pipeline. Same semantics as this PR (verified to 1e-7 relative on five datasets, so the TabArena validation transfers), without the baked-in statistics or the rebinding they forced on the fine-tuning path. |


Closes RES-2639.
Problem
The regressor z-normalises the target before the ensemble preprocessing, so every entry of
REGRESSION_Y_PREPROCESS_TRANSFORMSacted on standardized values rather than on the target.1_plus_logwaslog1pof a z-score, not of the target — undefined wherever the z-score drops below -1, which is 15% of the rows for a symmetric target, and those NaNs reached the model unguarded because the log presets have no trailing scaler.Change
wrap_target_transformcomposes each transform into a pipeline thatThe pipeline's input and output stay in the z-normalised space, so nothing downstream moves:
inverse_transformmaps the model's bar-distribution borders straight back into z-space, exactly as an unwrapped transform did, and the±1e3sanity limits applied to those borders keep the z-units they were tuned in. That is whypredict,predict_batchedand the border mapping are untouched.The fine-tuning data pipeline re-splits and re-normalises per split, so it rebinds the statistics before fitting.
"none"is now treated as no transform at all, since composing the identity would only add float noise.Also fixes the docstring of
_transform_labels_one, which called its input "unprocessed" (the second item on the ticket).Impact
Changes the v2 / v2.5 / v3 defaults, whose ensembles use
safepowerfor half of their estimators — up to ~4% relative prediction change on california housing. Bit-identical for the v2.6 default (("none",)), forn_estimators=1on any version, and for every estimator whose target transform isNone.Tests
New
tests/test_preprocessing/test_target_transform.py(17 cases) plus 4 regressor-level tests; two of them fail onmainand pass here. Full local sweep of regressor + classifier interface, preprocessing, consistency, finetuning-regressor, save/load and inference-tuning suites passes.🤖 Generated with Claude Code