MediumMetrics & Evaluation

Compute Accuracy, Precision, Recall, F1

Metrics & Evaluation

Medium

Problem

Compute accuracy, precision, recall, and F1 for single-label classification. For each class c, let TP_c count correct predictions of c, FP_c count predictions of c whose true label differs, and FN_c count occurrences of c predicted as another class.

P_c = \frac{TP_c}{TP_c + FP_c}

R_c = \frac{TP_c}{TP_c + FN_c}

F_{1,c} = \frac{2P_cR_c}{P_c + R_c}

Use micro to aggregate class counts before computing metrics, macro to average class metrics equally, weighted to average them by true-label support, and binary to report the class selected by pos_label. A zero denominator contributes 0.0. Return accuracy, precision, recall, and f1 in a dictionary, with every value rounded to six decimals.

Theory

All classification metrics derive from the confusion matrix, which counts predictions vs. actual labels.

For binary classification:

True Positive (TP): Predicted positive, actually positive

True Negative (TN): Predicted negative, actually negative

False Positive (FP): Predicted positive, actually negative (Type I error)

False Negative (FN): Predicted negative, actually positive (Type II error)

\begin{array}{c|cc} & \text{Predicted +} & \text{Predicted -} \\ \hline \text{Actual +} & TP & FN \\ \text{Actual -} & FP & TN \end{array}


Accuracy

The most intuitive metric: what fraction of predictions is correct?

\text{Accuracy} = \frac{TP + TN}{TP + TN + FP + FN}

Strengths:

Weaknesses:


Precision

Of all positive predictions, what fraction is actually positive?

\text{Precision} = \frac{TP}{TP + FP}

Intuition: "When the model says positive, how often is it right?"

High precision matters when:


Recall (Sensitivity, True Positive Rate)

Of all actual positives, what fraction did we catch?

\text{Recall} = \frac{TP}{TP + FN}

Intuition: "Of all the real positives, how many did we find?"

High recall matters when:


The Precision-Recall Trade-off

Increasing the classification threshold:

Decreasing the threshold:

You cannot maximize both simultaneously. The right balance depends on the application.


F1 Score

The harmonic mean of precision and recall:

F1 = 2 \times \frac{\text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}} = \frac{2 \times TP}{2 \times TP + FP + FN}

Why harmonic mean?

F1 range: 0 to 1, higher is better


F-beta Score

Generalization of F1 that lets you weight precision vs. recall:

F_\beta = (1 + \beta^2) \times \frac{\text{Precision} \times \text{Recall}}{\beta^2 \times \text{Precision} + \text{Recall}}

F1: \beta = 1, equal weight

F2: \beta = 2, recall weighted higher (2x importance)

F0.5: \beta = 0.5, precision weighted higher (2x importance)


Specificity (True Negative Rate)

Of all actual negatives, what fraction did we correctly identify?

\text{Specificity} = \frac{TN}{TN + FP}

Intuition: "How well do we identify negatives?"

Important in medical testing where you want to avoid false alarms.


False Positive Rate

\text{FPR} = \frac{FP}{FP + TN} = 1 - \text{Specificity}

Used in ROC curves. The fraction of negatives incorrectly classified as positive.


Worked Example

100 patients, 20 have disease, 80 healthy

Model predictions: 25 positive, 75 negative

Confusion matrix:

Calculations:

Accuracy = (18 + 73) / 100 = 0.91

Precision = 18 / (18 + 7) = 18/25 = 0.72

Recall = 18 / (18 + 2) = 18/20 = 0.90

F1 = 2 * (0.72 * 0.90) / (0.72 + 0.90) = 1.296 / 1.62 = 0.80

Specificity = 73 / (73 + 7) = 73/80 = 0.91


Matthews Correlation Coefficient (MCC)

A balanced metric that uses all four confusion matrix values:

\text{MCC} = \frac{TP \times TN - FP \times FN}{\sqrt{(TP+FP)(TP+FN)(TN+FP)(TN+FN)}}

Range: -1 to +1

Advantages:


Balanced Accuracy

Average of recall for each class:

\text{Balanced Accuracy} = \frac{\text{Recall}_+ + \text{Recall}_-}{2} = \frac{TPR + TNR}{2}

Useful for imbalanced datasets where regular accuracy is misleading.


Choosing the Right Metric

Balanced classes, general purpose: Accuracy or F1

Imbalanced classes: F1, MCC, or Balanced Accuracy

False positives costly: Precision

False negatives costly: Recall

Need single number for model comparison: F1 or MCC

Threshold will be tuned later: AUC-ROC

Multi-class: Micro/Macro/Weighted F1


Multi-Class Extension

For n classes, the confusion matrix is n \times n.

Per-class metrics: Treat each class as "positive vs. rest" to compute precision, recall, F1.

Aggregation:


Metric Pitfalls

Accuracy paradox: High accuracy on imbalanced data is meaningless.

Optimizing wrong metric: Optimizing precision alone can destroy recall (and vice versa).

Ignoring costs: All metrics treat errors equally. Real-world costs vary.

Single metric obsession: Report multiple metrics for a complete picture.

Threshold dependence: Precision, recall, F1 depend on threshold. AUC does not.

Examples

Example 1

Input
y_true = [0, 1, 2, 2], y_pred = [0, 1, 0, 2], average = "micro", pos_label = 1
Output
{"accuracy": 0.75, "precision": 0.75, "recall": 0.75, "f1": 0.75}
Explanation
Three of four labels are correct; for single-label micro averaging, precision, recall, and F1 also equal 0.75.

Example 2

Input
y_true = [0, 1, 2, 2], y_pred = [0, 1, 0, 2], average = "macro", pos_label = 1
Output
{"accuracy": 0.75, "precision": 0.833333, "recall": 0.833333, "f1": 0.777778}

Hints

  1. Use np.unique(np.concatenate([y_true, y_pred])) to collect every observed class.
  2. For each class, boolean masks can count true positives, false positives, and false negatives.
  3. Use the true-label count of each class as its weight for weighted averaging.

Requirements

Constraints

Starter Code

import numpy as np

def classification_metrics(y_true: list[int], y_pred: list[int], average: str = "micro", pos_label: int = 1) -> dict:
    """
    Returns a dictionary containing accuracy, precision, recall, and f1 rounded to six decimals.
    """
    # Write code here
    pass

Test Cases

CaseMatches
Micro averaging (3 classes)public
Macro averaging (3 classes)public