Try this first
You now have everything needed to write the function. Residuals, squaring, and a way to loop over data.
Write loss(m, b, data) yourself before reading on. It should return one number, bigger when the line fits worse. Then compare your version to the one below.
Mean squared error
function loss(m, b, data) {
let total = 0;
for (const r of data) {
const e = r.y - predict(m, b, r.x[0]);
total += e * e;
}
return total / data.length;
}
Four steps, one per line. Predict. Subtract to get the residual. Square it and add it to a running total. Divide by how many points there were.
This is mean squared error, and you will see it written MSE everywhere. It is the most used loss function for predicting numbers, and it is exactly the four steps above.
Why divide at the end
The division is the one part people skip, and it costs nothing to keep. Without it, the same line scores 190 on eight points and 1900 on eighty points drawn from the same source. The fit did not get ten times worse. You just added more terms to a sum.
Dividing by the count gives you the average squared error per point, which stays roughly the same as the dataset grows. That makes the number comparable across datasets, and it keeps the value in a range where you can reason about it.
Try it on the three candidates
log("red ", loss(8, 24, study).toFixed(2));
log("blue ", loss(7.5, 27, study).toFixed(2));
log("green", loss(9, 20, study).toFixed(2));
const flat = study.reduce((s, r) => s + r.y, 0) / study.length;
log("flat ", loss(0, flat, study).toFixed(2));
The three candidate lines score close to each other, which matches the picture. They all looked reasonable.
The fourth line is the baseline from lesson 2: slope zero, always guessing the average score. Its loss is far higher. That gap is what the model actually earns by paying attention to study time, and it is the only honest way to say a model is any good. Beating nothing is not an achievement. Beating the average is the minimum bar.
Reading the number
Suppose the red line scores 24.4. That is in marks squared. Take the square root and you get about 4.9, which means the line is typically about five marks off. That version is called root mean squared error, and it is the one to quote to a person, because it is in the same units as the thing you predicted.
What to watch
The loss depends on the data as well as the line, so a loss of 24 means nothing on its own. Two models are only comparable through their losses if they were measured on the same rows. Comparing your training loss against someone else’s test loss is a mistake that gets made constantly, and section 9 is largely about avoiding it.
Also note what loss is, viewed as a function. Hand it a line, get back a number. It does not care where the line came from. That is what makes searching possible: we can now generate candidate lines by any method at all and rank them, without any judgment involved.
Exercises
- Write
rmseas a one line wrapper aroundlossand print it for all four lines above. - Duplicate every row in
studyso there are sixteen points instead of eight. Confirm the loss stays the same, and explain which line of the function guarantees it. - Hold
bat 24 and print the loss formfrom 5 to 11 in steps of 0.5. Which value wins? Write the numbers down, you will need them next lesson. - Now do the same for
bfrom 15 to 35 withmfixed at 8. Both searches worked. Explain why searching both at once, in the same way, gets expensive fast.