φ: the theory of feature creation
Every page on this site shows how to make featurizer produce features. This one explains what a feature is — the small formal idea that makes the whole library cohere, and the reason leakage is impossible by construction rather than by discipline.
The intuition
Section titled “The intuition”A feature is a question you ask about an entity’s past: how many orders did this customer place in the last 7 days? What was their average basket in the last month? Two things hide inside every such question:
- An entity and a moment. The question is not “how many orders” — it is “how many orders as of June 1st”. The same customer gives a different answer on June 2nd.
- A restriction. Only events that had already happened by that moment may count. Anything later is the future, and the future must be invisible — otherwise a model trained on these features cheats.
So a feature is a function of two arguments — an entity and an as-of date — evaluated over the events visible at that date. featurizer calls this function φ. Everything else — YAML, planners, CTEs — is machinery for composing φ from small pieces and compiling it to SQL.
Play with the idea before reading the formalism — drag the as-of date and watch φ recompute; step through the depth-stacking panel to watch a nested feature name assemble itself:
Open the explorable full-page.
The formalism
Section titled “The formalism”Setup. Let temporal_ix — and as_of_dates
table).
The restriction operator. For an entity
— the as_of_boundary config key chooses the comparison. Every construct
below consumes
A feature is any function
The two primitive families. featurizer composes φ from exactly two kinds of pieces:
- Transformations
act within an entity, row by row (or over the entity’s own ordered history — lags, rolling stats, cumulative sums): per event, timestamps untouched. In SQL: an expression in the entity’s _transformCTE. - Aggregations
act across a relationship, collapsing a multiset of child values to a scalar. The windowed variant restricts further to an interval ending at :
In SQL: an aggregate with a FILTER (WHERE daterange(t − w, t) @> τ)
clause in the relationship’s aggregation CTE.
Deep Feature Synthesis is closure under composition. With entities
max_depth
up to depth intervals. That mechanical enumeration
of compositions is the core idea of the DFS paper: J. M. Kanter &
K. Veeramachaneni,
Deep Feature Synthesis: Towards Automating Data Science Endeavors
(IEEE DSAA 2015; see also the
project page).
featurizer’s contribution is making the composition temporal (every layer
respects H(e, t)) and compiling it to a single PostgreSQL query instead of
in-memory dataframes.
Point-in-time correctness, by construction. The only data-access
primitive in the algebra is
There is no discipline to maintain and no review checklist — a leaky feature
is not expressible in the algebra. In the rendered SQL you can point at the
guarantee: the where τ ≤ aod.as_of_date guard plus the interval FILTER
clauses (see the query skeleton).
Names are serialized
"MEAN(orders.ABS(orders.amount)|interval=P30D)"which is why the feature manifest can reconstruct lineage (depth, parents, source column, interval) for every column mechanically.
Three φ variants beyond the registry
Section titled “Three φ variants beyond the registry”Three feature families are planner passes with their own config blocks rather than registry primitives — but they are the same shape: functions of restricted histories.
The φ-bridge (ADR-0001).
Some φ need heavy Python — an embedding, a graph statistic — that SQL should
not recompute. The bridge computes a value per source row offline,
materializes it back as an ordinary column with the row’s own timestamp,
and the value re-enters the algebra as a plain variable subject to the same
τ ≤ t bound. The causal boundary survives because the precomputed value is
itself an event: it becomes visible when its row does, never earlier. (This
is why per-row φ is the supported shape — a value that genuinely depends on
(e, t) jointly cannot be materialized once per row.)
Peer groups (peer_groups: on an entity). These compare an entity
against the distribution of the same
Still a function of restricted histories only — just of several entities’
histories at the same PEER_GROUP_SIZE,
PEER_EVENT_RATE, and per measure PEER_MEAN / PEER_ZSCORE /
PEER_PCTILE / EGO_MINUS_PEER_MEAN.
Spatial relationships (spatial_relationships:). Here the “history” is a
second table’s geometry: φ asks how entity e’s location relates to another
entity set’s locations — COLOCATION_COUNT within a radius,
DISTANCE_TO_NEAREST, KDE_INTENSITY under a bandwidth. When the second
table is temporal, the same restriction applies to it; the spatial predicate
(within_m, bandwidth_m) simply replaces the interval window as the
“neighborhood” being aggregated.
Where to go next
Section titled “Where to go next”- The walkthrough — see φ compiled to SQL on real data.
- Primitives reference — the full
vocabulary of
ganda. - Performance internals — how the compiled query stays fast when the composition space gets wide.