Skip to content
1 change: 1 addition & 0 deletions changelog/923.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `TabPFNRegressor.fit_with_differentiable_input(X, y)` so gradients can flow from a downstream loss back through the regressor into upstream torch modules feeding `X` (and `y`, when it carries grads). Mirrors the existing classifier-side path — previously `TabPFNRegressor.fit` raised `ValueError("Differentiable input is not supported for regressors yet.")` and there was no differentiable counterpart.
18 changes: 18 additions & 0 deletions src/tabpfn/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,24 @@ def create_inference_engine( # noqa: PLR0913
raise ValueError(f"Invalid fit_mode: {fit_mode}")


def reject_categoricals_for_differentiable_input(
categorical_features_indices: Sequence[int] | None,
) -> None:
"""Reject categorical features in the differentiable-input fit path.

The differentiable path uses an identity preprocessor (no
ordinal-encoding step), so categorical columns have no valid handling
and would corrupt the prompt-tuning signal.
"""
if (
categorical_features_indices is not None
and len(categorical_features_indices) > 0
):
raise ValueError(
"Categorical features are not supported for differentiable input."
)


def initialize_model_variables_helper(
calling_instance: TabPFNRegressor | TabPFNClassifier,
model_type: Literal["regressor", "classifier"],
Expand Down
9 changes: 2 additions & 7 deletions src/tabpfn/classifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
get_embeddings,
initialize_model_variables_helper,
initialize_telemetry,
reject_categoricals_for_differentiable_input,
)
from tabpfn.constants import (
PROBABILITY_EPSILON_ROUND_ZERO,
Expand Down Expand Up @@ -635,13 +636,7 @@ def _initialize_for_differentiable_input(
)

# Minimal preprocessing for prompt tuning
if (
self.categorical_features_indices is not None
and len(self.categorical_features_indices) > 0
):
raise ValueError(
"Categorical features are not supported for differentiable input."
)
reject_categoricals_for_differentiable_input(self.categorical_features_indices)
n_features = X.shape[1]
features = [Feature(name=None, modality=FeatureModality.NUMERICAL)] * n_features
self.inferred_feature_schema_ = FeatureSchema(features=features)
Expand Down
Loading