ML Engineer interview prep
A spaced-repetition deck of 381+ ML Engineer interview questions — organised by topic and difficulty, and resurfaced right before you'd forget. Preview a few cards below, then sign in to study the whole track on an Anki-style SM-2 schedule.
Free · sign in with GitHub · your progress stays yours.
What's covered
Every topic in this track, grouped the way you'd study it.
Model Serving & ML Infrastructure
12 cardsDistributed Training & GPU
11 cardsLLM Inference & Optimization
12 cardsML Engineering Practice
9 cardsLive Coding: From Scratch
9 cardsML Fundamentals & Validation
10 cardsClassical ML & Ensembles
12 cardsMetrics & Class Imbalance
11 cardsFeatures, Data Prep & Leakage
10 cardsDeep Learning
12 cardsNLP & LLMs
12 cardsML System Design
8 cardsMLOps & Production
10 cardsPython
130 cardsCS Fundamentals
43 cardsDevOps & Infra
35 cardsBehavioral
35 cardsSample questions
A few cards from the deck — reveal each answer, then sign in to study the full set on a schedule.
Online vs batch inference: when do you pick which?
Online vs batch inference: when do you pick which?
Short answer: Batch inference computes predictions ahead of time on a schedule and stores them; online inference answers each request in real time. The choice comes down to two questions: are the inputs known in advance, and how quickly do predictions go stale?
In depth:
| Batch | Online | |
|---|---|---|
| When | inputs known ahead of time (nightly recs for all users) | features exist only at request time (search query, cart contents) |
| Latency | not critical; serve precomputed results from a KV store in milliseconds | hard SLA on p99 |
| Cost | cheap: offline job, spot GPUs | expensive: 24/7 replicas sized for peak traffic |
| Weakness | predictions go stale between runs | infrastructure complexity and fragility |
The standard hybrid: batch-precompute candidates and embeddings, then run only a light reranker online using fresh request-time features.
⚠️ Common mistake: moving everything online "for freshness." If a prediction can be computed ahead of time, batch is almost always cheaper, simpler, and more reliable.
Data vs tensor vs pipeline parallelism: when do you use each?
Data vs tensor vs pipeline parallelism: when do you use each?
Short answer: Data parallelism — when the model fits on one GPU: a replica on every device, the batch is split, gradients are combined with all-reduce. Tensor parallelism splits individual matmuls across GPUs — needs NVLink-class links, intra-node. Pipeline parallelism splits layers into stages; micro-batches fight the bubble. The largest models combine all three — 3D parallelism.
In depth:
| Kind | What is split | When to use | Cost |
|---|---|---|---|
| Data (DDP) | the batch | model fits on 1 GPU | gradient all-reduce every step |
| Tensor | matmuls inside a layer | a layer/model doesn't fit; fast intra-node links | communication in every layer, forward and backward |
| Pipeline | layers → stages | model doesn't fit, inter-node links are slow | pipeline bubble — idle stages |
| 3D | everything at once | LLM scale | orchestration complexity |
- Order of choice — start with data parallelism; a layer doesn't fit → tensor parallelism within a node; the whole model doesn't fit → pipeline across nodes.
- The bubble — stages sit idle at the start and end of each step; mitigated by slicing the batch into micro-batches.
⚠️ Common mistake: conflating tensor and pipeline parallelism: TP splits matrices inside a layer (all GPUs compute the same layer together), PP splits the model by layers into sequential stages.
What is the KV-cache and what problem does it solve?
What is the KV-cache and what problem does it solve?
Short answer: The KV-cache stores the per-layer K and V matrices of every token processed so far. Without it, autoregressive generation would recompute K and V for the whole prefix at every step — O(n²) work per sequence; with the cache, each decode step computes K, V and Q only for the single new token — O(n) total.
In depth:
- Why it works — K and V of past tokens do not depend on future ones: compute them once, reuse them at every later step.
- What is cached — only K and V, separately per layer. The current token's Q is computed fresh: it is needed exactly once — for this token to attend over the past — and is never reused.
- The cost — memory: the cache grows linearly with context length and batch size, and at long contexts it rivals the weights themselves in size.
No cache: step t → recompute K,V for tokens 1..t (O(t) per step, O(n²) total)
With cache: step t → K,V for token t only + read
cached K,V of tokens 1..t-1 from HBM (O(1) compute, O(n) total)
⚠️ Common mistake: saying "Q, K and V are cached." Q is not cached — a token's query is used exactly once, at the moment it is generated.
How do you test ML code when the "right answer" is stochastic?
How do you test ML code when the "right answer" is stochastic?
Short answer: Separate the deterministic from the stochastic. Transforms, losses and metrics get ordinary unit tests on hand-computable cases; training is covered by smoke tests (overfit a tiny batch, shape and gradient-flow checks) and behavioral tests with tolerances.
In depth:
| Layer | What it checks | Example |
|---|---|---|
| Unit tests | transforms, losses, metrics on hand-made cases | loss(y, y) == 0 |
| Shape/dtype/gradients | dimensions, types, gradient reaches every parameter | after backward() no param.grad is None |
| Overfit one batch | the pipeline can learn 10 examples to ~100% | if it can't → the wiring is broken, not the data |
| Behavioral | invariance and directionality | a synonym must not flip the class; "awful" lowers sentiment |
| Golden predictions | reference predictions with tolerance, run in CI | catch silent regressions after refactoring |
- Test the code, not the model — deterministic pieces (features, losses) deserve exact asserts; stochastic ones get tolerances and invariants.
- Smoke test in CI — a short 2–3 step run: the pipeline assembles, the loss is finite and decreasing.
⚠️ Common mistake: "we look at test accuracy" — that's model evaluation, not code testing. A dataloader bug can cost a couple of metric points and never surface.
Write numerically stable softmax and cross-entropy. Why can't you compute softmax and then take the log?
Write numerically stable softmax and cross-entropy. Why can't you compute softmax and then take the log?
Short answer: Subtract the row max before exp — exp(89) already overflows float32. For the loss, don't compute softmax and log separately; combine them as log-sum-exp: CE = logsumexp(z) − z[y].
In depth:
- Shift by the max — softmax is shift-invariant: exp(z − m)/Σexp(z − m) is the same value, minus the overflow.
- log-softmax in one piece — log(softmax(z)) = z − m − log Σ exp(z − m); we never take the log of a near-zero.
- CE as indexing — minus log-softmax at the correct class position, averaged over the batch.
import numpy as np
def log_softmax(z):
z = z - z.max(axis=1, keepdims=True) # exp(89) overflows fp32
return z - np.log(np.exp(z).sum(axis=1, keepdims=True))
def cross_entropy(z, y):
# CE = logsumexp(z) - z[y]; no separate softmax -> log
n = len(y)
return -log_softmax(z)[np.arange(n), y].mean()
⚠️ Common mistake: computing softmax, then taking the log — under saturation the probability rounds to 0 and log yields −inf. This is exactly why PyTorch's F.cross_entropy takes logits, not probabilities.
What is overfitting, how do you detect it, and how do you prevent it?
What is overfitting, how do you detect it, and how do you prevent it?
Short answer: Overfitting means the model learned the noise of the training set instead of the pattern: low error on train, high error on new data. You detect it via the train/validation gap and fix it with regularization, a simpler model, early stopping, and more data.
In depth:
- Detection — compare train vs validation error; learning curves: train error keeps falling while validation error stalls or rises → the model started memorizing noise.
- Treatment — reduce capacity or add signal, don't just chase the metric.
| Detect | Fix | |
|---|---|---|
| Metric gap | train ≈ 0, validation clearly worse | regularization (L1/L2), simpler model |
| Learning curves | curves diverge as training goes on | early stopping |
| Cross-validation | unstable metrics across folds | more data, augmentation |
| Model complexity | deep trees, millions of weights | limit depth, prune features |
⚠️ Common mistake: saying "cross-validation prevents overfitting." CV only detects it — it gives an honest quality estimate. Prevention comes from regularization, simpler models, and data.
Ready to make it stick?
Start your first session in under a minute. Your future self, mid-interview, will thank you.
Questions about this track
How should I prepare for a ML Engineer interview?
Study the concepts you'll be asked to explain, not just the ones you can code. RecallDeck's ML Engineer track gives you 381+ curated interview questions and resurfaces each one with an Anki-style SM-2 schedule right before you'd forget it — so the answers are still there under pressure on interview day.
What topics does the ML Engineer track cover?
The ML Engineer track is organised into the core areas ML Engineer interviews actually test, grouped by topic and by difficulty (Concept, Junior, Middle, Senior). You can preview the full outline and sample questions above before signing in.
Is spaced repetition effective for ML Engineer interview prep?
Yes. Actively recalling an answer and grading yourself honestly builds far more durable memory than re-reading notes. RecallDeck schedules each ML Engineer card to reappear at the moment you're about to forget it, so your daily reviews shrink while your recall holds.
Is the ML Engineer track free?
Yes — the ML Engineer track and the full SM-2 scheduler are free, with 20 new cards a day. Sign in with GitHub and your progress syncs to your account. RecallDeck Pro ($5/month or $29/year) raises the daily budget and adds cram mode.