Fifteen numbers learning the shape of a comfortable room

Ten rows, two inputs, one answer, and a network small enough to print. Every weight is on the page, every multiplication can be checked on paper, and the error that trains it can be watched walking backwards through the layers one edge at a time.

2 inputs · 2 hidden layers · 15 weights · 10 rows

the whole network, and one row moving through itpress send a row
forward is solid, backward is dashed

A straight line cannot describe a comfortable room

Ten rooms. For each one, the temperature, the humidity, and how comfortable people said it was out of ten.

Comfort is not a straight line in either input, and that is the whole reason this page exists. Too cold is bad. Too hot is bad. Somewhere around 23 degrees is lovely. The same for humidity. A rule of the form "comfort goes up by so much per degree" is wrong at both ends no matter what number you choose.

Press the button and the best straight line through both features will be drawn. It is the best one that exists, and it is still bad.

figure 1 · ten roomscomfort against temperature
Try the line, then the network. The line's mistakes are 0.023; the network's are 0.003. Seven times better, from fifteen numbers.
picture it

Fitting a plank to the inside of a bowl. You can angle the plank, you can slide it, and it will still cross the curve in two places and miss everywhere else. No amount of choosing a better plank fixes a curve. You need something that can bend.

A neural network is the cheapest way to build something that bends. It is made of a part so simple you can compute it in your head.

A neuron multiplies, adds, and squashes

That is the entire operation. Take the inputs, multiply each by its own weight, add a bias, then push the result through a function that flattens the extremes.

Here is one neuron doing it, on room seven: 27 degrees, 65 percent humidity. The inputs are scaled to sit near 0 and 1 first, which is bookkeeping rather than mathematics.

x1 = (27 − 15) / 20 = 0.60     x2 = (65 − 30) / 50 = 0.70

z = w1×x1 + w2×x2 + b
  = 1.2×0.60 + (−0.8)×0.70 + 0.1
  = 0.72 − 0.56 + 0.1 = 0.26

a = tanh(z) = tanh(0.26) = 0.254

Drag the weights below and watch the output move. The squash is what stops the neuron being a straight line, and it is the only nonlinear thing in the entire network.

figure 2 · one neuron, three dialsa = 0.254
Drag any dial. The dot slides along the tanh curve. Push a weight far enough and the output saturates: beyond about z = 2 the curve is flat and the neuron stops responding.
picture it

A volume knob with a limiter. Turn it up and the sound gets louder, but only to a point; past that the amplifier flattens everything into the same loudness. That flattening is exactly what makes a stack of neurons able to bend, and exactly what makes them stop learning when you push them too far.

Two hidden layers is fifteen numbers and nothing else

Stack those neurons. Two inputs feed two neurons, those feed two more, and those feed one output that is not squashed because comfort is a quantity rather than a yes or no.

Count the numbers. Four weights and two biases into the first layer, four and two into the second, two and one into the output. Fifteen. That is the whole model, and every one of them is printed on the diagram below.

Click any edge to see its weight, or any neuron to see what it computes.

figure 3 · every weight in the modelclick an edge or a neuron
Switch between start and trained. Training changed all fifteen numbers and nothing else. The wiring never moved.
picture it

A mixing desk with fifteen faders and no other controls. Learning is somebody nudging faders, listening, and nudging again. Nothing is added, nothing is rewired, and at the end the desk looks identical to the one you started with apart from where the faders sit.

Those fifteen numbers start as guesses. To improve them you first have to find out how wrong they are, which means pushing a row all the way through.

Forward: one row walks through the network

Room seven again: 27 degrees, 65 percent, actually rated 8.3. Press play and watch the numbers travel. Each neuron waits for its inputs, multiplies, adds its bias, squashes, and passes the result on.

Nothing here is learned or clever. It is fifteen multiplications and some additions, in a fixed order.

figure 4 · the forward pass, step by stepready
Press send. The tokens carry the value on each edge. Watch h1 finish before h2 starts: a layer cannot compute until the one behind it has.
h1₁: 1.2×0.60 + (−0.8)×0.70 + 0.1 = 0.260  →  tanh  0.254
h1₂: −1.1×0.60 + 0.9×0.70 − 0.2 = −0.230  →  tanh  −0.226

h2₁: 1.0×0.254 + (−0.9)×(−0.226) + 0.0 = 0.458  →  0.428
h2₂: 0.7×0.254 + 1.1×(−0.226) + 0.1 = 0.029  →  0.029

out: 1.0×0.428 + (−1.0)×0.029 + 0.5 = 0.899  →  comfort 9.0
the room was actually rated 8.3, so the model is 0.7 too generous
picture it

A bucket chain at a fire. Nobody in the line knows where the water came from or where it is going; each person takes what arrives, does one thing to it, and hands it on. The answer at the end is the whole chain's doing, and no single link contains it.

The loss is one number for all ten rooms

Do that for every row, square each miss, take the average. This is the same mean squared error from any regression, and it is what "training" is trying to make small.

loss = 1/n × Σ (prediction − actual)²

room 7  (0.899 − 0.830)² = 0.0047
all ten, at the starting weights  →  0.3562
the best straight line manages  →  0.0232
this network after training  →  0.0031

The important thing about the loss is not the formula, it is what it depends on. Every one of those fifteen weights affects it. Change one and the loss changes. That makes the loss a function of fifteen numbers, and finding its lowest point is the entire job.

figure 5 · the loss as a function of one weightslide a weight
Drag the weight. Everything else is held still. The slope under the marker is the gradient for that one weight, and it is exactly what backpropagation computes for all fifteen at once.
picture it

Standing on a hillside in fog with fifteen dials, each of which tilts the ground a little. You cannot see the valley, but you can feel which way each dial makes the ground fall. Turn them all slightly downhill, then feel again. That is the whole of training.

Feeling all fifteen slopes without walking the hill fifteen times is what backpropagation is for.

Backward: the error walks the other way

The model said 0.899, the room was 0.830. That gap is the only thing the network has to learn from, and it starts at the output and moves left, splitting at every neuron.

At each step the question is the same: how much did this weight contribute to the error? A weight that fed a large signal into a big mistake gets a large share. A weight whose neuron was saturated gets almost nothing, because a flat curve passes no blame.

Press play. The dashed tokens carry blame backwards, and every weight lights up with the amount assigned to it.

figure 6 · backpropagation, one layer at a timeready
Play, then apply the update. Each weight moves against its own gradient, by an amount the learning rate decides. Fifteen tiny nudges, and the loss falls.
dL/d(out) = 2 × (0.899 − 0.830) = +0.138

output weights, straight away
dL/dW3₁ = 0.138 × h2₁ = 0.138 × 0.428 = +0.059
dL/dW3₂ = 0.138 × h2₂ = 0.138 × 0.029 = +0.004

push the blame back through the squash
δh2₁ = 0.138 × 1.0 × (1 − 0.428²) = +0.112
δh2₂ = 0.138 × (−1.0) × (1 − 0.029²) = −0.138

and again, one layer further back
δh1₁ = (0.112×1.0 + (−0.138)×0.7) × (1 − 0.254²) = +0.015
δh1₂ = (0.112×(−0.9) + (−0.138)×1.1) × (1 − 0.226²) = −0.240

then every weight is just delta times what came in
dL/dW1₁₁ = 0.015 × 0.60 = +0.009

W1₁₁ ← 1.2 − 0.5×0.009 = 1.1955
picture it

A project goes wrong and the blame is apportioned backwards down the chain of command. Everyone's share depends on how much they contributed and how much authority they had, and someone who was asleep at the time gets none. The derivative of the squash is exactly that "how awake was this neuron" factor.

Note what backpropagation is not: it is not searching, guessing, or trying weights to see what happens. It is one pass of the chain rule from calculus, and it produces all fifteen slopes for roughly the cost of one forward pass. That efficiency is the only reason any of this is practical.

Forward computes the answer. Backward computes who to blame for it.

One dial decides whether it learns, crawls, or explodes

Forward, backward, nudge, repeat. That loop is training, and it has exactly one setting that matters here: how far to move each weight along its slope.

The loop below is real. It runs the same fifteen weights, the same ten rooms, and the same arithmetic you just checked by hand. Set the rate and press train.

figure 7 · training, liveloss 0.3562 at step 0
Try 0.50, then 0.02, then 2.60. One learns, one crawls, one throws the weights so far that the neurons saturate and the loss stops moving at all.
rate 0.50   loss falls 0.356 → about 0.005 within 500 steps
rate 0.02   the same shape, roughly twenty times slower
rate 2.60   the first few steps overshoot, tanh saturates, and the gradient dies
picture it

Walking downhill in fog again. Tiny steps and you are still on the hillside at nightfall. Enormous steps and you leap clean across the valley to the opposite slope, then leap back. Nothing about the hill changed; only your stride.

Watch the loss curve rather than the number. A curve that falls fast and flattens is healthy. One that falls and then jitters sideways is a rate slightly too high. One that goes flat immediately at a bad value is saturation, and no amount of patience fixes it.

What the hidden units actually learned, and what this tiny model cannot tell you

After training, the four hidden neurons are not mysterious. Each one is a squashed tilt across the temperature and humidity plane, and the output is a weighted sum of those tilts. Bending happens where they overlap.

Click a hidden neuron to see the surface it responds to. Nobody designed these. They fell out of fifteen numbers being nudged downhill three hundred times.

figure 8 · what each hidden unit responds toclick a neuron
Step through the units. Each is a soft ramp in a different direction. The output is those ramps added up, which is how a stack of straight things makes a curved thing.
picture it

Making a curved shape out of stiff card by folding several flat pieces and overlapping them. No individual piece bends. The shape does. That is a hidden layer, and adding a second one lets you fold the folds.

Now the honest part. Ten rows and fifteen weights is close to one and a half parameters per observation, which is a ratio no serious model would accept. This network can very nearly memorise the table, and its 0.0031 loss on the same ten rooms it trained on is not evidence that it would work on the eleventh room.

Everything on this page is the mechanism, checked to the digit. None of it is a claim that the model is good. Establishing that would take a held-back set, and with ten rows there is nothing to hold back.

The arithmetic here is exact. The model is a toy. Those two statements are both true and people constantly confuse them.

The whole thing, in one paragraph

Fifteen numbers turn two inputs into one output by multiplying, adding and squashing. A loss says how wrong the answers are. The chain rule walks that wrongness backwards and hands each of the fifteen a share of the blame. Each moves a little against its share. Repeat three hundred times and a set of arbitrary numbers has become the shape of a comfortable room. Every model you have heard of is this, with more numbers.