Loading content...
In machine learning classification tasks, evaluating model performance requires understanding how predictions align with actual labels across all classes. The Classification Outcome Matrix (commonly known as a confusion matrix) is a powerful diagnostic tool that provides a comprehensive breakdown of model predictions versus ground truth.
Given a set of true labels y_true and predicted labels y_pred, the classification outcome matrix is a square matrix of dimensions num_classes × num_classes where the entry at position (i, j) represents the number of samples that have true class label i but were predicted as class j.
Matrix Structure:
Normalization Modes: The matrix can be normalized in three different ways to reveal different insights:
Row-wise normalization (normalize='true'): Each row is divided by its sum, showing the recall distribution for each true class. This answers: "Of all samples that truly belong to class i, what proportion was predicted as each class?"
Column-wise normalization (normalize='pred'): Each column is divided by its sum, showing the precision distribution for each predicted class. This answers: "Of all samples predicted as class j, what proportion truly belongs to each class?"
Global normalization (normalize='all'): All entries are divided by the total number of samples, showing the overall distribution of outcomes across the entire dataset.
When normalization is applied, round the output values to the specified number of decimal places.
Your Task: Implement a function that constructs the classification outcome matrix with support for optional normalization. Handle edge cases appropriately, such as rows or columns with zero sums during normalization (these should remain as zeros).
y_true = [0, 1, 2, 2]
y_pred = [0, 2, 1, 2]
num_classes = 3
normalize = 'true'
round_decimals = 4[[1.0, 0.0, 0.0], [0.0, 0.0, 1.0], [0.0, 0.5, 0.5]]First, we build the raw count matrix:
• Class 0: 1 sample truly in class 0, correctly predicted as 0 → [1, 0, 0] • Class 1: 1 sample truly in class 1, incorrectly predicted as 2 → [0, 0, 1] • Class 2: 2 samples truly in class 2, one predicted as 1 and one as 2 → [0, 1, 1]
Raw matrix: [[1, 0, 0], [0, 0, 1], [0, 1, 1]]
With row-wise normalization (normalize='true'), each row is divided by its sum: • Row 0: [1, 0, 0] / 1 = [1.0, 0.0, 0.0] • Row 1: [0, 0, 1] / 1 = [0.0, 0.0, 1.0] • Row 2: [0, 1, 1] / 2 = [0.0, 0.5, 0.5]
The normalized matrix shows that class 2 samples have 50% recall with 50% misclassified as class 1.
y_true = [0, 0, 1, 1, 2, 2]
y_pred = [0, 1, 1, 0, 2, 2]
num_classes = 3
normalize = null
round_decimals = 4[[1, 1, 0], [1, 1, 0], [0, 0, 2]]Without normalization, we return the raw count matrix:
• Class 0: 2 true samples → 1 correctly predicted as 0, 1 misclassified as 1 • Class 1: 2 true samples → 1 correctly predicted as 1, 1 misclassified as 0 • Class 2: 2 true samples → both correctly predicted as 2
The diagonal shows [1, 1, 2] correct predictions, totaling 4 out of 6 (66.7% accuracy). The off-diagonal elements reveal symmetric confusion between classes 0 and 1.
y_true = [0, 0, 1, 1, 2, 2, 0, 1]
y_pred = [0, 0, 1, 2, 2, 1, 1, 1]
num_classes = 3
normalize = 'pred'
round_decimals = 4[[1.0, 0.25, 0.0], [0.0, 0.5, 0.5], [0.0, 0.25, 0.5]]First, we build the raw count matrix:
• Row counts: [[2, 1, 0], [0, 2, 1], [0, 1, 1]]
Column sums: [2, 4, 2] (samples predicted as each class)
With column-wise normalization (normalize='pred'), each column is divided by its sum: • Column 0: [2, 0, 0] / 2 = [1.0, 0.0, 0.0] • Column 1: [1, 2, 1] / 4 = [0.25, 0.5, 0.25] • Column 2: [0, 1, 1] / 2 = [0.0, 0.5, 0.5]
This reveals precision insights: predictions of class 0 are 100% precise, while predictions of class 1 are only 50% precise with 25% actually belonging to each of classes 0 and 2.
Constraints