FT-Transformer: the Transformer, adapted to tabular data.
Implements the architecture of Gorishniy et al. (NeurIPS 2021), Revisiting Deep Learning Models for Tabular Data: a feature tokenizer turns each column into its own embedding, a [CLS] token is prepended, and a stack of pre-norm Transformer blocks attends over the resulting feature sequence.
PyTorch is an optional dependency -- pip install 'tuiml[torch]'. Nothing in this module imports torch until fit is called.
Classes
class algorithms.tabular_deep.ft_transformer.FTTransformerClassifier(_FTTransformerCore, _DeepTabularClassifierMixin, Classifier)
FT-Transformer: per-feature tokens attended by a Transformer.
[CLS] token rides along and collects the evidence; the prediction head reads only that token.Overview
- Tokenize: numerical feature x_j becomes W_j x_j + b_j,
d_token-dimensional vector with its own weights; categorical features index an embedding table.
-
Prepend a learned
[CLS]token, givingm + 1tokens. -
Apply
n_blockspre-norm Transformer blocks: multi-head self-attention
-
Predict from the final
[CLS]token.
Theory
The tokenizer is an affine map applied per feature, not per row, which is what distinguishes it from a plain input layer:
Each block then applies pre-norm attention and a feed-forward network:
with attention over the feature axis,
Because attention scores are computed between features, the model learns multiplicative feature interactions directly, rather than approximating them with axis-aligned splits as a tree ensemble does.
Parameters
d_token
n_heads. The default is deliberately small so that a fit on a toy problem takes milliseconds; real tabular problems want 64-192.
n_blocks
n_heads
dropout
learning_rate
weight_decay
batch_size
n_epochs
early_stopping=True.
early_stopping
validation_fraction of the rows and restore the best-scoring weights when validation loss stops improving.
validation_fraction
early_stopping is enabled.
patience
categorical_features
None treats every column as numerical.
device
"cpu" because accelerators make results non-reproducible; "auto" picks CUDA, then MPS, then CPU and is the right choice when speed matters more than bit-exactness.
random_state
device="cpu" the same seed reproduces predictions exactly.
Attributes
classes_
fit.
network_
feature_mean_, feature_scale_
loss_curve_
n_iter_
n_epochs if early stopping triggered.
n_features_in_
fit.
Notes
Requires PyTorch. Install with pip install 'tuiml[torch]'. The class can be constructed and inspected without torch; fit raises ImportError naming the install command.
Complexity. One block costs O(n m^2 d + n m d^2) per epoch, quadratic in the number of features rather than of samples, so wide tables cost more than tall ones. Memory is O(b m^2) for the attention matrix of a batch.
When to use. FT-Transformer is the strongest of the attention-based tabular baselines and the one to reach for when features interact in ways an additive model misses, and when there is enough data (roughly tens of thousands of rows) to train a Transformer. On small tables a gradient boosted ensemble is usually both faster and more accurate.
References
See Also
Constructing and inspecting a model needs no torch:
>>> from tuiml.algorithms.tabular_deep import FTTransformerClassifier
>>> model = FTTransformerClassifier(d_token=8, n_blocks=1, random_state=0)
>>> model.d_token
8
>>> "n_epochs" in FTTransformerClassifier.get_parameter_schema()
True
Fitting requires pip install 'tuiml[torch]'; the example below is a
no-op on an install without it:
>>> import numpy as np
>>> from tuiml.utils.torch_backend import has_torch
>>> rng = np.random.default_rng(0)
>>> X = rng.normal(size=(300, 4))
>>> y = ((X[:, 0] > 0) ^ (X[:, 1] > 0)).astype(int)
>>> if has_torch():
... model = FTTransformerClassifier(n_epochs=150, random_state=0).fit(X, y)
... print(float(model.score(X, y)) > 0.85)
... else:
... print(True)
True
class algorithms.tabular_deep.ft_transformer.FTTransformerRegressor(_FTTransformerCore, _DeepTabularRegressorMixin, Regressor)
FT-Transformer for regression: per-feature tokens, [CLS] readout.
FTTransformerClassifier. The architecture is identical -- feature tokenizer, [CLS] token, pre-norm Transformer blocks -- and only the output layer and objective change: a single unit trained with mean squared error against a standardised target, rescaled back on prediction.Overview
- Standardise the target, so the loss scale is independent of the units.
-
Tokenize each feature into a
d_token-dimensional embedding. -
Attend across features through
n_blockspre-norm Transformer blocks. -
Read the
[CLS]token through a linear head and undo the target
Theory
Given tokens T \in \mathbb{R}^{(m+1) \times d} the network minimises
where \hat{y} is the head applied to the final [CLS] token. Standardising y matters more than it does for trees: with a raw target of large magnitude the initial gradients dominate the attention weights and the model spends its early epochs learning the mean.
Parameters
d_token
n_heads. Real problems want 64-192.
n_blocks
n_heads
dropout
learning_rate
weight_decay
batch_size
n_epochs
early_stopping
validation_fraction
early_stopping is enabled.
patience
categorical_features
device
"auto" trades reproducibility for speed.
random_state
Attributes
network_
target_mean_, target_scale_
feature_mean_, feature_scale_
loss_curve_
n_iter_
n_features_in_
fit.
Notes
Requires PyTorch. Install with pip install 'tuiml[torch]'. Building the object works without it; fit raises ImportError.
Complexity. Identical to the classifier: O(n m^2 d + n m d^2) per epoch, quadratic in the feature count.
When to use. Prefer it over ExplainableBoostingRegressor when the target depends on feature interactions rather than on an additive sum of shape functions, and there is enough data to train a Transformer.
References
See Also
>>> from tuiml.algorithms.tabular_deep import FTTransformerRegressor
>>> model = FTTransformerRegressor(d_token=8, n_epochs=10)
>>> model.n_epochs
10
>>> sorted(FTTransformerRegressor.get_capabilities())[:2]
['categorical', 'non_linear']
Fitting requires pip install 'tuiml[torch]'; the example below is a
no-op on an install without it:
>>> import numpy as np
>>> from tuiml.utils.torch_backend import has_torch
>>> rng = np.random.default_rng(0)
>>> X = rng.normal(size=(300, 4))
>>> y = np.sin(X[:, 0]) * X[:, 1]
>>> if has_torch():
... model = FTTransformerRegressor(n_epochs=300, random_state=0).fit(X, y)
... print(float(model.score(X, y)) > 0.8)
... else:
... print(True)
True