Decision trees cut the plane into a De Stijl painting; a forest blurs it into glazes.
A decision tree's leaves are axis-aligned rectangles, so its partition is painted as a composition in red, blue, yellow and white with black bars for the cuts. The tree is grown with CART: at every node both axes are swept, every midpoint is tried, and the cut with the lowest weighted Gini impurity wins. Splits are revealed breadth-first, each bar sliding across its parent rectangle before the two halves are washed in their majority colors (mixed leaves stay white). Deep trees chase the noisy points and fracture the canvas into slivers, which the plaque measures with training and test accuracy. The forest mode grows 32 trees on bootstrap resamples, each choosing a random axis at every split, and averages their leaf votes into a soft glaze with every tree's bars laid over it in pencil.
Try it. Click the painting to add a point in the selected paint and shift-click (or right-click) to remove one; the tree regrows instantly. Change the depth with the minus and plus chips, switch between Tree and Forest, or start a new composition. Keys: arrows change depth, F and T switch modes, 1 to 4 pick a paint, N for a new composition, P hides the points.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a decision tree visualizer that paints its partition like a Mondrian, with JavaScript and the HTML canvas element. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.
Start simple:
- Make a canvas that fills the window, stays sharp on high-DPI screens (scale by devicePixelRatio), and draw a 3:2 painting area centered on a pale gallery-wall background.
- Generate about 150 labeled points in the unit square with four classes: white (scattered everywhere) plus red, blue and yellow (each mostly inside its own random rectangle), with a few labels flipped at random as noise.
- Grow a CART decision tree: at each node, for both axes, sort the points, try every midpoint between neighboring values, and keep the split with the lowest weighted Gini impurity (1 - sum of squared class proportions). Stop at a maximum depth of 5 or when a node is pure.
- Draw each leaf rectangle filled with its majority class color (white if no class has 60 percent), then draw every split as a thick black bar across its parent rectangle.
- Draw the points as small dots on top.
Once that works, make it beautiful:
- Reveal the splits one at a time in breadth-first order: each bar slides across its rectangle, then the two halves fade from the parent's color into their own.
- Make the bars thinner the deeper the split, and add a subtle canvas grain over the paint.
- Add plus and minus buttons for the depth, and let a click add a point in the selected color, so you can watch a deep tree overfit into slivers.
Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as a random forest that averages many bootstrapped trees into a soft vote map, showing test accuracy to measure overfitting, or a gallery plaque with the painting's title.