Predict on a flat table with RelFM Tabular
RelFMTabular is a standalone alternative to RelFM for data that’s already one flat table per split — features and the label are all on the same row. It skips the relational setup entirely: no Graph, no PropertyTransformer, no shared entity Concept across splits, and no Relationship wrapping a split. Each of context, validation, and the domain you predict for is simply its own Concept.
Reach for RelFMTabular when your data doesn’t need multi-table joins to produce features — a single denormalized table already has everything the model needs per row.
Predictor vs. forecaster
Section titled “Predictor vs. forecaster”RelFMTabular is a thin factory: pass task_type and it dispatches to one of two classes with disjoint parameters and validation. Construct the subclass directly if you want static type-checking for exactly which parameters apply.
task_type | Class | Use for |
|---|---|---|
"binary_classification", "multiclass_classification", "regression" | RelFMTabularPredictor | One prediction per row of a domain table |
"forecasting" | RelFMTabularForecaster | Future values over a time-indexed panel/history table |
Both share the same core parameters—database, schema, context, label_column, validation, eval_metric—as well as the job-control and tuning knobs described below. Neither has a training step: context is used directly as in-context examples, just as with RelFM.
| Parameter | Description | Default |
|---|---|---|
test_batch_size | Batch size used during inference. | 256 |
stream_logs | Stream job logs to stdout. | True |
dataset_alias | A user-chosen alias for the dataset, used to name the tables exported to database/schema. | context’s Concept name |
device | "cpu" or "cuda". | "cpu" |
n_estimators | Ensemble size. Higher improves quality at the cost of slower inference. | 8 |
random_state | Seed for ensemble generation and context sampling. | 42 |
sample_size | Max rows of context sampled as in-context examples. None uses all rows. | None |
sampling_strategy | How to draw the context sample: "stratified", "most_recent", "mixed", "random", or "balanced". | "stratified" |
quantile_levels | Quantile levels output when regression_output="distribution" or for forecasting tasks. | None (uses [0.1, 0.5, 0.9]) |
norm_methods | Feature normalization applied before inference: "none", "power" (Yeo-Johnson), "quantile", "quantile_rtdl", or "robust". Pass a list to use different methods across ensemble members. None uses ["none", "power"]. | None |
clamp_min | Regression only. Lower bound on predictions (as a percentile). | 0 |
clamp_max | Regression only. Upper bound on predictions (as a percentile). | 100 |
regression_output | Regression only. "point" returns a single estimate; "distribution" also returns the quantiles in quantile_levels. | "point" |
Unlike RelFM, there’s no graph, property_transformer, source_concept, has_time_column, use_current_time, or parallel_reasoners_init — RelFMTabular has no relational graph to traverse and no separate Logic-reasoner setup.
Classification or regression
Section titled “Classification or regression”context must be identified by a single natural-key property (a composite identity across more than one property isn’t supported) and include label_column among its own properties:
from relationalai.semantics.reasoners.predictive import RelFMTabular
relfm_tabular = RelFMTabular( database="MYDB", schema="MYSCHEMA", context=Customer, label_column="lifetime_value", task_type="regression", eval_metric="rmse",)
Customer.predictions = relfm_tabular.predictions(domain=TestCustomer)domain (here TestCustomer) must also be identified by a single natural-key property and include the same feature columns as context, excluding label_column. The returned relationship exposes .predicted_value for regression, or .probs/.predicted_labels for classification — the same shape as RelFM’s output.
Forecasting
Section titled “Forecasting”Forecasting uses context differently: it’s a history/panel table naturally identified by (item_id_column, time_column) together — a composite identity, unlike the predictor’s single natural key.
| Parameter | Description | Required |
|---|---|---|
time_column | The datetime property name on context/validation/the forecast() domain. | Yes |
max_context_length | How many time steps of history to look back over. | Yes |
item_id_column | Property name that identifies the series. Omit for a single-series forecast, or set it to partition context into multiple series (e.g. one series per store) for panel forecasting. | No |
relfm_forecast = RelFMTabular( database="MYDB", schema="MYSCHEMA", context=SalesHistory, label_column="sales", time_column="date", item_id_column="storeid", max_context_length=60, task_type="forecasting",)
FutureWindow.forecast = relfm_forecast.forecast(domain=FutureWindow)domain (here FutureWindow) carries the future (item_id, time) rows to forecast for — no label_column, but time_column (and item_id_column, for panel forecasting) present. The forecast lands exactly on domain’s own (item_id, time) rows, so each series can ask for its own dates at its own spacing. A couple of things are rejected before the job runs:
- An item in
domainthat has no matching history incontext. - A duplicate
(item_id, time)row indomain.
The output relationship exposes .predicted_value (point estimate), plus one quantile_<level> property per level when quantile_levels is set — e.g. quantile_10/quantile_50/quantile_90 for [0.1, 0.5, 0.9].
For eval_metric on forecasting tasks, the valid values are "mae", "rmse", and "mape".
Scoring
Section titled “Scoring”Both classes support .score(domain=...), evaluating against a labeled domain and returning {"metric_name": str, "metrics": dict[str, float]}. Omit domain to score against the validation Concept passed to the constructor:
relfm_tabular.score(domain=ValidationCustomer)Comparing to RelFM and GNN
Section titled “Comparing to RelFM and GNN”If your data instead spans multiple related tables — and you’d rather let an estimator pull in features across joins than flatten everything yourself — see Predict with RelFM or Configure and train a GNN.