Chris Collins

Tools · ai

Classic machine learning, step by step

Classic machine learning on 2-D data you can edit — a decision tree growing split by split with its best-split search, a random forest's bootstrap trees and vote map, gradient boosting round by round, k-NN, logistic regression, a soft-margin linear SVM and Gaussian naive Bayes side by side — and an optimiser lab racing SGD, momentum, Nesterov, AdaGrad, RMSProp, Adam and AdamW over Rosenbrock, Beale, a saddle and an ill-conditioned bowl with learning-rate schedules.

Added

How to use it

Two classes of points on a plane, and the classic models drawing their decision boundaries over them. Every model is computed exactly, in this page, and checked against scikit-learn. Every setting can be put in a link — see Linking to an example.

The data

Each classifier tab has the same Data panel: a dataset (two moons, circles, blobs, XOR, a spiral or a linear split), the number of points, the noise, and New sample for another random draw (the seed). 30 % of the points are held out as a test set: filled points train the model, hollow points only test it, so every tab shows a train and a test accuracy and overfitting is something you can see. The plot’s mode:

  • Probe — hover (or tap) to read the model’s probability of class 1 at that spot.

  • + ● blue / + ▲ red — tap to add a training point of that class (outlined).

  • Erase — tap a point to remove it. Clear edits brings the original sample back.

Shading shows the predicted class and how sure the model is; the line is the decision boundary, where p = ½.

Decision tree

CART as scikit-learn grows it: at each node, try every threshold halfway between neighbouring values of each feature, score each by the drop in impurity (Gini, or entropy in bits), keep the best, and stop at the maximum depth, below min samples to split, when a child would get fewer than min samples per leaf, or when the node is pure. Next ▶ makes one split at a time (breadth first), ◀ undoes one, Play animates the growth and ⏭ Grow finishes it. The dashed box on the plot is the node about to be split, with its chosen line; the chart under it plots every candidate threshold for x₁ and x₂ against its impurity decrease, with the winner ringed, and the diagram draws the tree so far: the split, impurity, size and class counts of each node (up to six levels). The XOR example shows the greedy search’s blind spot: no single split lowers the impurity much, but two levels solve it.

Random forest

Many deep trees, each grown on a bootstrap sample (n points drawn with replacement, so about 63 % distinct) and choosing each split from a random subset of the features — with two features, scikit-learn’s default √p means one at random per split. The forest averages the trees' class probabilities: the main plot is that vote share. Small multiples show the first eight trees with their own samples (big dots were drawn several times, faint ones are out of bag); tap one, or use Show, to see it large. The out-of-bag error judges every training point only by the trees that never saw it — a free estimate of the test error.

Gradient boosting

Friedman’s gradient boosting for log loss, as scikit-learn’s GradientBoostingClassifier: the score starts at the log-odds of the class share, F₀ = log(p/(1 − p)); each round fits a small regression tree to the pseudo-residuals y − p and gives each leaf the Newton step Σr / Σp(1 − p), added after shrinking by the learning rate. Step through the rounds: point size shows how wrong the model still is at each training point, the small plot shows the tree added that round (red pushes towards class 1, blue towards 0), and the chart shows train and test log loss by round, with the best test round ringed — more rounds keep lowering the training loss long after the test loss has turned.

k-NN, logistic regression, linear SVM, naive Bayes

  • k-NN: k, the distance (Euclidean, Manhattan, Chebyshev) and equal or 1/distance votes. Probe a point to see its k neighbours, the ball that holds them (a circle, a diamond or a square, depending on the distance) and a table of their distances. k = 1 is perfect on the training set and ragged on the test set.

  • Logistic regression: on every monomial up to the degree (degree 2 can draw a circle), with L2 regularisation. Fitted exactly by Newton’s method on scikit-learn’s objective ½‖w‖² + C Σ log loss (intercept unpenalised). Shows the coefficients. For the one-feature version and its cross-entropy bowl, see the maths of machine learning.

  • Linear SVM: the soft margin. Minimises ½‖w‖² + C Σ max(0, 1 − y(w·x + b)), solved in the dual by SMO with LIBSVM’s working-set selection; draws the boundary, the margin lines ±1, the support vectors (thick ring: αᵢ = C, inside or beyond its margin) and reports the margin width 2/‖w‖. Small C: wide margin, many violations; large C: narrow margin.

  • Naive Bayes: one Gaussian per feature per class (scikit-learn’s GaussianNB, var_smoothing 10⁻⁹), drawn as axis-aligned ellipses at 1σ and 2σ, with the fitted means, variances and priors. Untick the class-share prior to move the boundary with the prior slider.

Compare draws all seven models, each with its own tab’s settings, on the current data, with their train and test accuracies. Tap one to open its tab.

Optimiser lab

Seven optimisers race down a loss surface from the same start. Tap the plot to move the start.

  • Surfaces: Rosenbrock’s banana valley, (1 − x)² + 100(y − x²)², minimum at (1, 1); Beale’s function, minimum at (3, ½); a saddle, x² − y², with no minimum (start just off the ridge and watch who escapes); an ill-conditioned quadratic ½(u² + κv²) turned 30°, where plain gradient descent diverges once the learning rate passes 2/κ; and Himmelblau’s function with four minima.

  • Optimisers, exactly as PyTorch’s torch.optim defines them: SGD; momentum (b ← μb + g, step lr·b); Nesterov (step lr·(g + μb)); AdaGrad; RMSProp (α 0.99); Adam (bias-corrected moments, β₁, β₂); AdamW (Adam with decoupled weight decay, p ← p(1 − lr·λ) first). Tick the ones to run; each has its own learning rate (Suggested rates restores the defaults for the surface).

  • Schedules: constant; step (halve every quarter of the run); cosine annealing; linear warm-up over the first 10 % then cosine; and one-cycle (PyTorch’s OneCycleLR: from lr/25 up to lr at 30 % of the run, then down to lr/250 000, cosine-shaped). The small chart plots the multiplier.

  • Hyperparameters: momentum μ, β₁, β₂, AdamW’s decay λ and gradient noise σ, Gaussian noise added to every gradient (seeded) to mimic mini-batch SGD.

The paths animate together (Play, Restart, speed, or drag the Step slider); the chart plots f − f_min on a log scale for each, and the table gives each optimiser’s loss and distance to the nearest minimum at the current step.

Full screen

⛶ Full screen (or the F key) fills the screen with the tool: the plot grows to fill the space and the side panel can be hidden with Hide panel so the plot goes edge to edge. Escape (or the button) leaves. Where the browser has no full-screen mode (iPhone) the tool covers the window instead.

Limits

  • Two features and two classes only, so everything can be drawn. Up to 400 generated points plus your own.

  • The models are exact for small data but not fast: random forests of 100 deep trees or k-NN with many points take a moment to redraw.

  • The SVM is linear only (no kernels) and stops at LIBSVM’s tolerance (10⁻³), so its w and b agree with scikit-learn’s to about three decimals. The SVM shading is a squashed margin, not a probability.

  • The random forest uses its own seeded random numbers, so its trees are not scikit-learn’s for the same data (the method is the same). Ties between equally good splits go to the first found.

  • The optimisers run on exact gradients of two-variable functions; real training has millions of parameters and noisy gradients, so treat the race as intuition, not a benchmark.

Tested against scikit-learn 1.9.1 on a fixed 40-point dataset: the decision tree’s root split (feature, threshold, impurity), all node impurities, probabilities and feature importances for Gini and entropy; KNeighborsClassifier probabilities for four settings; GaussianNB means, variances, ε and probabilities; LogisticRegression coefficients (raw and degree-2 features); SVC(kernel="linear") w, b, support-vector counts and accuracy for C = 0.1, 1, 10; and GradientBoostingClassifier probabilities and training deviance. The optimiser steps are checked against the update formulas in the PyTorch documentation and the schedules against their definitions.

Sources: L. Breiman, J. Friedman, R. Olshen, C. Stone, Classification and Regression Trees (1984); L. Breiman, Random forests (2001); J. H. Friedman, Greedy function approximation: a gradient boosting machine (2001); J. Platt, Sequential minimal optimization (1998) and R.-E. Fan, P.-H. Chen, C.-J. Lin, Working set selection using second order information (2005); S. Shalev-Shwartz et al., Pegasos (2007), for the primal view of the same hinge loss; Y. Nesterov (1983) and I. Sutskever et al. (2013) for momentum; J. Duchi, E. Hazan, Y. Singer, AdaGrad (2011); G. Hinton, Lecture 6e of Neural Networks for Machine Learning (RMSProp, 2012); D. Kingma, J. Ba, Adam (2015); I. Loshchilov, F. Hutter, Decoupled weight decay regularization (AdamW, 2019) and SGDR (cosine annealing, 2017); L. Smith, Super-convergence (one-cycle, 2018); scikit-learn’s user guide and the torch.optim documentation.

Related: Neural network designer (the next step: train a network on the same kinds of data), The maths of machine learning (least squares, gradient descent, logistic regression in one dimension, backpropagation), Model evaluation (confusion matrices, ROC and PR curves, calibration), Embedding explorer, PCA and SVD and Statistics.

Linking to an example

A link opens the tool with the given settings: /tools/ml-visualiser/?<parameters>#<tab>, where the tab is tree, forest, boost, knn, logreg, svm, bayes, compare or optim. Share link (top right) builds one from whatever is on screen; points you added or erased are packed into the link too.

Parameter Meaning Example

example

a preset (list below); other parameters in the same link override it

tree-xor

data

dataset: moons, circles, blobs, xor, spiral, linear

circles

n

number of generated points (20–400)

200

noise

Gaussian noise added to each coordinate

0.15

seed

random sample (also seeds the forest and the gradient noise)

3

crit

tree impurity: gini or entropy

entropy

depth

tree maximum depth

4

mss

tree minimum samples to split

2

msl

tree minimum samples per leaf

1

step

splits made so far (999 = the whole tree)

3

trees

forest size

25

rfdepth

forest trees' maximum depth

6

boot

bootstrap samples (true/false)

true

maxf

features tried per split: 1 or 2

1

show

forest tree shown (0 = the vote)

0

rounds

boosting rounds

60

lr

boosting learning rate

0.3

gbdepth

boosting tree depth

2

round

boosting round shown

10

k

k-NN neighbours

7

metric

k-NN distance: euclidean, manhattan, chebyshev

manhattan

weights

k-NN votes: uniform or distance

distance

deg

logistic regression polynomial degree (1–6)

2

C

logistic regression C

10

svmC

SVM C

0.1

prior

naive Bayes P(class 1); −1 = the class share

0.3

surf

optimiser surface: rosenbrock, beale, saddle, quadratic, himmelblau

beale

kappa

quadratic’s condition number κ

50

steps

optimiser steps

1500

sched

schedule: constant, step, cosine, warmup, onecycle

cosine

on

optimisers run: any of sgd,momentum,nesterov,adagrad,rmsprop,adam,adamw

sgd,adam

lrs

learning rates that differ from the suggested ones

sgd:0.002,adam:0.1

mu, b1, b2, wd, gnoise

momentum μ, β₁, β₂, AdamW decay λ, gradient noise σ

0.9

sx, sy

start point

-1.5

Presets for example=:

Name Tab Shows

tree-moons

tree

A depth-4 tree on two moons, three splits in

tree-xor

tree

XOR: no single split helps, yet two levels solve it

tree-overfit

tree

A full-depth entropy tree memorising noisy moons

forest-moons

forest

25 bootstrapped trees voting on noisy moons

boost-circles

boost

Boosting stumps into a circle, round by round

knn-k1

knn

k = 1 on noisy data: islands around every point

logreg-circles

logreg

Circles: a straight line fails, degree 2 succeeds

svm-soft

svm

Soft margin with C = 0.1: a wide margin with violations

nb-blobs

bayes

Gaussian naive Bayes on two blobs

opt-rosenbrock

optim

Rosenbrock’s valley: SGD, momentum, RMSProp and Adam

opt-saddle

optim

A saddle point: plain SGD lingers, adaptive methods escape

opt-illcond

optim

κ = 50: SGD zig-zags, momentum and Nesterov cut across

opt-onecycle

optim

The one-cycle schedule on Beale’s function

Runs entirely in your browser; nothing you type leaves this page.