Skip to content
Work Practice Products Coding interviews Machine learning coding Quant developer HFT course Blog Method Why me About Enquire Book a call

ML coding · Ranking and evaluation metrics

Macro-averaged F1 across classes

Easy · Target 10 minutes · Python and NumPy

Given true labels y_true and predictions y_pred (integers), let the classes be every label that appears in either list. For each class c, F1 = 2TP / (2TP + FP + FN), counting TP, FP and FN for c against all other classes. Return the unweighted mean of the per-class F1 scores.

Examples

Input y_true = [0, 0, 1, 1, 2], y_pred = [0, 1, 1, 1, 0]

Output 0.4333

Class 2 is never predicted, so its F1 is 0 and it pulls the mean down.

Input y_true = [5, 5, 5], y_pred = [5, 5, 5]

Output 1

One class, all correct: 1.0.

Constraints

  • 1 ≤ n ≤ 10⁶
  • Labels are integers
  • Checked to a relative tolerance of 10⁻¹²

Hints

Hint 1

np.union1d(y_true, y_pred) gives the classes.

Hint 2

For each class, TP is the count where both equal c; FP where only the prediction does; FN where only the label does.

Hint 3

Every class in the union appears at least once, so 2TP + FP + FN is never zero.

Where candidates go wrong

  • Taking the classes from y_true only: a class that is predicted but never true is silently ignored.
  • Computing precision and recall first and dividing by zero when a class is never predicted.
  • Returning micro-F1, which for single-label problems is just accuracy.
Console⌘/Ctrl + Enter runs

Python runs in your browser with NumPy. The first run downloads the runtime, which takes a few seconds.


Why interviewers ask it

The default metric for imbalanced classification, and a quick test of whether a candidate knows the difference between macro, micro and weighted averaging.

The theory behind it is in the lesson NDCG, calibration error and macro-F1 from scratch.


Keep going