Task 3 of 5
The whole algorithm, now: stand somewhere, ask which way is up, move the other way, repeat.
m ← m − η · ∂L/∂m
c ← c − η · ∂L/∂c
η is the learning rate — how far you move per step. Both kernels below are already written (task 1's loss, task 2's gradient), and the driving loop lives in JavaScript, exactly as the halving ladder's driver does: the arithmetic that touches all 4,096 points stays on the GPU, and the two numbers that say where you are stay on the host.
Sixty steps at η = 0.1 from (0, 0) land on
(3, 4) to five decimal places, and the loss falls
25.5 → 0.79 → 0.503 → 0.5 along the way. Watch where it stops:
0.5, not zero. The scatter in this data is real, and no straight line
can explain it away — the optimum is where the loss stops falling, not where it
vanishes.
m and
c one step downhill, and land on y = 3x + 4 with a final loss
of 0.5.rate: m = m - rate * g[0]gradientAt() is async — await it, and use the averaged gradient it returns, not a raw sum3 and 4The gradient points in the direction the loss increases fastest.
At (0, 0) it is (−6, −8), so downhill is
(+6, +8), and m − 0.1·(−6) = 0.6 is the first step. That
minus sign is the whole difference between fitting and exploding.
m = m - rate * g[0];
c = c - rate * g[1];
Both parameters move on the same gradient — the one measured before either of them changed.
This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.