Deep Learning πŸ“‚ Artificial Neural Networks (ANN) Β· 4 of 7 28 min read

Loss Functions & Optimisation Objectives in Machine Learning

A comprehensive, story-driven guide to the four essential loss functions β€” MSE, binary cross-entropy, categorical cross-entropy, and regularised loss (L1/L2). Covers probabilistic derivations via Maximum Likelihood Estimation, two worked numerical examples (rent prediction + spam classification), interactive canvas diagrams, complete Python code with scikit-learn, and golden rules for choosing the right loss in practice.

Section 01

The Story That Explains Loss Functions

The Archery Coach and the Scoreboard
Imagine an archery coach watching a student shoot at a target. After each arrow, the coach doesn't just say "good" or "bad" β€” she measures the exact distance from the bullseye. That distance is the loss.

If the arrow lands 2 cm away, she says "adjust your grip a little." If it lands 40 cm away, she says "stop, we need to completely rethink your stance." The magnitude of the error dictates the magnitude of the correction.

A machine learning model does exactly this. After every prediction it makes, the loss function measures how far off it was. The optimiser then nudges the model's parameters in whatever direction reduces that distance. Repeat millions of times. That is training.

A loss function (also called a cost function or objective function) is a mathematical formula that takes the model's prediction Ε· and the true label y, and returns a single non-negative number representing how wrong the prediction is. The model's entire goal during training is to minimise this number.

💡
Loss vs Cost vs Objective

Loss is computed on a single example. Cost (or empirical risk) is the average loss over the entire dataset. Objective is what you actually optimise β€” usually cost plus a regularisation penalty. The three terms are often used interchangeably in practice, but the distinction matters when reading research papers.


Section 02

Mean Squared Error β€” The Regression Workhorse

The Estate Agent's Mistake
An estate agent predicts house prices. On Monday she predicts Β£200,000 for a house that sells for Β£210,000 β€” a Β£10,000 miss. On Friday she predicts Β£200,000 for a house that sells for Β£230,000 β€” a Β£30,000 miss.

If we simply averaged the raw errors, a model that over-predicts by Β£20,000 and under-predicts by Β£20,000 would look perfect β€” they cancel out. That's useless. So instead we square each error before averaging. Squaring does two things: eliminates negative signs, and punishes large errors disproportionately (the Β£30,000 miss hurts 9Γ— more than the Β£10,000 miss, not just 3Γ—).

The Formula

Single-Sample Loss
L(y, Ε·) = (y βˆ’ Ε·)Β²
Square the difference between the true value y and prediction Ε·.
MSE over n Samples
MSE = (1/n) Ξ£ (yα΅’ βˆ’ Ε·α΅’)Β²
Average squared error over the entire training set.
📐
Probabilistic Derivation β€” Why MSE is "Correct"

MSE is not an arbitrary choice. It falls directly out of Maximum Likelihood Estimation (MLE) when you assume the residuals follow a Gaussian distribution: y = f(x) + Ξ΅, where Ξ΅ ~ N(0, σ²). Maximising the log-likelihood of a Gaussian is exactly equivalent to minimising the sum of squared errors. This gives MSE a deep statistical justification β€” it's optimal when your noise really is Gaussian.

🔨 Numerical Example 1 β€” MSE Step by Step

A model predicts apartment rents (Β£/month) for five flats. Let's compute the MSE manually.

Flat True Rent (y) Predicted Rent (Ε·) Error (y βˆ’ Ε·) Squared Error (y βˆ’ Ε·)Β²
AΒ£1,200Β£1,150+502,500
BΒ£850Β£900βˆ’502,500
CΒ£2,000Β£1,700+30090,000
DΒ£950Β£940+10100
EΒ£1,500Β£1,520βˆ’20400
🧮 MSE Calculation
Step 1
Sum the squared errors: 2,500 + 2,500 + 90,000 + 100 + 400 = 95,500
Step 2
Divide by n = 5: MSE = 95,500 / 5 = 19,100
Step 3
RMSE (more interpretable): √19,100 β‰ˆ Β£138.2 β€” the model is off by roughly Β£138 on average.
Note
Flat C's Β£300 error contributes 90,000 β€” over 94% of the total squared error. MSE is very sensitive to outliers.
📈 MSE Parabola β€” Why the Loss Surface is Bowl-Shaped

The loss surface for MSE is a smooth, convex parabola. Any gradient descent algorithm is guaranteed to find the global minimum β€” there are no local traps.

When to Use MSE

House Price Prediction
USE MSE
Continuous target, roughly Gaussian errors, large errors warrant heavier penalty.
Temperature Forecasting
USE MSE
Symmetric errors expected, physics-based noise is Gaussian.
Median Income (Outliers)
USE MAE
MSE gets dominated by billionaire outliers. MAE or Huber loss is more robust.

Section 03

Binary Cross-Entropy β€” The Classification Standard

The Overconfident Doctor
A doctor reviews an X-ray and says: "I am 99% sure this patient has no tumour." The patient actually has a tumour. How wrong is the doctor?

If we used MSE: (1 βˆ’ 0.01)Β² = 0.98 β€” sounds manageable. But intuitively, a doctor being 99% wrong on a cancer diagnosis is catastrophically wrong. That confidence should be punished severely.

Cross-entropy agrees: βˆ’log(0.01) β‰ˆ 4.6 β€” a very large penalty. For the same patient, a doctor who said "50% chance" gets βˆ’log(0.50) β‰ˆ 0.69 β€” still penalised, but fairly. Cross-entropy punishes confident wrong answers brutally while barely scolding humble uncertainty.

The Formula

Binary Cross-Entropy (per sample)
L = βˆ’[yΒ·log(Ε·) + (1βˆ’y)Β·log(1βˆ’Ε·)]
y ∈ {0, 1}, ŷ ∈ (0, 1) is the predicted probability. Only one term is "active" for each label.
Categorical Cross-Entropy (K classes)
L = βˆ’Ξ£β‚– yβ‚– Β· log(Ε·β‚–)
yβ‚– is 1 for the true class, 0 otherwise (one-hot). Ε·β‚– is the softmax probability for class k.
🌱
Probabilistic Derivation β€” Cross-Entropy from MLE

Assume labels follow a Bernoulli distribution: P(y|x) = Ε·y(1βˆ’Ε·)1βˆ’y. Taking the log-likelihood of n samples and flipping the sign (to minimise) gives exactly the binary cross-entropy formula. Minimising cross-entropy = maximising the likelihood that the model's predicted probabilities generated the observed labels. No arbitrary choice β€” it drops out of pure probability theory.

🔨 Numerical Example 2 β€” Cross-Entropy Step by Step

A spam classifier assigns probabilities to 4 emails. We compute the binary cross-entropy for each and then the average cost.

Email True Label (y) P(spam) = Ε· Active Term Loss = βˆ’log(active prob)
E1 β€” Spam SPAM (1) 0.90 βˆ’log(0.90) 0.105 βœ“ Low
E2 β€” Not Spam HAM (0) 0.05 βˆ’log(1 βˆ’ 0.05) = βˆ’log(0.95) 0.051 βœ“ Very Low
E3 β€” Spam SPAM (1) 0.10 βˆ’log(0.10) 2.303 βœ— High Penalty
E4 β€” Not Spam HAM (0) 0.60 βˆ’log(1 βˆ’ 0.60) = βˆ’log(0.40) 0.916 ⚠ Moderate
🧮 Average Cross-Entropy (Cost)
Sum
0.105 + 0.051 + 2.303 + 0.916 = 3.375
Average
Cost = 3.375 / 4 = 0.844
Key Insight
Email E3 alone contributes 2.303 of 3.375 (68%) of the total cost β€” the model was 90% confident it was ham, but it was spam. Cross-entropy demands this be fixed urgently.
📈 Cross-Entropy Curve β€” The Asymptotic Penalty

As the predicted probability of the true class approaches 0, the loss approaches infinity. This is why neural networks never output exactly 0 or 1 β€” the gradient would be undefined.


Section 04

Maximum Likelihood Estimation β€” The Unifying View

You may wonder why MSE and cross-entropy look so different, yet both "work." The answer is that they are both instances of the same principle: Maximum Likelihood Estimation.

Fitting a Key to a Lock
You have a lock (the data) and need to find the best key (model parameters ΞΈ). MLE says: "Choose the key that makes the data you observed as probable as possible." Formally, you maximise P(data | ΞΈ) β€” the likelihood of observing your training data given a particular set of parameters. Since products of tiny probabilities underflow numerically, we take the log and maximise the sum. Flipping the sign (to minimise) gives the negative log-likelihood β€” which is your loss function.
Assumed Noise Distribution Likelihood P(y|x,ΞΈ) βˆ’log Likelihood = Resulting Loss
Gaussian (Normal) N(Ε·, σ²) Ξ£ (yα΅’ βˆ’ Ε·α΅’)Β² / 2σ² MSE
Bernoulli (binary) Ε·ΚΈ(1βˆ’Ε·)¹⁻ʸ βˆ’Ξ£ [y log Ε· + (1βˆ’y)log(1βˆ’Ε·)] Binary Cross-Entropy
Categorical (K classes) Ξ  ŷₖʸᡏ βˆ’Ξ£ yβ‚– log Ε·β‚– Categorical Cross-Entropy
Laplacian exp(βˆ’|yβˆ’Ε·|/b) Ξ£ |yα΅’ βˆ’ Ε·α΅’| MAE (L1 Loss)
🎉
The Beautiful Unification

Every major loss function is the negative log-likelihood under some probability distribution. Choosing a loss function is therefore equivalent to choosing a probabilistic model for your noise. This is why the choice matters: if your data has Gaussian noise, MSE is principled. If it has heavy-tailed noise, you need Huber or MAE. The loss function encodes your assumptions about the world.


Section 05

Regularised Loss β€” L1 and L2 Penalties

A model that perfectly minimises training loss often overfits β€” it memorises the training data including noise, and fails on new examples. Regularisation adds a penalty term to the objective that discourages the model from growing too complex.

L2 Regularisation (Ridge)
J(θ) = Loss + λ·Σ θᡒ²
Penalises the sum of squared weights. Pushes all weights toward zero smoothly. Never exactly zero.
L1 Regularisation (Lasso)
J(θ) = Loss + λ·Σ |θᡒ|
Penalises the sum of absolute weights. Creates sparse solutions β€” some weights become exactly zero (feature selection).
The Bureaucrat and the Sculptor
L2 (Ridge) is like a bureaucrat who tells every employee: "You can work, but the harder you work the more tax you pay β€” so everyone naturally works a bit less." All employees stay employed, but none are working at full capacity. Weights are all small but non-zero.

L1 (Lasso) is like a sculptor with a chisel. Instead of just penalising effort, the sculptor actively carves away anything unnecessary. After training, many weights are exactly zero β€” the model has selected a sparse subset of features. Ideal when you suspect most features are irrelevant.
Property L1 (Lasso) L2 (Ridge) Elastic Net (L1+L2)
Sparsity (zero weights) Yes β€” exact zeros No β€” only shrinks Partial
Feature Selection Built-in Not built-in Partial
Correlated Features Picks one, drops rest Spreads weight across all Handles well
Gradient at zero Undefined (subgradient) Smooth and differentiable Mixed
Best Use Case Many irrelevant features All features somewhat relevant Correlated feature groups
⚠️
Tuning Ξ» β€” The Regularisation Strength

Ξ» = 0: No regularisation β€” pure loss minimisation, maximum overfitting risk.
Ξ» β†’ ∞: All weights crushed to zero β€” maximum underfitting (the model predicts the mean always).
The optimal Ξ» lives between these extremes and is found via cross-validation, not guessing. In sklearn, this is the alpha parameter.


Section 06

Gradient Descent β€” How the Optimiser Actually Learns

Knowing what to minimise is only half the story. The optimiser is the algorithm that actually adjusts the model's weights to reduce the loss. The most fundamental optimiser is gradient descent.

01
Forward Pass
Feed a mini-batch of training examples through the model. Compute predictions Ε· using current weights ΞΈ.
02
Compute Loss
Apply the chosen loss function to compare Ε· against y. Get a single scalar: the current cost.
03
Backward Pass (Backpropagation)
Compute βˆ‚Loss/βˆ‚ΞΈ for every weight using the chain rule. This gives the direction of steepest ascent for each weight.
04
Parameter Update
Nudge every weight in the opposite direction: ΞΈ ← ΞΈ βˆ’ Ξ· Β· βˆ‚Loss/βˆ‚ΞΈ, where Ξ· is the learning rate.
05
Repeat Until Convergence
After enough iterations, weights settle at values that minimise the loss. That is your trained model.
🔄
Why MSE and Cross-Entropy Have Beautiful Gradients

For MSE: βˆ‚MSE/βˆ‚Ε· = βˆ’2(y βˆ’ Ε·) β€” linear in the error. Simple and stable.
For cross-entropy + sigmoid/softmax: the gradient simplifies to Ε· βˆ’ y β€” the prediction error itself. This clean form is not a coincidence; it's another reason MLE-derived losses are preferred. The math works out perfectly.


Section 07

Python Implementation β€” Full Working Code

Below is a complete example computing MSE, binary cross-entropy, and regularised loss from scratch in NumPy, then training a logistic regression model with both L1 and L2 regularisation using scikit-learn.

Part A β€” Loss Functions from Scratch

import numpy as np

# ── Mean Squared Error ──────────────────────────────────
def mse(y_true, y_pred):
    return np.mean((y_true - y_pred) ** 2)

# ── Root Mean Squared Error ─────────────────────────────
def rmse(y_true, y_pred):
    return np.sqrt(mse(y_true, y_pred))

# ── Binary Cross-Entropy ────────────────────────────────
def binary_cross_entropy(y_true, y_pred):
    eps = 1e-15  # prevent log(0)
    y_pred = np.clip(y_pred, eps, 1 - eps)
    return -np.mean(
        y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred)
    )

# ── Regularised MSE ─────────────────────────────────────
def regularised_mse(y_true, y_pred, weights, lam=0.01, mode='l2'):
    loss = mse(y_true, y_pred)
    if mode == 'l2':
        penalty = lam * np.sum(weights ** 2)
    elif mode == 'l1':
        penalty = lam * np.sum(np.abs(weights))
    else:
        penalty = 0
    return loss + penalty

# ── Demo ─────────────────────────────────────────────────
y_true_reg  = np.array([1200, 850, 2000, 950, 1500])
y_pred_reg  = np.array([1150, 900, 1700, 940, 1520])
weights     = np.array([0.5, -0.3, 1.2, 0.8])

print(f"MSE:         {mse(y_true_reg, y_pred_reg):,.1f}")
print(f"RMSE:        Β£{rmse(y_true_reg, y_pred_reg):.1f}")

y_true_cls = np.array([1, 0, 1, 0])
y_pred_cls = np.array([0.90, 0.05, 0.10, 0.60])
print(f"BCE:         {binary_cross_entropy(y_true_cls, y_pred_cls):.4f}")
print(f"Reg MSE L2:  {regularised_mse(y_true_reg, y_pred_reg, weights, 0.01, 'l2'):,.2f}")
print(f"Reg MSE L1:  {regularised_mse(y_true_reg, y_pred_reg, weights, 0.01, 'l1'):,.2f}")
OUTPUT
MSE: 19,100.0 RMSE: Β£138.2 BCE: 0.8438 Reg MSE L2: 19,100.03 Reg MSE L1: 19,100.03

Part B β€” Scikit-learn: L1 vs L2 on Breast Cancer Dataset

from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import log_loss, accuracy_score
import numpy as np

# Load data
data = load_breast_cancer()
X, y = data.data, data.target

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test  = scaler.transform(X_test)

# L2 Regularised Logistic Regression (default)
lr_l2 = LogisticRegression(penalty='l2', C=1.0, max_iter=1000)
lr_l2.fit(X_train, y_train)

# L1 Regularised Logistic Regression
lr_l1 = LogisticRegression(penalty='l1', C=1.0, solver='liblinear')
lr_l1.fit(X_train, y_train)

for name, model in [('L2 Ridge', lr_l2), ('L1 Lasso', lr_l1)]:
    probs = model.predict_proba(X_test)
    acc   = accuracy_score(y_test, model.predict(X_test))
    bce   = log_loss(y_test, probs)
    zeros = np.sum(model.coef_ == 0)
    print(f"{name} | Accuracy: {acc:.4f} | BCE Loss: {bce:.4f} | Zero weights: {zeros}/30")
OUTPUT
L2 Ridge | Accuracy: 0.9737 | BCE Loss: 0.0791 | Zero weights: 0/30 L1 Lasso | Accuracy: 0.9649 | BCE Loss: 0.1022 | Zero weights: 12/30
🔍
Reading the Output

L2 (Ridge) achieves slightly higher accuracy because it uses all 30 features simultaneously β€” none are discarded. L1 (Lasso) zeroed out 12 of 30 features, trading a little accuracy for a far simpler, more interpretable model. In a clinical setting where explaining which features drive the diagnosis matters, L1's 18-feature model might be the better choice despite the lower accuracy.


Section 08

Quick Reference β€” Choosing Your Loss Function

📈
Regression, Gaussian Noise
β†’ Use MSE / RMSE
sklearn: LinearRegression
keras: loss='mse'
👑
Regression, Outlier-Robust
β†’ Use MAE or Huber
sklearn: HuberRegressor
keras: loss='huber'
🚨
Binary Classification
β†’ Use Binary Cross-Entropy
sklearn: LogisticRegression
keras: loss='binary_crossentropy'
🌎
Multi-class (mutually exclusive)
β†’ Categorical Cross-Entropy
sklearn: softmax output
keras: loss='sparse_categorical_crossentropy'
📋
Overfitting β€” Many Features
β†’ Add L1 penalty (Lasso)
sklearn: penalty='l1'
keras: regularizers.l1(Ξ»)
🔧
Overfitting β€” Correlated Features
β†’ Add L2 penalty (Ridge)
sklearn: penalty='l2'
keras: regularizers.l2(Ξ»)

Section 09

Golden Rules

⚡ Loss Functions & Optimisation β€” Non-Negotiable Rules
1
Never use MSE for classification. MSE assumes a linear, continuous output. Applied to probabilities (0–1), its gradient behaves badly near the extremes and the loss surface develops flat regions that stall training.
2
Clip predictions before computing log-based losses. log(0) is undefined (βˆ’βˆž). Always clip predicted probabilities to [Ξ΅, 1βˆ’Ξ΅] where Ξ΅ = 1e-15 before calling any cross-entropy function.
3
MSE is sensitive to outliers β€” check your target distribution first. If your target has heavy tails or occasional extreme values, a single outlier can dominate the entire loss. Use Huber loss or log-transform the target.
4
Tune Ξ» with cross-validation β€” never by intuition. The regularisation strength is a hyperparameter. Use GridSearchCV or RidgeCV/LassoCV which have efficient built-in cross-validation over a range of Ξ» values.
5
The loss function and the evaluation metric need not be the same. You might train with cross-entropy but evaluate with F1 score or AUC-ROC. The loss must be differentiable (for gradient descent); the metric just needs to measure what you care about in production.
6
Cross-entropy implicitly assumes calibrated probabilities. If your model is poorly calibrated (confident and wrong), cross-entropy will be very high. Consider using CalibratedClassifierCV in sklearn to post-hoc calibrate your model's output probabilities.