Skip to content
elevatedevco

Machine Learning

Feature engineering at scale

Feature engineering transforms raw data into informative inputs that maximize model performance, generalization, and interpretability. This cheat sheet cov

Professional34 questions34 quiz questionsCheat sheet

Questions & Answers

Tap a question to reveal its answer. Written for self-study and interview preparation.

What is the primary purpose of a feature store in a large-scale ML system?

A feature store centralizes feature definitions, computation, and serving so the same transformation logic is reused for both training and inference. Its key value is eliminating training-serving skew by guaranteeing offline (batch) and online (low-latency) feature values are produced from identical logic. It also provides discoverability, versioning, point-in-time correctness, and reuse across teams.

What is a point-in-time (as-of) join and why is it essential when building training datasets at scale?

A point-in-time join attaches to each label/event only the feature values that were known at or before that event's timestamp, preventing future information from contaminating the row. Without it you leak data because aggregations computed with later events inflate offline performance and collapse in production. Feature stores implement it via time-windowed joins keyed on entity plus event timestamp.

What is training-serving skew and what is a common cause of it?

Training-serving skew is the discrepancy between feature values used at training time and those computed at serving time, leading to silent model degradation. A common cause is having two separate code paths (e.g., a batch SQL/Spark pipeline for training and a hand-written Python service for online inference) that diverge over time. Sharing transformation code via a feature store or a single transformation library mitigates it.

When serving features online with strict latency budgets, why are online and offline stores typically split into different backends?

Offline stores optimize for high-throughput batch reads over historical data (columnar formats like Parquet on a data lake or warehouse), while online stores optimize for single-key, millisecond point lookups (key-value stores like Redis, DynamoDB, or Cassandra). The access patterns are fundamentally different, so a dual-store architecture serves each workload efficiently. A materialization job syncs precomputed features from offline to online.

What is the difference between batch, streaming, and on-demand (request-time) features?

Batch features are precomputed on a schedule from historical data (e.g., 30-day average spend). Streaming features are updated in near real-time from event streams (e.g., count of clicks in last 5 minutes). On-demand features are computed at request time from the inference payload or freshly fetched context (e.g., distance between user's current location and a merchant), because they depend on data unavailable until the request arrives.

Why is feature backfilling computationally challenging, and what technique makes it tractable?

Backfilling recomputes a new feature's historical values for every past entity-timestamp so it can be used in training, which is expensive over long windows and many entities. The standard technique is point-in-time correct batch computation with incremental, windowed aggregations (and partition pruning by date) so only relevant historical partitions are scanned. Reusing intermediate aggregates and bucketing by entity reduces redundant work.

What is the main risk of target (mean) encoding a high-cardinality categorical feature, and how do you mitigate it?

Target encoding replaces a category with the mean of the target for that category, which leaks the label and overfits rare categories whose mean is computed from few rows. Mitigations include computing encodings out-of-fold (using cross-fold or leave-one-out schemes), adding smoothing toward the global mean, and adding noise. At scale these must be computed in a point-in-time-correct, fold-aware way to avoid leakage.

# out-of-fold target encoding with smoothing
global_mean = y.mean()
def smooth(stats, m=10):
    n, mean = stats['count'], stats['mean']
    return (n*mean + m*global_mean)/(n+m)
# compute per fold on the OTHER folds, then map onto held-out fold
For very high-cardinality categoricals (e.g., millions of IDs) in deep models, why is the hashing trick or embedding preferred over one-hot encoding?

One-hot encoding millions of categories produces an unusable, sparse, memory-heavy feature space and cannot handle unseen values. The hashing trick maps categories to a fixed number of buckets in O(1) with bounded memory (accepting some collisions), while learned embeddings map IDs to dense low-dimensional vectors that capture similarity. Both scale to unbounded vocabularies and handle new IDs gracefully.

What is the key consideration when fitting feature scalers/encoders inside a cross-validation loop at scale?

Any fitted transformation (scalers, target encoders, imputers) must be fit only on the training fold and then applied to the validation fold; fitting on the full dataset leaks information and inflates CV scores. At scale this is enforced by wrapping transforms in a pipeline so fit/transform boundaries are respected per fold. The same fitted artifacts are later persisted for serving to guarantee consistency.

In Spark, why can a naive groupBy aggregation for feature computation cause data skew, and how do you address it?

If a few keys (e.g., a popular product or null key) dominate, their partitions become huge and a few tasks run far longer than others, causing stragglers and OOM. Mitigations include salting hot keys (appending a random suffix to split them across partitions then re-aggregating), using map-side combine/partial aggregation, and enabling adaptive query execution to handle skewed joins. Filtering or special-casing null/default keys also helps.

from pyspark.sql import functions as F
salted = df.withColumn('salt', (F.rand()*N).cast('int'))
part = salted.groupBy('key','salt').agg(F.sum('amt').alias('p'))
final = part.groupBy('key').agg(F.sum('p').alias('total'))
What is feature drift versus concept drift, and how do they differ in monitoring implications?

Feature (data/covariate) drift is a change in the distribution of input features P(X); concept drift is a change in the relationship P(Y|X) between features and target. You monitor feature drift with distribution tests (PSI, KL, KS) on inputs without needing labels, while detecting concept drift requires labels or proxy performance metrics. Feature drift can occur without concept drift and vice versa.

What does the Population Stability Index (PSI) measure and how is it commonly interpreted?

PSI measures how much a feature's (or score's) distribution has shifted between a baseline and a current period by summing (actual%-expected%)*ln(actual%/expected%) across bins. Common rules of thumb: PSI < 0.1 means little shift, 0.1-0.25 moderate shift warranting investigation, and > 0.25 a significant shift likely requiring action. It is widely used to monitor feature and score drift in production.

import numpy as np
def psi(expected, actual, bins=10):
    # use unique edges to avoid zero-width bins on skewed data
    edges = np.unique(np.quantile(expected, np.linspace(0, 1, bins + 1)))
    e, _ = np.histogram(expected, edges)
    a, _ = np.histogram(actual, edges)
    e = e / e.sum() + 1e-6
    a = a / a.sum() + 1e-6
    return float(((a - e) * np.log(a / e)).sum())
Why are tree-based gradient boosting models relatively insensitive to monotonic feature scaling, while still benefiting from other feature engineering?

Tree splits depend only on the ordering of values within a feature, so any monotonic transform (standardization, log) leaves the split structure unchanged and offers no benefit for the trees themselves. They still benefit from engineered interactions, ratios, target/count encodings, and handling of high-cardinality categoricals, since those create signal trees can't easily derive from raw columns. Scaling matters mainly for distance/gradient-based models, not trees.

What is the advantage of computing time-windowed aggregation features using sliding windows over event streams (e.g., Flink) rather than recomputing in batch?

Streaming windowed aggregations update incrementally as events arrive, giving low-latency, fresh features (e.g., transactions in last 60s) without rescanning history each time. Frameworks like Flink/Spark Structured Streaming maintain state and emit watermark-aware results that handle late and out-of-order events. Batch recomputation is too slow and stale for real-time use cases like fraud detection.

In a fraud detection pipeline, why might you avoid using a feature like 'account_is_now_blocked' even if it is highly predictive?

Such a feature is a form of leakage because the block status is set as a consequence of the fraud being detected, so it would not be available (or would be a different value) at the prediction time you care about. Using it inflates offline metrics but fails in production where the decision must be made before the block exists. You must use only features whose values are causally available at the moment of scoring.

What is the role of a feature's TTL (time-to-live) in an online feature store?

TTL defines how long a materialized feature value remains valid for serving; once expired, the store returns null/default rather than a stale value. It bounds staleness, controls memory by evicting old entries, and signals when a backing materialization job has fallen behind. Choosing TTL trades off freshness requirements against materialization cost and storage.

When normalizing/standardizing numeric features for a model deployed online, where should the fitted statistics (mean, std) be stored and why?

They must be persisted as versioned artifacts (e.g., in the model/transform bundle or feature store metadata) computed from the training data, and applied identically at serving. Recomputing statistics from live serving data would change the transform and cause training-serving skew. Versioning lets you reproduce and roll back transformations alongside the model.

What is the difference between filter, wrapper, and embedded feature selection methods?

Filter methods rank features by intrinsic statistics (correlation, mutual information, variance) independent of any model and are cheapest. Wrapper methods (e.g., recursive feature elimination, forward selection) repeatedly train a model on subsets and are accurate but expensive. Embedded methods perform selection during model training (L1/Lasso, tree feature importances, gain). At scale, filter and embedded methods dominate because wrappers are too costly.

Why is mutual information often preferred over Pearson correlation for filter-based feature selection?

Pearson correlation only captures linear relationships and can score a strongly nonlinearly-related feature as near zero. Mutual information measures any statistical dependence, including nonlinear and non-monotonic relationships, between a feature and the target. The trade-off is that MI requires density/binning estimation and is more expensive and sensitive to estimator choice.

What problem does the 'cold start' for new entities cause in feature serving, and how is it commonly handled?

A brand-new user/item has no historical aggregates, so its online features are missing, which can break the model or produce poor predictions. Common handling includes returning sensible defaults or global/segment averages, using content-based or contextual features that don't require history, and falling back to a separate cold-start model. The serving layer should explicitly define default values rather than passing nulls blindly.

Why might you store precomputed embeddings as features in a feature store rather than recompute them at inference?

Embeddings from large models (text, image, graph) are expensive to compute, so materializing them once and serving from a low-latency store avoids redundant heavy computation per request. This decouples the embedding pipeline's cadence from serving and keeps inference fast. The trade-off is staleness for entities whose underlying content changes between embedding refreshes.

What is the danger of computing global statistics (e.g., overall mean for imputation) before splitting into train/test, and how does it manifest at scale?

Computing imputation values, scalers, or encodings on the combined data leaks test/future information into training, optimistically biasing evaluation. At scale this is easy to do accidentally in a shared ETL job that produces one wide table. The fix is to compute such statistics within the training partition (and per fold) and persist them, or use point-in-time-correct pipelines that never see future rows.

How does feature lineage/versioning help in a large ML platform?

Lineage tracks how each feature is derived (source tables, transformation code, upstream features) and versioning pins a feature definition to a specific logic, so models can reference exact feature versions reproducibly. This enables debugging drift, reproducing past training sets, impact analysis when a source changes, and safe rollouts of new transformation logic without silently breaking consumers. It is foundational for governance and reproducibility at scale.

What is the benefit of computing features in a declarative transformation framework (e.g., dbt, Spark SQL, or a feature DSL) over imperative per-service code?

A declarative definition has a single source of truth that can be compiled to both batch and streaming/serving execution, reducing training-serving skew and duplication. It enables automatic dependency tracking, lineage, testing, and reuse, and lets the platform optimize execution. Imperative per-service code tends to diverge across teams and pipelines.

Why is naive count/frequency encoding sometimes safer than target encoding for high-cardinality features?

Count/frequency encoding replaces a category with how often it appears, which does not use the label and therefore cannot leak the target. It still gives trees useful signal (popularity/rarity) and handles unseen categories by mapping to zero/low counts. The trade-off is it carries less direct predictive signal than a well-regularized target encoding.

In streaming feature computation, what is a watermark and why is it important?

A watermark is the streaming engine's estimate of event-time progress, declaring that events with timestamps older than the watermark are assumed to have arrived. It lets windowed aggregations decide when to finalize and emit results while tolerating bounded lateness, and lets state be safely dropped to bound memory. Setting it too tight drops late events; too loose increases latency and state size.

What is the purpose of feature value monitoring (e.g., null rate, range, cardinality) in production beyond drift detection?

It catches data quality and pipeline breakages, such as an upstream schema change causing all-null features, a unit change blowing up ranges, or a join failure spiking cardinality. These bugs often degrade models silently and faster than slow statistical drift. Alerting on null rates, min/max bounds, and expected cardinality acts as a fast-failing data contract.

When would you choose log or Box-Cox transformation of a numeric feature, and does it help tree models?

Log/Box-Cox transforms compress heavy right-skewed, multiplicative-scale features (income, counts, prices) toward normality, helping linear and distance-based models and gradient-based optimization. They do not change split decisions for tree models because the transform is monotonic. Use them when the model assumes additive/linear effects or when the feature spans many orders of magnitude.

What is the main scalability advantage of the hashing trick, and what is its principal downside?

The hashing trick maps arbitrary feature names/categories to a fixed-size index space in O(1) with constant memory, requiring no vocabulary to be stored or updated, which is ideal for streaming and unbounded vocabularies. Its principal downside is hash collisions, where distinct categories share an index and their signals are conflated, mildly hurting accuracy. Increasing the hash space size reduces collision probability at the cost of memory.

Why are interaction and ratio features (e.g., spend/income, clicks/impressions) often valuable even with powerful models?

They encode domain-meaningful relationships that the model would otherwise need many splits or large capacity to approximate, improving sample efficiency and generalization. Ratios normalize for scale differences across entities (a $100 charge means different things for different incomes), and explicit interactions capture combined effects directly. Even deep/boosted models benefit because raw features may not expose these relationships compactly.

What is the recommended way to handle categorical features with rare levels at scale to avoid overfitting and serving issues?

Group infrequent levels into a single 'other' bucket using a frequency threshold determined from training data, and reserve an explicit unknown bucket for unseen levels at serving. This stabilizes statistics for rare categories, bounds dimensionality, and guarantees the encoder never fails on new values. The frequency threshold and mapping must be persisted as a versioned artifact for consistent serving.

How do learned embeddings of categorical IDs differ functionally from target encoding, and when is each preferred?

Target encoding is a fixed scalar derived from label statistics, simple and great for tree models, but it compresses a category to one number and risks leakage. Learned embeddings are multi-dimensional vectors trained end-to-end that capture rich similarity structure and interactions, preferred in deep models and when categories have latent structure. Embeddings need more data and a neural architecture, while target encoding works with limited data and any model.

What is a 'feature freshness SLA' and why does it matter for time-sensitive models?

A freshness SLA specifies the maximum acceptable age of a feature value at serving (e.g., 'last-5-min transaction count must be no older than 30s'). It matters because stale features in fast-moving domains like fraud or recommendations degrade decisions even if the value is technically correct. Monitoring materialization lag against the SLA detects pipeline delays before they harm predictions.

Why should feature engineering pipelines be idempotent and partitioned by date in large batch systems?

Idempotency lets you safely re-run a failed or late job for a given date without double-counting or corrupting downstream aggregates, which is essential given inevitable failures and backfills. Date partitioning enables partition pruning (scan only needed days), parallelism, and atomic overwrite of a single day's output. Together they make pipelines reliable, reprocessable, and efficient at scale.

Put it into practice with AI Learning

This topic — and hundreds more — comes from our free, offline AI Learning app. Practice Q&A, quizzes and cheat sheets anywhere, no account needed.

  • Free
  • No account
  • Works offline
Coming soon toGoogle Play