Measuring Error: How Wrong is Our Model?
๐ง The Theory
AI/ML Concept: The Loss Function
In machine learning, the formula we use to measure error is called the Loss Function (or Cost Function).
An AI model does not have a brain. It does not understand what a house is, nor does it inherently know if a prediction makes sense. The only way an AI knows if it is doing a good job is by looking at the output of the Loss Function.
The entire goal of training a machine learning model is to adjust the weights and biases (which we built in Functions and Lines: Adding the Bias) so that the Loss Function returns a number as close to zero as possible.
Mean Squared Error (MSE) is the default loss function for regression tasks (predicting continuous numbers like prices, temperatures, or ages). Today, we give our engine the ability to realize when it has made a mistake.
๐The Math
Math: Calculating Squared Error
When we make a prediction, we need to mathematically quantify how wrong we are. We do this by calculating the difference between the actual truth () and our prediction (). This is called the residual or error: .
However, if we just add up all our errors across multiple predictions, a prediction that is too high () and a prediction that is too low () would cancel each other out to . This would falsely tell us our model is perfect!
To fix this, we square the error: .
Squaring does two critical things:
- It forces all errors to be positive (since a negative multiplied by a negative is a positive).
- It heavily penalizes large errors. Being off by 10 results in an error of 100, but being off by 20 results in an error of 400.
To find the average error across an entire dataset of predictions, we sum up all the squared errors and divide by . This formula is the Mean Squared Error (MSE):
โ๏ธThe Code
def mean_squared_error(actuals: list[float], predictions: list[float]) -> float:
"""Calculate the mean squared error between actual values and predictions."""
if len(actuals) != len(predictions):
raise ValueError("Actuals and predictions must have the same length.")
squared_errors = [(a - p) ** 2 for a, p in zip(actuals, predictions)]
return sum(squared_errors) / len(squared_errors)
# Example Usage: Evaluating our model on a dataset of 3 houses
# 1. Ground Truth (Actual selling prices in thousands)
actual_prices = [300.0, 450.0, 200.0]
# 2. Our Model's Guesses (Predictions in thousands based on weights/bias)
predicted_prices = [310.0, 430.0, 250.0]
# 3. Calculate how wrong the model was overall
mse_loss = mean_squared_error(actual_prices, predicted_prices)
print(f"Actual Prices: {actual_prices}")
print(f"Predicted Prices: {predicted_prices}")
print(f"Mean Squared Error: {mse_loss:.2f}")
# Note: An MSE of 1000.0 means the average squared error is 1000.
# To get the error back into the original units (thousands of dollars),
# we would take the square root of the MSE (Root Mean Squared Error).Code Breakdown
def mean_squared_error(actuals: list[float], predictions: list[float]) -> float: A standalone function that takes two lists of numbers representing the ground truth () and our model's outputs ().if len(actuals) != len(predictions):: We first check if the two lists have the same length. If not, we raise aValueErrorbecause we cannot compare values that don't correspond to each other.squared_errors = [(a - p) ** 2 for a, p in zip(actuals, predictions)]: This is a list comprehension that iterates through both lists simultaneously usingzip. For each pair of actual and predicted values, it calculates the difference, squares it, and adds it to thesquared_errorslist.return sum(squared_errors) / len(squared_errors): Finally, we calculate the mean by summing up all the squared errors and dividing by the total number of values. This gives us the average squared difference between our predictions and the actual values.