What kind of problem is this?
Before choosing a model, name the genre of the problem: a number, a label, a grouping, a decision, text, an image, a ranked list, or a future value. The same algorithm can serve several genres (an SVM both regresses and classifies), so the genre is a property of the problem, not of the model. Pick a genre to see the families that solve it. Every family links to its full entry.
Regression
How much? Predict a continuous number from features.
- Output
- A real-valued estimate, ideally with an interval around it.
- Typically optimizes
- Squared error (the conditional mean), absolute error (the median), or pinball loss (any quantile).
- OLSLinear Regression · Classical ML
- LassoRidge, Lasso & Elastic Net · Classical ML
- SVMSupport Vector Machine · Classical ML
- Decision TreeDecision Tree (CART) · Classical ML
- Random ForestClassical ML
- Neural NetworksMultilayer Perceptron · Deep Learning
- GBMGradient Boosted Trees · Classical ML
- GLMGeneralized Linear Models · Classical ML
- k-Nearest NeighboursClassical ML
- Stepwise RegressionClassical ML
- Quantile RegressionClassical ML
The loss is the metric. Squared Euclidean error targets the mean and is what least squares and neural regressors minimise; Manhattan (L1) error targets the median and is robust to outliers; Mahalanobis comes in when residuals are correlated across outputs.
What does “similar” mean to the algorithm?
Nearest neighbours, clustering, retrieval and recommendation all reduce to one choice: how to measure closeness. That choice depends first on how much structure the data has, from an unordered set up to a whitened coordinate system, and then on which differences should count. Drag the vectors and edit the sets and strings to see each metric compute, and why the same two points can be near under one metric and far under another.
- 1Set
- 2Sequence
- 3Coordinates in ℝⁿ
- 4Direction
- 5Centred
- 6Whitened
Set: An unordered bag of items. No coordinates, no order, no magnitude. Preprocessing: None: tokenize or list the items.
Jaccard
similarityNone. The two objects are sets, and the only question is how much of their combined membership they share.
- |A ∩ B| / |A ∪ B|2 / 8
- Jaccard0.250
- Cosine on binary vectors, |A ∩ B| / √(|A||B|)0.436
Try making A a small subset of B: cosine stays fairly high because it divides by the geometric mean of the sizes, while Jaccard drops because every item only B has still counts in the union.
- the two sets (tags, tokens, purchased items, shingles)
- items in both
- items in either
- Is not True metric
- Is Bounded
- Is Scale-invariant
- Is not Shift-invariant
O(|A| + |B|) with hashing; MinHash estimates it in O(k) per pair.
Set algebra, not geometry. Because the union is the denominator, items that only one set has count against the score, so a small set inside a big one scores low. 1 − J is a true metric (the Jaccard distance), and the probability that two random hash permutations pick the same minimum element equals J. That fact is what makes MinHash and locality-sensitive hashing possible at web scale.
- Reach for it when
- Binary presence/absence data where absence is not evidence: tags, basket contents, near-duplicate documents (as shingle sets), and the support side of association rules.
- Why not the alternatives
- Cosine on the same binary vectors divides by √(|A||B|) instead of the union, so it forgives a size mismatch that Jaccard penalises. Hamming or Euclidean on binary vectors count shared absences as agreement, which in a sparse catalogue of a million items means every pair looks almost identical.
- Where it breaks
- It throws away counts and weights: a customer who bought 40 of an item and one who bought 1 look the same. Use weighted Jaccard or TF-IDF cosine when frequency matters.
- Problem genres that lean on it
- NLP / LLMRecommender SystemComputer VisionClustering
A decision path, general to niche
Once you know the genre, these questions narrow it to a family and then to a model, by what you are producing, what the data looks like, and what constrains you.
What are you trying to produce?
The most general question there is, and the only one that reliably narrows the field before you know anything else. The shape of the output — a number, a label, a sequence, new data, or a decision — determines the loss, and the loss determines the family.
A number or a score
Do you have labelled examples of the number you want?
Supervision is the next binding constraint. With labels this is regression; without them you are describing the data instead, which is a different family entirely.
Yes — I have labels
Do you need to explain the prediction to someone?
Interpretability is a hard requirement in regulated and high-stakes settings, and it narrows the field before accuracy does. It is a constraint, not a preference.
Yes — it must be explainable
Start with the linear family.
A regularized linear model gives coefficients you can defend, calibrated intervals, and a baseline that a more complex model has to beat before it earns its operational cost.
Linear ModelsNo — accuracy is what matters
Go to gradient boosting.
On tabular data, boosted trees remain the strongest default. Reach past them only when the data stops being tabular.
Gradient Boosting
No labels
Are you looking for axes, or for groups?
Without a target the only options are describing variation (a low-rank basis) or partitioning (clusters). Both are unsupervised, but they answer different questions.
Structure & Clustering
A category or a group
How rare is the class you care about?
Balanced classification and rare-event detection look identical on paper and behave nothing alike. Below roughly 1% positives, accuracy stops meaning anything and the problem becomes "model normal, measure deviation".
Balanced — both classes are common
Is your data tabular, or perceptual?
Tabular data still belongs to gradient boosting; images, audio, and text belong to learned representations. This is the most reliable modality split in applied ML.
Trees & EnsemblesRare — under ~1%
Do you have labelled anomalies, or only normal data?
Almost always only normal data, and the interesting anomalies are ones never seen before — which is why this is a modelling-normality problem rather than a classification one.
Anomaly Detection
A sequence over time
One series, or many related series?
This single question separates classical forecasting from deep forecasting more reliably than anything else. Cross-series structure is the only thing that pays for a deep model; without it you are fitting a large model to a small problem.
One short series
Does it have clear trend and seasonality?
On a few hundred points the structure is low-dimensional and a stated model beats a learned one. Start at the seasonal-naive baseline and make anything fancier earn its place.
Classical Time SeriesMany, long, or coupled series
Are the series linked by a known structure?
If the relationships are known — a road network, a grid, a supply chain — a graph prior encodes them directly. If they are merely numerous, a global sequence model shares statistical strength without needing the topology.
Time-Series ForecastingYes — the topology is known
Encode the relationships directly.
When you already know which series influence which — a road network, a power grid, a supply chain — a graph prior states that structure instead of making the model rediscover it from data.
Graph architecturesNo — just a great many of them
Train one global sequence model across all of them.
Thousands of related series share statistical strength even without a known topology. This is the case where a deep model genuinely beats per-series classical fits, and the only one where it reliably does.
Sequence architectures
New data or content
Do you need an exact likelihood, or just good samples?
The central trade-off of generative modelling. Exact density, fast sampling, and stable training cannot all be had at once, and which one you give up defines the architecture.
I need exact likelihood
Is the data sequential, or continuous?
The chain rule gives exact likelihood for free on sequences; on continuous data you need an invertible map. That is the whole reason both autoregressive models and normalizing flows exist.
Latent-Variable ModelsSamples matter more than density
Can you afford many steps at sampling time?
Diffusion buys quality and training stability by spending many forward passes per sample. If inference latency binds, a one-shot generator is the trade you make.
Diffusion
A decision under feedback
Does your action change what you observe next?
The dividing line between prediction and control. If actions change the state, you have a sequential decision problem and no supervised loss can express the objective. If they do not, you have a much simpler bandit.
Yes — there is state and delayed reward
Are your actions discrete, or continuous?
Value-based methods take a max over actions, which is only tractable when actions are discrete. Continuous action spaces force an actor-critic formulation — this is the fork inside RL.
Reinforcement LearningDiscrete — a finite menu
Learn the value of each action.
Taking a max over actions is only tractable when there are finitely many, which is exactly the assumption value-based methods rest on.
Value-based methodsContinuous — a real-valued setting
Parameterize the policy directly.
Greedy maximization over a continuous action space is not tractable, which forces an actor-critic formulation — the fork that defines this half of the category.
Continuous control
There are hard constraints to satisfy
Must every answer be feasible, not just good?
Once feasibility is non-negotiable — a schedule that must fit, a budget that must balance — a learned model that cannot guarantee constraint satisfaction belongs inside the solver rather than replacing it. That reframing is what separates optimization from prediction.
OptimizationNo — each choice is independent
Do you have context features for each decision?
A stateless repeated choice is a bandit, not an MDP, and reaching for full RL here adds instability for nothing. This is the most common correct answer in production, and the most commonly over-engineered.
Multi-Armed Bandits
Which category, and what it assumes
Ordered by how much they assume. Classical ML assumes you can state the structure; deep learning assumes you have enough data to learn it; generative modelling assumes you want the distribution rather than a mapping; reinforcement learning assumes an environment you can act on. Each premise is a trade, and naming the trade is what makes the choice arguable rather than fashionable.
Classical ML
Most generalYou supply the structure — the features, the functional form, the assumed noise — and the model fits a small number of parameters inside it. That buys you sample efficiency, calibrated uncertainty, interpretability, and training that finishes in seconds. It costs you everything the features do not capture: if the real signal is an interaction you did not encode, the model cannot find it.
8 groups, general to niche
Deep Learning
Rung 2Instead of supplying features, you supply an architecture whose structure matches the structure of the data — locality for images, recurrence or causal masking for sequences, adjacency for graphs — and let gradient descent learn the representation. That buys you the ability to model interactions nobody could hand-engineer. It costs data, compute, calibration, and interpretability, and it wins only when there is enough data for the learned representation to beat a stated one.
9 groups, general to niche
Generative AI
Rung 3Rather than learning a mapping from input to label, you learn the distribution the data came from. That buys you sampling, density scoring, and a use for unlabeled data at scale. It costs you a hard evaluation problem — likelihood, sample quality, and usefulness disagree with each other — and it means the tractable trade-off you pick (exact likelihood, fast sampling, or stable training) is the defining design decision.
6 groups, general to niche
Reinforcement Learning
Most specializedYou give up i.i.d. data entirely: your own actions determine what you observe next, and the signal is a scalar reward that may arrive many steps after the decision that earned it. That buys you the ability to optimize a long-horizon objective directly, which no supervised loss can express. It costs sample efficiency, stability, and safety — and it is the wrong tool whenever the real task is prediction rather than control.
5 groups, general to niche
The three this site goes deepest on
Each of these answers the same question from the other direction: given this problem shape, which category is the default, which is situational, and which is rarely the right tool — argued from the structure of the problem rather than from popularity.
Time-Series Forecasting
Observations are ordered and dependent, which breaks the i.i.d. assumption every other supervised setting rests on. The signal usually decomposes into trend, seasonality, and autocorrelated noise, and the label is simply the series' own future value — so "more data" often means a longer history of the same process, not more independent examples. The binding constraint is that you must never let information from the future leak backwards, which rules out ordinary shuffled cross-validation outright.
Which model, and whyAnomaly Detection
The positive class is rare (often well under 1%), frequently unlabeled, and the interesting anomalies are the ones you have never seen — so the problem is usually "model normal and measure deviation", not "classify". Accuracy is meaningless at this base rate, and the real constraint is almost always the alert budget: how many false positives per day a human team will tolerate before they stop reading the alerts.
Which model, and whyOptimization
The deliverable is a decision, not a prediction: choose the assignment, schedule, price, or allocation that maximizes an objective subject to hard constraints. Feasibility usually matters more than accuracy — a slightly worse feasible plan beats an excellent infeasible one — and the objective is frequently non-differentiable or only observable by trying it.
Which model, and whyWhat idiomatic and optimized mean here
Every model carries nine code samples — Python, C/C++, and Rust, each progressing from the math transcribed literally, to how that language actually wants it written, to an optimized form that names the lever it pulls and the trade-off it accepts. Those definitions live here rather than being re-derived per model, and a build-time check holds each sample to them. The philosophy behind the three stages is on the technical-prep page.
Python
PEP 8 · PEP 484 type hints · PEP 257 docstrings
- Explicit type hints on every public signature
- No mutable default arguments
- Dataclasses or NamedTuples over ad-hoc dicts
- Context managers for resource cleanup
- Raise specific exceptions, never bare except
- Guard clauses over nested conditionals
- Vectorize to NumPy/BLAS (@, np.dot, einsum)
- Eliminate Python-level loops over samples
- Pre-allocate output arrays and use in-place operations
- Ensure contiguous memory layout and a single dtype
- Replace a closed-form solve with a numerically stabler factorization
- Batch work to amortize interpreter overhead
- Fuse adjacent operations so intermediates are never materialized
- Reach for a compiled kernel (numba/JAX) only once profiled
- Premature numba/Cython before profiling
- Lists-of-lists standing in for matrices
- Broadcasting tricks that obscure the shape contract
Numeric: NumPy / SciPy · ML: scikit-learn, PyTorch
C/C++
C++ Core Guidelines · ISO C++20
- RAII for every owned resource
- const-correctness on parameters and members
- No raw new/delete; std::vector and smart pointers instead
- std::span for non-owning views
- Rule of zero — let the compiler generate special members
- Fail fast on invalid input before any allocation
- Compile with -O3 -march=native
- Row-major, cache-friendly memory layout
- Loop fusion to eliminate intermediate buffers
- Restrict/aliasing hints so the compiler can vectorize
- Rely on compiler autovectorization before hand-written SIMD
- OpenMP for data-parallel loops
- Eigen expression templates to avoid temporaries
- Delegate the inner kernel to a tuned BLAS
- Hand-written SIMD intrinsics before measuring
- Raw owning pointers
- Premature multithreading of a memory-bound loop
Numeric: Eigen, BLAS/LAPACK · ML: libtorch
Rust
Rust API Guidelines · Rust Style Guide
- Result<T, E> over panics for recoverable errors
- Iterator chains over manual index loops
- Borrow rather than clone; take &[T] not Vec<T>
- Newtypes for units and dimensions
- Forbid unsafe unless a benchmark justifies it
- Validate inputs at the constructor boundary
- Iterator chains for bounds-check elision
- rayon for data parallelism
- ndarray with the BLAS feature enabled
- Vec::with_capacity to avoid reallocation
- Eliminate needless clone() in the hot path
- #[inline] on small hot functions
- Operate on slices to keep data contiguous
- unsafe for speed without a benchmark
- clone() to sidestep the borrow checker
- Collecting an iterator only to immediately re-iterate it
Numeric: ndarray · ML: linfa, candle / burn
87 models published so far; more landing per category.