MediumLoss Functions

Implement Cross-Entropy Loss

Loss Functions

Medium

Problem

Compute the mean multiclass cross-entropy loss from correct class labels and predicted class probabilities. For sample i, select the probability assigned to its correct class:

L_i = -\log(p_{i,y_i})

Average the sample losses:

L = -\frac{1}{N} \sum_{i=1}^{N} \log(p_{i,y_i})

Here, N is the number of samples, y_i is the correct class index for sample i, and p_{i,y_i} is the predicted probability of that class. Use the natural logarithm and return the mean loss as a Python float.

Theory

Cross-entropy loss (also called log loss or softmax loss) is the standard loss function for classification problems. It measures how different the predicted probability distribution is from the true distribution.

For multi-class classification with C classes:

\text{CE} = -\sum_{c=1}^{C} y_c \log(\hat{y}_c)

Where:


Simplification for One-Hot Labels

When the true label is one-hot encoded, only one term in the sum is non-zero:

\text{CE} = -\log(\hat{y}_{\text{true class}})

This is equivalent to: "negative log of the predicted probability for the correct class."

Examples:

The more confident the model is in the correct class, the lower the loss.


Understanding the Negative Log

Why negative logarithm? Let us trace through the reasoning:

Step 1: We want high probability for the true class

Step 2: Log gives us this behavior

Step 3: Negate to make it a loss

The loss grows without bound as the predicted probability for the true class approaches zero.


The Loss Curve

For a single sample where the true class is c, the loss as a function of predicted probability:

Predicted probability 0.99: loss = 0.010 Predicted probability 0.90: loss = 0.105 Predicted probability 0.70: loss = 0.357 Predicted probability 0.50: loss = 0.693 Predicted probability 0.30: loss = 1.204 Predicted probability 0.10: loss = 2.303 Predicted probability 0.01: loss = 4.605

Key observations:


The Gradient

The gradient of cross-entropy with respect to the logits (before softmax) has a remarkably simple form:

\frac{\partial \text{CE}}{\partial z_c} = \hat{y}_c - y_c

Where z_c is the logit for class c.

What this means:

The gradient is exactly the difference between predicted and true probabilities. This simplicity is one reason cross-entropy works so well with softmax.


Cross-Entropy and Information Theory

Cross-entropy comes from information theory. Given two probability distributions p (true) and q (predicted):

H(p, q) = -\sum_x p(x) \log q(x)

This measures the average number of bits needed to encode samples from p using a code optimized for q.

Minimizing cross-entropy is equivalent to minimizing KL divergence from the true distribution.


Binary Cross-Entropy

For binary classification (2 classes), the formula simplifies:

\text{BCE} = -[y \log(\hat{y}) + (1 - y) \log(1 - \hat{y})]

Where:

This is equivalent to:

Binary cross-entropy is used with sigmoid output, while multi-class cross-entropy is used with softmax output.


Numerical Stability

Computing log(predicted) directly is dangerous:

Solutions:


Where Cross-Entropy Is Used

Cross-entropy is the default loss for classification because:

Examples

Example 1

Input
y_true = [0, 1], y_pred = [[0.9, 0.1], [0.3, 0.7]]
Output
0.231018
Explanation
The selected probabilities are 0.9 and 0.7, and the output is the mean of their negative logarithms.

Example 2

Input
y_true = [2], y_pred = [[0.1, 0.1, 0.8]]
Output
0.223144

Example 3

Input
y_true = [1, 0, 1], y_pred = [[0.2, 0.8], [0.6, 0.4], [0.49, 0.51]]
Output
0.469105

Hints

  1. np.arange(len(y_true)) provides the row indices for advanced indexing.
  2. y_pred[row_indices, y_true] selects one correct-class probability per sample.
  3. Use np.log() followed by np.mean() for the final reduction.

Requirements

Constraints

Starter Code

import numpy as np

def cross_entropy_loss(y_true: list[int], y_pred: list[list[float]]) -> float:
    """
    Returns the mean multiclass cross-entropy loss as a Python float.
    """
    # Write code here
    pass

Test Cases

CaseMatches
Two samples binarypublic
Single sample 3-classpublic
Three samples binarypublic