Source code for autogluon.tabular.models.tabpfnv2.tabpfn3_model

from __future__ import annotations

from typing import ClassVar

import pandas as pd

from .tabpfnv2_5_model import TabPFNModel


[docs] class TabPFN3Model(TabPFNModel): """TabPFN-3 version: https://priorlabs.ai/. Technical Report: https://arxiv.org/abs/2605.13986 Requires ``tabpfn>=8.0`` for the v3 checkpoints. .. versionadded:: 1.6.0 """ ag_key = "TABPFN-3" ag_name = "TabPFN-3" license_noncommercial: ClassVar[bool] = True fixed_random_state: int = 0 """We found that the validation score is misleading for TabPFN, when one uses a different random state for the refit model than for models fit during CV. This is because TabPFN's random state determines the preprocessing of TabPFN. """ default_classification_model: str | None = "tabpfn-v3-classifier-v3_default.ckpt" default_regression_model: str | None = "tabpfn-v3-regressor-v3_default.ckpt" max_batch_size_min: int = 100_000 """TabPFN-3 reuses the training context (KV cache) across prediction chunks, so chunks smaller than the training set multiply predict time while saving little memory — unlike TabPFN-2.5/2.6 (the base default), which re-process the joint train + batch sequence per chunk and benefit from a low floor.""" _default_auxiliary_params_extra = { "max_rows": 500_000, # No feature cap: TabPFN-2.6 and -3 handle very wide data well, and on BeyondArena's # widest tasks (up to 22k columns) they are the two strongest methods of 28. Set to None # rather than removed, because the base TabPFNModel (2.5) caps at 2000 and subclass # `_default_auxiliary_params_extra` entries are merged base-most first, so an absent key # would inherit that tighter cap instead of lifting it. Memory remains bounded by # `_estimate_memory_usage_static`, which is what skips a fit that genuinely will not fit. "max_features": None, "max_classes": 160, # max_batch_size (prediction chunking) is the model's only bound on # test-side VRAM (peak grows linearly in unchunked prediction rows); # "auto" resolves at fit time to min(1M, max(100k, n_train)). "max_batch_size": "auto", "model_telemetry": False, } @staticmethod def extra_checkpoints_for_tuning(problem_type: str) -> list[str]: """The list of checkpoints to use for hyperparameter tuning.""" raise NotImplementedError("We did not benchmark more checkpoints or tuning.") @classmethod def _estimate_memory_usage_static( cls, *, X: pd.DataFrame, hyperparameters: dict | None = None, **kwargs, ) -> int: """Peak CPU RSS: ~2.8 GB process baseline plus ~10 float64 copies of the train + prediction-batch data made by TabPFN-3's preprocessing. Features count up to the model's internal 500-feature subsampling cap. Calibrated on synthetic fit+predict measurements (1k-800k rows, 10-2000 features) and all 136 real TabArena and BeyondArena tasks (100 to 1M rows): 1.03-2.5x of measured, no underestimates. """ n_train, n_features = X.shape n_test = cls._n_test_for_memory_estimate(n_train=n_train, hyperparameters=hyperparameters) baseline_mem_est = 2.8e9 preprocessing_mem_est = 10 * 8 * (n_train + n_test) * min(n_features, 500) return int(baseline_mem_est + preprocessing_mem_est) @classmethod def _estimate_gpu_memory_usage_static( cls, *, X: pd.DataFrame, hyperparameters: dict | None = None, problem_type: str | None = None, **kwargs, ) -> int: """Peak VRAM (reserved + CUDA context) across fit and prediction. TabPFN-3's peak is asymmetric in train vs prediction rows: train rows persist as attention context (~40 KB/row reserved) while prediction rows are transient (~26 KB/row) and bounded by the fit-time prediction batch (see :meth:`_n_test_for_memory_estimate`). Features cost ~18 MB each (x1.5 for regression), saturating at ~230 where internal subsampling caps the cost. Flat in ``n_estimators``. Regression's distributional (full-support) output costs more per prediction row (~110 KB, saturating to ~40 KB past 100k rows) plus buffers that grow with the training size to a ~2.9 GB ceiling. Calibrated on synthetic measurements up to 500k train rows / 800k prediction rows / 2000 features plus all 136 real TabArena and BeyondArena tasks (100 to 1M rows): 1.0-4.3x of measured, no underestimates. """ n_train, n_features = X.shape n_test = cls._n_test_for_memory_estimate(n_train=n_train, hyperparameters=hyperparameters) is_regression = problem_type == "regression" if is_regression: prediction_mem_est = 110e3 * min(n_test, 100_000) + 40e3 * max(n_test - 100_000, 0) output_buffer_mem_est = min(2.9e9, 1e6 * n_train) else: prediction_mem_est = 26e3 * n_test output_buffer_mem_est = 0 return int( 1.1e9 # CUDA context + model weights floor + 40e3 * n_train + prediction_mem_est + output_buffer_mem_est + 18e6 * min(n_features, 230) * (1.5 if is_regression else 1.0) )