The accuracy paradox
What it is
On a dataset that is 99% negative, a model that predicts 'negative' for every row is 99% accurate. It has learned nothing, it catches nothing, and it beats most honest first attempts on the metric you were watching.
Why it matters
It is the reason every metric decision in this module exists. Accuracy averages over the classes weighted by how common they are, so on imbalanced data it is almost entirely a measurement of the majority class — and the majority class is the one nobody asked about.
In the real world: A loan-default model that says “no one defaults” is 97% accurate and completely useless.
Visual example
Accuracy paradoxThe all-negative classifier and a real model, on the same 10,000 rows. Accuracy cannot tell them apart; nothing else is confused.
Where 0.99 comes from
9,900 negatives all predicted correctly, 100 positives all missed
accuracy = 9900 / 10000 = 0.990
balanced accuracy = (1.000 + 0.000) / 2 = 0.500
The 1% of rows anyone cares about contributes 1% of the metric
Why this matters
The third row is the model you would actually ship, and it is the worst of the three on accuracy. If accuracy is the number on the dashboard, shipping it will look like a regression.
Common misconception
Wrong idea: 99% accuracy means the model is nearly always right.
Correct idea: it means the model is nearly always right about the common class. Report per-class recall, balanced accuracy or average precision, and accuracy stops being able to mislead you.
import numpy as np
from sklearn.dummy import DummyClassifier
from sklearn.metrics import accuracy_score, balanced_accuracy_score, f1_score
from sklearn.model_selection import train_test_split
y = np.concatenate([np.zeros(9900), np.ones(100)])
X = np.random.default_rng(0).standard_normal((10000, 5)) # pure noise
X_tr, X_te, y_tr, y_te = train_test_split(X, y, stratify=y, test_size=0.3, random_state=0)
dummy = DummyClassifier(strategy="most_frequent").fit(X_tr, y_tr)
pred = dummy.predict(X_te)
accuracy_score(y_te, pred) # 0.99
balanced_accuracy_score(y_te, pred) # 0.50 — the honest version
f1_score(y_te, pred, zero_division=0) # 0.00Using accuracy as the scoring argument in a grid search on imbalanced data. Every hyperparameter that makes the model *more* willing to predict the positive class will score worse, so the search converges on the most conservative model in the space — often the one that never predicts positive at all.