0Pricing
Machine Learning Academy · Lección

Métricas de clasificación: accuracy, precision, recall y F1

Calcule las cuatro métricas con las mismas predicciones y comprenda cuál debe priorizar según el coste de los falsos positivos frente al de los falsos negativos.

Métricas de clasificación: accuracy, precision, recall y F1 es una lección gratuita de Machine Learning Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Machine Learning Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Machine Learning Academy incluye 4 lecciones en total.

Partes de esta lección aún no han sido traducidas y se muestran en inglés.

Why Accuracy Is Often Not Enough

Accuracy — the fraction of correct predictions — is the most intuitive metric, but it is misleading when classes are imbalanced. Consider a medical test for a disease that affects 1% of patients. A model that always predicts 'healthy' achieves 99% accuracy while being completely useless — it misses every actual disease case. In fraud detection, cancer screening, or rare event prediction, accuracy hides the model's failure to detect the rare but critical positive class. This is why we need metrics that separately measure performance on each class: precision, recall, and F1-score.

import numpy as np

# 1000 patients: 990 healthy, 10 sick
y_true = [0]*990 + [1]*10
y_pred_dummy = [0]*1000  # Always predict healthy

correct = sum(p == t for p, t in zip(y_pred_dummy, y_true))
accuracy = correct / len(y_true)
print(f'Dummy accuracy: {accuracy:.1%}')  # 99.0% -- misleadingly high!
print('But 0 sick patients correctly identified!')
print('This is why we need precision and recall.')

The Confusion Matrix: Ground Truth

The confusion matrix is the foundation of all classification metrics. For binary classification, it is a 2x2 table: True Positives (TP) — correctly predicted positive; True Negatives (TN) — correctly predicted negative; False Positives (FP) — predicted positive but actually negative (Type I error); False Negatives (FN) — predicted negative but actually positive (Type II error). Every classification metric is derived from some combination of these four numbers. Inspecting the raw confusion matrix reveals which type of error the model makes most.

from sklearn.metrics import confusion_matrix
import numpy as np

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

cm = confusion_matrix(y_true, y_pred)
print('Confusion Matrix:')
print(cm)
# [[TN, FP],
#  [FN, TP]]
TN, FP, FN, TP = cm.ravel()
print(f'TP={TP}, TN={TN}, FP={FP}, FN={FN}')

Accuracy: Simple but Limited

Accuracy = (TP + TN) / (TP + TN + FP + FN). It answers: of all predictions, what fraction were correct? Accuracy is a fair metric only when classes are roughly balanced and the costs of false positives and false negatives are similar. For example, handwritten digit recognition with ~10% of each digit class is balanced, making accuracy a reasonable measure. Use accuracy when: classes are balanced and all errors have equal cost. Avoid it when: classes are skewed (one class dominates) or false negatives cost more than false positives (or vice versa).

from sklearn.metrics import accuracy_score, confusion_matrix
import numpy as np

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

acc = accuracy_score(y_true, y_pred)
print(f'Accuracy = {acc:.2f}')  # (TP+TN) / total

# Manual calculation
TN, FP, FN, TP = confusion_matrix(y_true, y_pred).ravel()
acc_manual = (TP + TN) / (TP + TN + FP + FN)
print(f'Manual: ({TP}+{TN}) / ({TP}+{TN}+{FP}+{FN}) = {acc_manual:.2f}')

Precision: Quality of Positive Predictions

Precision = TP / (TP + FP). It answers: of all the samples we predicted as positive, what fraction actually are positive? Precision is the metric to optimise when false positives are costly. In spam detection: a high-precision spam filter rarely marks legitimate email as spam. In drug testing: high precision means we rarely approve a drug that does not work. Low precision means many of our positive predictions are wrong — we are flooding users with false alarms. Precision tells you nothing about the false negatives — a model that only predicts one obvious case as positive has precision 1.0 but misses everything else.

from sklearn.metrics import precision_score, confusion_matrix
import numpy as np

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

prec = precision_score(y_true, y_pred)
print(f'Precision = {prec:.2f}')

# Manual calculation
TN, FP, FN, TP = confusion_matrix(y_true, y_pred).ravel()
print(f'Manual: TP/(TP+FP) = {TP}/({TP}+{FP}) = {TP/(TP+FP):.2f}')
print('Of all PREDICTED positives, this fraction are truly positive.')

Recall: Coverage of Actual Positives

Recall = TP / (TP + FN) (also called Sensitivity or True Positive Rate). It answers: of all samples that actually are positive, what fraction did we find? Recall is the metric to optimise when false negatives are costly. In cancer screening: high recall means we identify most patients who actually have cancer. In fraud detection: high recall means we catch most fraudulent transactions. Low recall means we are missing too many actual positives — dangerous in medical or security contexts. Recall and precision are in tension: increasing one typically decreases the other.

from sklearn.metrics import recall_score, confusion_matrix
import numpy as np

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

rec = recall_score(y_true, y_pred)
print(f'Recall = {rec:.2f}')

# Manual calculation
TN, FP, FN, TP = confusion_matrix(y_true, y_pred).ravel()
print(f'Manual: TP/(TP+FN) = {TP}/({TP}+{FN}) = {TP/(TP+FN):.2f}')
print('Of all ACTUAL positives, this fraction were correctly identified.')

The Precision-Recall Trade-Off

Precision and recall are inversely related when you adjust the classification threshold. As you lower the threshold (predict positive more aggressively), recall increases (you catch more actual positives) but precision decreases (more false positives get through). Raising the threshold has the opposite effect. There is no single threshold that simultaneously maximises both. Which metric to prioritise depends on the business problem: in email filtering, prioritise precision (do not annoy users with false spam alerts); in disease screening, prioritise recall (do not miss sick patients).

from sklearn.metrics import precision_score, recall_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
import numpy as np

X, y = load_breast_cancer(return_X_y=True)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, random_state=42)

clf = LogisticRegression(max_iter=10000)
clf.fit(X_tr, y_tr)
proba = clf.predict_proba(X_te)[:, 1]

for thresh in [0.3, 0.5, 0.7, 0.9]:
    y_pred = (proba >= thresh).astype(int)
    prec = precision_score(y_te, y_pred, zero_division=0)
    rec  = recall_score(y_te, y_pred)
    print(f'threshold={thresh}: precision={prec:.3f}, recall={rec:.3f}')

F1-Score: Harmonic Mean of Precision and Recall

F1-score = 2 * (Precision * Recall) / (Precision + Recall). The F1-score is the harmonic mean of precision and recall. Unlike the arithmetic mean, the harmonic mean punishes extreme values: a model with precision=1.0 and recall=0.0 gets F1=0, not 0.5. This makes F1 a fair aggregate metric that requires both precision and recall to be reasonably high. F1 is the standard metric for imbalanced text classification (NLP benchmarks always report it), fraud detection, and any problem where class imbalance makes accuracy misleading.

from sklearn.metrics import f1_score, precision_score, recall_score
import numpy as np

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

prec = precision_score(y_true, y_pred)
rec  = recall_score(y_true, y_pred)
f1   = f1_score(y_true, y_pred)

print(f'Precision = {prec:.3f}')
print(f'Recall    = {rec:.3f}')
print(f'F1-Score  = {f1:.3f}')
print(f'Manual F1 = 2 * ({prec:.3f} * {rec:.3f}) / ({prec:.3f} + {rec:.3f}) = {2*prec*rec/(prec+rec):.3f}')

Fbeta-Score: Weighted Precision-Recall Balance

The Fbeta score generalises F1 by introducing a parameter beta that controls how much to weight recall relative to precision: F_beta = (1 + beta^2) * Precision * Recall / (beta^2 * Precision + Recall). When beta=1, this is the standard F1 score. When beta=2 (F2), recall is weighted twice as much as precision — useful when missing positives is twice as costly as false alarms. When beta=0.5 (F0.5), precision is weighted more — useful in recommendation systems where accuracy of suggestions matters more than coverage.

from sklearn.metrics import fbeta_score
import numpy as np

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

for beta in [0.5, 1.0, 2.0]:
    score = fbeta_score(y_true, y_pred, beta=beta)
    print(f'F{beta:.1f} = {score:.3f}')

print()
print('beta=0.5: precision weighted 2x -> use when false alarms costly')
print('beta=1.0: balanced precision/recall -> standard F1')
print('beta=2.0: recall weighted 2x -> use when missing positives costly')

Multi-Class Averaging: Macro, Micro, and Weighted

For multi-class classification, you must aggregate per-class precision/recall/F1 into a single number. Macro average: compute metric for each class independently, then average — treats all classes equally regardless of size. Weighted average: same but weights by class support — gives larger classes more influence. Micro average: aggregate TP/FP/FN across all classes first, then compute — equivalent to accuracy for precision, recall, and F1 when there are no samples with multiple labels. Use macro for imbalanced datasets where small minority classes are important.

from sklearn.metrics import f1_score
import numpy as np

# Multi-class predictions
y_true = [0, 0, 1, 1, 2, 2, 2]
y_pred = [0, 1, 1, 1, 2, 0, 2]

print('Macro F1:    ', f1_score(y_true, y_pred, average='macro').round(3))
print('Micro F1:    ', f1_score(y_true, y_pred, average='micro').round(3))
print('Weighted F1: ', f1_score(y_true, y_pred, average='weighted').round(3))
print('Per-class F1:', f1_score(y_true, y_pred, average=None).round(3))
print()
print('Macro treats all classes equally (even rare ones)')
print('Weighted rewards correct prediction of common classes')

classification_report: All Metrics in One

classification_report() generates a formatted table showing precision, recall, F1-score, and support (number of true instances) for each class, plus macro/weighted averages. This is the standard output to include in any ML evaluation report. The 'support' column is especially important: a class with support=5 will have noisy precision/recall estimates and should be interpreted cautiously. Always check support values alongside F1 scores to assess metric reliability.

from sklearn.metrics import classification_report
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

X, y = load_iris(return_X_y=True)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, random_state=42)

clf = RandomForestClassifier(random_state=42)
clf.fit(X_tr, y_tr)
y_pred = clf.predict(X_te)

print(classification_report(
    y_te, y_pred,
    target_names=load_iris().target_names
))

Balanced Accuracy for Imbalanced Classes

Balanced accuracy is the arithmetic mean of sensitivity (recall for each class). For binary classification: balanced_accuracy = (TPR + TNR) / 2 where TNR (True Negative Rate) = TN / (TN+FP). Unlike standard accuracy, balanced accuracy gives equal weight to each class regardless of how many samples it has. A model that always predicts the majority class gets balanced accuracy of 0.5 — correctly identifying it as no better than random. Use balanced accuracy when classes are imbalanced and you want a single metric that reflects performance on all classes equally, without the complexity of computing per-class metrics.

from sklearn.metrics import balanced_accuracy_score, accuracy_score
import numpy as np

# Imbalanced: 990 class 0, 10 class 1
y_true = np.array([0]*990 + [1]*10)
y_dummy = np.zeros(1000, dtype=int)  # Always predict class 0

acc_standard = accuracy_score(y_true, y_dummy)
acc_balanced = balanced_accuracy_score(y_true, y_dummy)

print(f'Standard accuracy: {acc_standard:.3f}')  # 99% -- misleading
print(f'Balanced accuracy: {acc_balanced:.3f}')  # 0.5 -- correctly shows no skill
print()
print('Balanced accuracy correctly penalises ignoring the minority class')

Quick Check

Test your understanding of Machine Learning with Python concepts from this lesson.

Lesson Recap

In this lesson you learned: accuracy is misleading for imbalanced classes — use the confusion matrix as ground truth, precision measures quality of positive predictions (minimise false positives) and recall measures coverage of actual positives (minimise false negatives), and F1-score harmonically combines both into a balanced metric. Next up we explore ROC curves and AUC-ROC for threshold-independent model evaluation.

Preguntas frecuentes

¿La lección «Métricas de clasificación: accuracy, precision, recall y F1» es gratis?

Sí — el texto completo de «Métricas de clasificación: accuracy, precision, recall y F1» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Machine Learning Academy, actualiza a CoddyKit PRO. El curso de Machine Learning Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Métricas de clasificación: accuracy, precision, recall y F1»?

Calcule las cuatro métricas con las mismas predicciones y comprenda cuál debe priorizar según el coste de los falsos positivos frente al de los falsos negativos. Practicas Machine Learning Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Machine Learning Academy?

No se requiere experiencia previa. Machine Learning Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.

¿Cuánto tiempo toma la lección «Métricas de clasificación: accuracy, precision, recall y F1»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Machine Learning Academy?

Sí. Cada lección de Machine Learning Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Métricas de clasificación: accuracy, precision, recall y F1
  2. Curvas ROC y AUC-ROC
  3. Métricas de regresión: MAE, MSE, RMSE y R-squared
  4. Cómo elegir la métrica adecuada para su problema de negocio
← Volver a Machine Learning Academy