Precision and Recall - Model Evaluation
Implement Precision and Recall in Python with NumPy. medium exercise with examples, hints, and instant feedback. No setup or signup required.
Precision and Recall
What you'll build
A function that compares binary predictions with the true labels and returns (precision, recall), the two quantities that F1 and the precision-recall curve are built from.
Background
Accuracy hides what kind of mistakes a model makes. Precision asks "when the model says positive, how often is it right?" and recall asks "of all the real positives, how many did it find?". Raising the threshold usually trades recall for precision. These are sklearn.metrics.precision_score and recall_score with pos_label=1.
Formula
TP = #{y_pred = 1 and y_true = 1} (true positives)
FP = #{y_pred = 1 and y_true = 0} (false positives)
FN = #{y_pred = 0 and y_true = 1} (false negatives)
precision = TP / (TP + FP)
recall = TP / (TP + FN)
Inputs
y_true: binary labels (0 or 1), shape(n,)y_pred: binary predictions (0 or 1), shape(n,)
(Tests may pass Python lists; convert with np.asarray.)
Expected return format
A tuple (precision, recall) of Python floats, each rounded to 4 decimals with round(x, 4).
Edge cases and conventions
- Zero division: if nothing is predicted positive (
TP + FP = 0), precision is0.0; if there are no actual positives (TP + FN = 0), recall is0.0. This matches scikit-learn's defaultzero_divisionbehaviour (0, with a warning). - The positive class is
1; true negatives don't enter either formula.
Constraints
- NumPy only (no sklearn); count with boolean masks, no Python loops.
Follow-up
- Compute F1 =
2 * P * R / (P + R)from your result. Why is it the harmonic mean rather than the arithmetic mean? - How would you extend this to multi-class (macro vs micro averaging)?
Examples
Input: precision_recall(np.array([1, 1, 0, 1, 0]), np.array([1, 0, 0, 1, 1])) Output: (0.6667, 0.6667)
TP = 2, FP = 1 (index 4), FN = 1 (index 1): precision = 2/3 and recall = 2/3.
Input: precision_recall(np.array([1, 1, 1, 1, 0]), np.array([1, 0, 0, 0, 0])) Output: (1.0, 0.25)
A cautious model: its one positive prediction is right, but it finds only 1 of the 4 positives.
Input: precision_recall(np.array([1, 1, 0]), np.array([0, 0, 0])) Output: (0.0, 0.0)
No positive predictions: TP + FP = 0, so precision falls back to 0.0; recall is 0 / 2 = 0.0.
Practice in Python
import numpy as np
def precision_recall(y_true: np.ndarray, y_pred: np.ndarray) -> tuple:
"""
Precision and recall for binary classification (positive class = 1).
Args:
y_true: True labels (0 or 1), shape (n,)
y_pred: Predicted labels (0 or 1), shape (n,)
Returns:
Tuple (precision, recall) of floats rounded to 4 decimals;
a metric whose denominator is 0 is returned as 0.0
"""
# Your code here
pass
The interactive editor loads with Python and NumPy. Run your implementation against 6 tests, or use the progressive hints.