Training Tables
A predictive query defines the task. A training table holds the labeled rows Kumo learns from, and a prediction table holds the entities it scores.
Kumo can generate both tables from your query, or you can supply your own rows.
This page continues with the query, temporal_query, and snapshot from Predictive Queries.
Static and Temporal Rows
The query type decides what a row is. A static query labels each entity once, using the value already stored in its target column. A temporal query labels each entity at one or more anchor times, using what happened in the window after each anchor.
In a static training table, the same customer appears at most once. In a temporal training table, a customer can appear at several anchors, each with its own label. If every entity in a static query already has a target, Kumo has nothing to score and prediction table generation raises an error. Supply prediction rows to score those entities.
Generate a Training Table
Generate labeled rows from your query and snapshot:
This synchronous call creates the training, validation, and test artifacts used by Training.
Classification training tables need at least two observed target values and must stay within the configured class limit. A one-class table raises Too few classes to predict; adjust the query or supplied labels.
The returned table retains its rows, labels, split assignments, and generation settings.
Training consumes those artifacts without regenerating the rows.
Keep their files in scratch until the operations using them have finished.
To customize generation, import and construct a TrainingTableGenerationPlan, then pass it to the generation call. For a temporal task, offsets count backward from the latest usable timestamp in the snapshot:
These are table-generation settings, separate from the model and optimization settings in ModelPlan.
For a temporal query, choose a range that has enough history for features and enough future data to calculate training labels.
When both bounds are supplied, train_end_offset must be smaller than train_start_offset; equal or reversed bounds are rejected.
Integer offsets and spacing use the query’s time unit, including calendar offsets for a query expressed in months.
Choose Split Assignments
Pass the split constructor as a string. For example, assign static node rows reproducibly:
Use a split that matches the task and available timestamps:
Ratios have two or three nonnegative entries. Temporal ratio splits must cover the full dataset; random splits can leave rows unused.
An explicit TimeRangeSplit still uses the temporal query’s label-window width and the generation plan’s anchor spacing. It does not make unavailable labels appear.
For static array-link tasks, a supplied RandomSplit or TemporalSplit is normalized to RandomLinkSplit; its ratio survives, but a random seed does not.
If you omit split, Kumo chooses by task:
- Static node rows without time use random 80/10/10; timestamped static nodes use chronological 80/10/10.
- Static array links use random per-link 80/10/10. The public foreign-key
LIST_DISTINCTranking path uses this per-link assignment. - Temporal non-link targets starting at offset zero use approximate date-offset 80/10/10. Other temporal targets use date-offset boundaries based on the query’s target end offset.
- Forecasting reserves chronological windows based on horizon and window width. For horizon
Hand window widthW, the default split offsets are-2*H*W + Wand-H*W + Win the query’s time unit.
Review the resulting stage counts before fitting. A split configuration does not guarantee every class or entity appears in every stage.
Generate Forecast Inputs
For the existing temporal order-count query, request three future windows, two historical target values, and year-over-year inputs:
forecast_length overrides a horizon written in PQL. Each row contains three future_labels values and two autoregression_labels values, ordered from oldest to most recent.
Forecasting defaults to one lag and requires a positive integer; lag_timesteps=0 is rejected.
Year-over-year inputs use a 364-day offset with ten steps of padding on each side, giving horizon + 20 values. They are not a calendar-year join.
Use source history covering those lookbacks and inspect missing values before fitting.
Fit forecast_table through the normal Training workflow.
For prediction, reuse trainer.training_table_generation_plan, including after loading a bundle, as shown in Making Predictions.
See Forecasting Architecture.
Inspect and Retain Rows
Read a bounded batch from the generated training rows before fitting:
Training rows include entity keys, labels, and applicable timestamps or forecast sequences. Continue to Making Predictions. See Inspect the Training Table.
To retain a row artifact outside disposable scratch, copy its file or partitioned directory to a new destination:
A row copy is useful for inspection or a separately prepared supplied-table workflow. It is not a portable TrainingTable: native manifests, split artifacts, and graph indexes are separate.
Keep original scratch artifacts for ongoing operations. Retaining row files does not save the model or its graph snapshot.
Advanced Configurations
Kumo usually generates training and prediction rows from your query. Supply your own rows instead when you already have labels, sample weights, or split assignments, or when you want to score a specific set of entities. If Kumo generates your rows, skip this section and continue to Training.
Use Custom Training Tables
A custom training table is a file of labeled rows that Kumo trains on as is. It needs these columns:
The following steps use a small local example: 50 customers, of which IDs 40 through 49 have no churn label.
1. Create the example graph and query. Choose an unused source directory on local storage that is separate from, and not nested inside, your configured Kumo scratch directory:
2. Load your labeled rows as a training table. These 30 rows carry their own labels, weights, and splits: 20 train, 6 validation, and 4 test.
Kumo keeps your labels as they are instead of recalculating them from the query.
3. Train and score. Pass the same spec when suggesting the model plan so Kumo accounts for the weights:
Prediction returns ten rows, for IDs 40 through 49. True_PROB is the predicted probability of the positive label, and TARGET_PRED applies the threshold. These synthetic results demonstrate the workflow, not model quality.
Rules for labels, weights, and splits
Name ENTITY1 and TARGET1 exactly. Entity keys must match the graph primary-key type; use real keys from that snapshot, not row positions.
Scalar tasks require scalar labels and scalar weights. Weights must be finite, non-null, and not all zero; negative weights are rejected for this task.
WEIGHT changes each row’s contribution under weighted_loss; sample uses weights for training-row sampling, while None ignores them. See Weighting and Class Imbalance.
SPLIT uses only 0 (train), 1 (validation), and 2 (test). split_col overrides the generation plan’s split with this mapping.
Omit weight_col or split_col if the source lacks that column; without manual assignments, the selected or inferred split applies.
This constructor supports those two spec fields, not custom feature or candidate-column specifications.
Trainer.fit receives the materialized table and its explicit snapshot.
When to include a TIMESTAMP column
For temporal node, link, and forecast tasks, include a real per-row TIMESTAMP using timezone-naive UTC Arrow timestamps. Static node tasks also need TIMESTAMP when their entity table has a time_column; the untimestamped example above does not.
Do not apply the static-node rule to links. A static foreign-key LIST_DISTINCT ranking query rejects a graph containing relevant time columns before it checks supplied rows. Use a temporal aggregation, or a separate graph definition without those time columns, rather than trying to fix that error by adding a supplied timestamp.
Supply list targets for ranking tasks
Link labels use a variable-length list of target entity keys in each TARGET1 row. Per-element weight lists must have the same lengths as their corresponding target lists; scalar weights do not stand in for per-element lists.
Negative weights have a separate temporal-link contract and must not be copied from that task into static or scalar examples.
For example, suppose an untimestamped graph link_graph has integer-key users and products, with orders.UID and orders.PID relationships to them. After creating link_snapshot, prepare list rows whose user and product IDs exist in that snapshot:
Use link_spec in link_query.suggest_model_plan(link_snapshot, train_table_spec=link_spec) and pass link_training to Trainer.fit with that snapshot. Choose optimization.weight_mode=["weighted_loss"] for these supplied link weights; weighted sampling is not supported for this task.
For scoring, supply only the user keys and pass num_classes_to_return=3 to Trainer.predict. Expect one result row per returned user/product pair.
Use Supplied Prediction Rows
To score specific entities instead of the generated population, write their keys to a file and load it as a prediction table. This example scores three customers from the example above:
Expect IDs 40, 42, and 49, each once. The file needs typed ENTITY1 keys and no TARGET columns. Pass the fitted trainer’s training_table_generation_plan as plan.
For a temporal query, also add a TIMESTAMP column with each row’s anchor time, such as pd.to_datetime(["2024-03-01", "2024-03-08", "2024-03-15"]), using dates covered by your graph history. An entity can appear more than once at distinct anchors. See Retain Supplied Row Anchors.
Validation notes
Both supplied-table constructors stage and validate their rows immediately. Use them to define a population rather than modifying generated files. Column validation does not establish that every identifier exists in the snapshot. Check the resulting population and avoid null, missing, or mismatched keys.
Supply Forecast Sequences
Forecasting tables need extra sequence columns for future labels and past history. Most readers should let Kumo generate them. Expand the section below only if you calculate these values yourself.
Forecast sequence columns and example
Use a generated table with the intended forecast plan as a schema template before replacing values with independently calculated labels and history. For the count forecast above, the sequence columns are variable-length Arrow lists of integers:
This round trip checks the representation without changing values. Keep it small: to_table() materializes the row data in memory.
Fit the supplied rows, then use the fitted plan to prepare a scoring template:
Expect three horizon rows for each selected entity and anchor in this example. Replace keys, anchors, and historical arrays together when adapting the scoring rows. Do not add TARGET1 or future_labels to scoring rows.
The constructors preserve supplied arrays; they do not derive them from keys and timestamps. Keep the fitted generation plan after saving and loading the model too.
For horizon 3 and lag 2, lengths are 3, 2, and 23. Both generated and supplied forecasting reject zero lag. Do not use a null list, a differently sized sequence, or an invented fill value to represent unavailable history; retain the generated task’s aggregation semantics when calculating your own inputs. This count example does not define missing-value handling for every aggregation or certify arbitrary Arrow list representations.
Continue to Training or Making Predictions.