Skip to content

Give each regression member its own target pipeline [RES-2639] - #1198

Merged
bejaeger merged 5 commits into
mainfrom
benjamin/res-2639-target-encoder-refactor
Oct 28, 2026
Merged

bejaeger merged 5 commits into
mainfrom
benjamin/res-2639-target-encoder-refactor

Conversation

@bejaeger

@bejaeger bejaeger commented Aug 21, 2026 •

Copy link
Copy Markdown
Collaborator

Generated by Codex

Give each regression ensemble member an invertible target pipeline while retaining the order: standardize, then apply the preset. Keep the raw-target mean and standard deviation as the shared aggregation frame, and require that frame when fitting preprocessed regression batches. Document that saved fitted regressors must be refitted after this change.

PR 1 of 2 for RES-2639. Follow-up: #1199 changes transform order and preserves input standardization inside regression safepower.

Behavior and review fixes
  • Row-subsampled members normalize using their own training rows. With full contexts, small prediction differences can still arise from floating-point border mapping.

  • Inverse-transformed borders return to the shared standardized frame in float64 before narrowing. Grouped prediction uses each dataset's frame.

  • Saved .tabpfn_fit regressors and fitted pickles from earlier versions are incompatible and must be refitted. The breaking changelog documents this; there is no version stamp or runtime compatibility check.

  • RegressorBatch.y_train_mean and y_train_std are required. Custom loops must pass both to TabPFNRegressor.fit_from_preprocessed; that method now sets the frame instead of relying on an earlier fit() or fine-tuning setup call.

  • Fine-tuning and member preprocessing use the same StandardizeTarget statistics and epsilon, including near-constant targets.

  • Missing member pipelines raise in regression loss and grouped border translation. The separate no-transform path for differentiable inputs remains valid.

  • Target pipeline annotations and the stale normalization comment are corrected.

  • Rebased onto main ffd53715. Preserve main's CPU float64 border reconstruction and new serialization coverage. Update main's custom-loop tests to pass the required target frame while retaining their state-isolation assertions.

Validation

Rebased validation: the broad non-slow suite reported 244 passed, 55 skipped, 66 deselected, and two failures. The border-frame assertion used float32 arithmetic despite main now reconstructing borders in float64; its corrected CPU and MPS variants both pass without changing tolerances. The config-equivalence test differed by 1.6e-5 on the Mac accelerator and passed in isolation without changes. All four custom-loop state-isolation tests pass.

The border-remapping suite adds 28 passed and 3 skipped. Pre-commit checks, including Mypy and Ruff, pass.

Command: PYTHONPATH=src python -m pytest tests/test_preprocessing/test_target_transform.py tests/test_regressor_interface.py tests/test_batched_prediction_shape_safety.py tests/test_batched_prediction_data_util.py tests/test_finetuning_regressor.py tests/test_downsample_correction.py tests/test_save_load_fitted_model.py tests/test_fit_from_preprocessed.py -q -m 'not slow'

Earlier full-context validation on the original revision found all 24 model-input target arrays bit-identical to its main baseline. Those measurements predate these review fixes; no new benchmark claim is made here.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread src/tabpfn/finetuning/data_util.py
Comment thread src/tabpfn/preprocessing/target_transform.py Outdated
@bejaeger
bejaeger force-pushed the benjamin/res-2639-target-encoder-refactor branch from d5e41e0 to 09ebdd7 Compare September 23, 2026 12:41

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread changelog/1198.changed.md Outdated
@bejaeger
bejaeger force-pushed the benjamin/res-2639-target-encoder-refactor branch from 09ebdd7 to 05ed97d Compare September 23, 2026 12:57

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread src/tabpfn/finetuning/finetuned_regressor.py
@bejaeger
bejaeger force-pushed the benjamin/res-2639-target-encoder-refactor branch 3 times, most recently from b5da313 to e541339 Compare September 24, 2026 10:23
@bejaeger
bejaeger added this pull request to stack #1332 September 30, 2026 13:03
LeoGrin
LeoGrin previously approved these changes Oct 4, 2026

@LeoGrin LeoGrin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

One comment from claude, which makes sense IMO. Not sure we want to guarantee this always work, but maybe we could find a way to fail loudly for safety?

  1. Fit states saved before this PR load and predict wrong values, with no error.
  • A .tabpfn_fit archive stores the fitted member configs and has no version stamp. An old archive holds bare presets whose inverse already lands in z-norm space.
  • transform_borders_one now standardizes that result a second time.
  • transform_borders_one now standardizes that result a second time.
  • Repro: I saved a fit with the parent commit (4 estimators, 2 with a preset) and loaded it with the PR. Predictions went from [1057, 1029, 1025, 1005] to [524, 510, 508, 498]. Loading with the parent reproduces the original exactly.
  • The same applies to pickled fitted estimators.
  • Suggested fix: stamp the archive and raise on an old one, or detect a transform without the standardize_target step.

A few other nits from Claude which look correct:

  • _targets_in_estimator_space returns raw targets when target_transform is None. That branch is now unreachable from the dataset path, and wrong if reached. Raise there instead.
  • The None branch in _translate_batched_logits is dead for the same reason.
  • data_util floors the frame std at 1e-8, while the member uses std + 1e-20. On a near-constant fine-tuning split the two disagree and the borders collapse. One shared constant would remove this.
  • The comment at regressor.py:1340 still says "before the z-normalisation below". There is none after this PR.
  • target_preprocessors is still annotated list[TransformerMixin | Pipeline | None], but it is now always a Pipeline.

Comment thread src/tabpfn/regressor.py
Comment thread src/tabpfn/finetuning/data_util.py Outdated
@bejaeger
bejaeger force-pushed the benjamin/res-2639-target-encoder-refactor branch from ba2656f to 28fe360 Compare October 13, 2026 10:31

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 28fe360. Configure here.

Comment thread src/tabpfn/regressor.py
@bejaeger
bejaeger force-pushed the benjamin/res-2639-target-encoder-refactor branch from 28fe360 to f48014d Compare October 23, 2026 12:45
@bejaeger

Copy link
Copy Markdown
Collaborator Author

I addressed all nits.
both unreachable None branches now raise, fine-tuning and member preprocessing share the same standardization logic and epsilon, the stale comment is corrected, and target_preprocessors is typed as list[Pipeline].

For saved fit states, I chose to document this as a breaking change requiring refitting rather than add version stamps or runtime compatibility checks. This means old archives and pickled estimators remain unsupported and can silently produce incorrect predictions if reused; the PR does not make them fail loudly but I think this is fine?

@bejaeger
bejaeger requested a review from LeoGrin October 23, 2026 12:52

@LeoGrin LeoGrin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@bejaeger
bejaeger added this pull request to the merge queue Oct 28, 2026
Merged via the queue into main with commit d05cd1b Oct 28, 2026
17 checks passed
@bejaeger
bejaeger deleted the benjamin/res-2639-target-encoder-refactor branch October 28, 2026 13:16
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.

2 participants