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
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.
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.
How to approach it
Try on your own first, then open one hint at a time.
Hint 1
Look up the probability assigned to each sample’s correct class, then average the negative logs of those values.
Hint 2
Clamp very small probabilities upward before taking logs to avoid undefined results.
Hint 3
Only the labeled class matters for each row, so ignore the other class probabilities when computing the loss.
Expected complexity
O(samples) time, O(1) extra space
References
This challenge is adapted for CodeUtility. Follow the statement and constraints above.