All challenges
Easy 0 solved 0% acceptance

Categorical Cross-Entropy Loss

Measure the loss of a multi-class classifier from its predicted probabilities and the true classes.

What you'll learn

  • Score predicted probabilities against true classes
  • Average the loss over samples
  • Avoid log(0) with clipping

Problem

A multi-class classifier outputs one probability per class (for example from softmax). Categorical cross-entropy punishes it for giving the correct class a low probability:

loss = -(ln(p₁) + ln(p₂) + … + ln(pₙ)) / n

where pᵢ is the probability the model gave to the correct class of sample i. To avoid ln(0), first raise any probability below 0.0000001 to 0.0000001.

Implement categorical_cross_entropy(probabilities, labels).

Input

probabilities: One row per sample, with one probability per class.

labels: The index of the correct class for each sample (0-based).

Output

Return the average loss as a decimal number.

Constraints

1 ≤ samples ≤ 1,000, 2 ≤ classes ≤ 100

0 ≤ each probability ≤ 1

0 ≤ labels[i] < number of classes

Examples

Example 1
Input:
labels = [0, 1]
probabilities = [
    [0.7, 0.2, 0.1],
    [0.1, 0.8, 0.1]
]

Expected output:
expected = 0.289909
Input:
std::vector<long long> labels = {0, 1};
std::vector<std::vector<double>> probabilities = {
    {0.7, 0.2, 0.1},
    {0.1, 0.8, 0.1}
};

Expected output:
double expected = 0.289909;
Input:
long[] labels = new long[] {0, 1};
double[][] probabilities = new double[][] {
    new double[] {0.7, 0.2, 0.1},
    new double[] {0.1, 0.8, 0.1}
};

Expected output:
double expected = 0.289909;

Explanation

The correct classes got 0.7 and 0.8: -(ln(0.7) + ln(0.8)) / 2 = -(-0.356675 - 0.223144) / 2 ≈ 0.289909.

Example 2
Input:
labels = [1]
probabilities = [
    [1.0, 0.0]
]

Expected output:
expected = 16.118096
Input:
std::vector<long long> labels = {1};
std::vector<std::vector<double>> probabilities = {
    {1.0, 0.0}
};

Expected output:
double expected = 16.118096;
Input:
long[] labels = new long[] {1};
double[][] probabilities = new double[][] {
    new double[] {1.0, 0.0}
};

Expected output:
double expected = 16.118096;

Explanation

The correct class got probability 0, which is raised to 0.0000001, so the loss is -ln(0.0000001) ≈ 16.118096: a confident wrong answer is punished hard.

References

This challenge is adapted for CodeUtility. Follow the statement and constraints above.

Learn from others

Community solutions

No published solutions yet. Solve this challenge to share the first one.