Login to unlock
Deep Learning · Phase 2: Forward & Backward Propagation · Loss Functions for Deep Networks

Loss Functions for Deep Networks

Lesson 1 of 2 5 min read
Back to course

What you will learn in this lesson:

  • How softmax converts raw output scores into a probability distribution
  • Why cross-entropy loss is the standard pairing for a softmax output, and how their gradients combine
  • Why mean squared error remains the default for regression outputs
  • Why the choice of loss function is really a choice about gradient behavior, not just "what number to report"

Softmax: Turning Scores Into Probabilities

A multi-class classification network's final layer typically outputs one raw score (called a logit) per class, with no activation applied. These logits can be any real number, positive or negative, and don't sum to anything meaningful on their own. Softmax converts them into a valid probability distribution:

Softmax

softmax(z)_i = e^(z_i) / Σ_j e^(z_j)

Exponentiating makes every value positive; dividing by the sum makes everything sum to exactly 1. Larger logits get larger probabilities, and the relative gaps between logits are preserved (exponentially amplified, in fact) in the resulting probabilities.

import numpy as np

def softmax(z):
    z_shifted = z - np.max(z)  # numerical stability trick, explained below
    exp_z = np.exp(z_shifted)
    return exp_z / np.sum(exp_z)

logits = np.array([2.0, 1.0, 0.1])
probs = softmax(logits)
print("Logits:        ", logits)
print("Probabilities: ", np.round(probs, 4))
print("Sum of probs:  ", round(float(np.sum(probs)), 6))

Subtracting the maximum logit before exponentiating doesn't change the result mathematically (it cancels out in the division), but it prevents np.exp from overflowing on large logits, a standard numerical-stability trick worth keeping in any softmax implementation.


Cross-Entropy: Measuring How Wrong a Probability Distribution Is

Once a network outputs a probability distribution over classes, cross-entropy measures how far that distribution is from the true label. For a single example with true class index c:

Cross-entropy loss

L = −log(p_c)    (the predicted probability assigned to the correct class)

If the model assigns the correct class a probability close to 1, −log(p_c) is close to 0: low loss. If the model assigns the correct class a probability close to 0, −log(p_c) blows up toward infinity: a severe penalty for confidently wrong predictions.

import numpy as np

def cross_entropy(probs, true_class_idx):
    return -np.log(probs[true_class_idx] + 1e-12)  # epsilon avoids log(0)

# Same true class (index 0), three different predicted distributions
confident_correct = np.array([0.97, 0.02, 0.01])
unsure = np.array([0.4, 0.35, 0.25])
confident_wrong = np.array([0.02, 0.9, 0.08])

print("Confident & correct loss:", round(cross_entropy(confident_correct, 0), 4))
print("Unsure loss:              ", round(cross_entropy(unsure, 0), 4))
print("Confident & wrong loss:   ", round(cross_entropy(confident_wrong, 0), 4))

The confident-and-wrong case produces by far the largest loss, exactly the behavior you want: the network should be punished hardest for being both wrong and overconfident about it.

Why Softmax + Cross-Entropy Is a Particularly Good Pairing

The reason this combination is the default for classification isn't just convention. When you work out ∂L/∂z (the gradient of cross-entropy loss with respect to the pre-softmax logits), the exponentials and logarithms cancel in a remarkably clean way:

The combined softmax + cross-entropy gradient

∂L/∂z = p − y    (predicted probabilities minus the one-hot true label)

That's it: predicted minus actual, elementwise. This gradient never saturates the way it would if you ran mean squared error through a sigmoid or softmax output. A confidently wrong prediction (predicted probability near 0 for the correct class) produces a gradient near 1 in magnitude, exactly when you want the strongest push to correct the network. This is the concrete answer to "why cross-entropy and not MSE for classification": MSE through a saturating output can produce a tiny gradient exactly in the cases where you most need a large corrective signal.

import numpy as np

def softmax(z):
    z = z - np.max(z)
    e = np.exp(z)
    return e / np.sum(e)

# A confidently wrong prediction: true class is 0, but the model favors class 1
logits = np.array([-3.0, 4.0, -1.0])
probs = softmax(logits)
y_true = np.array([1, 0, 0])  # one-hot for class 0

grad = probs - y_true
print("Predicted probabilities:", np.round(probs, 4))
print("Gradient (p - y):       ", np.round(grad, 4))

The gradient on the true class's logit is strongly negative (push it up), which is exactly the large, unsaturated correction signal the network needs when it's this wrong.


Mean Squared Error: The Default for Regression

For predicting a continuous value rather than a class, mean squared error remains the standard choice:

Mean squared error

L = (ŷ − y)^2    (per example; averaged across a batch)

∂L/∂ŷ = 2(ŷ − y)

Its gradient is proportional to the size of the error: a prediction that's off by 10 produces a gradient ten times larger than a prediction off by 1. This naturally focuses learning on the examples where the model is currently most wrong, and it has no saturation issue analogous to sigmoid/softmax because, for a regression output, there's typically no bounding activation function applied at all, the network's final layer is just a raw linear combination.


Choosing a Loss Is Choosing Gradient Behavior

The throughline of this lesson: a loss function isn't merely a scorecard you check after training finishes. It's the function backpropagation differentiates first, and its gradient is the very first link in the chain rule that flows through every layer of the network. Two losses that rank model quality identically can still produce wildly different training dynamics if their gradients behave differently near the extremes, which is exactly the practical reason cross-entropy, not accuracy and not MSE, is the default for classification.

Key takeaway

Softmax converts raw logits into a probability distribution; cross-entropy measures how far that distribution is from the true label, with loss exploding as confidence in the wrong answer increases. Combined, their gradient simplifies to predicted − actual, a clean signal that doesn't vanish even for confidently wrong predictions. Mean squared error remains the default for regression, where its gradient's proportionality to the error size is exactly the desired behavior.

⌘/Ctrl + Enter to send

AI-generated feedback, graded against this lesson — it can occasionally be wrong. The lesson above is the source of truth.

Found this useful?

Finished this lesson?

Mark it complete to update your Phase 2: Forward & Backward Propagation progress.