W3docs

Machine Learning: Comprender la Matriz de Confusión

Aprende qué es una matriz de confusión, cómo construirla en Python con scikit-learn, visualizarla con seaborn y derivar precisión, exhaustividad y F1-score.

Una matriz de confusión es una tabla que resume los resultados de predicción de un modelo de clasificación comparando las etiquetas reales con las etiquetas predichas. Es el punto de partida para calcular la precisión, la exhaustividad, el F1-score y la mayoría de las demás métricas de clasificación.

Este capítulo cubre:

  • Qué significan las cuatro celdas (TP, FP, TN, FN) y por qué cada una importa
  • Cómo calcular métricas comunes a partir de esas celdas
  • Cómo construir y visualizar una matriz de confusión en Python con scikit-learn y seaborn
  • Matrices de confusión multiclase
  • Errores comunes, especialmente en conjuntos de datos desequilibrados

¿Qué es una Matriz de Confusión?

Para un clasificador binario (dos clases posibles: positiva y negativa), la matriz de confusión es una tabla de 2×2:

Predicción PositivaPredicción Negativa
Real PositivoVerdadero Positivo (TP)Falso Negativo (FN)
Real NegativoFalso Positivo (FP)Verdadero Negativo (TN)

Cada celda cuenta un tipo específico de resultado:

TérminoAbreviaturaSignificado
Verdadero PositivoTPEl modelo predice positivo; la realidad es positiva ✓
Verdadero NegativoTNEl modelo predice negativo; la realidad es negativa ✓
Falso PositivoFPEl modelo predice positivo; la realidad es negativa ✗ (Error de Tipo I)
Falso NegativoFNEl modelo predice negativo; la realidad es positiva ✗ (Error de Tipo II)

Un truco mnemotécnico: la primera palabra (Verdadero / Falso) indica si la predicción fue correcta; la segunda palabra (Positivo / Negativo) indica qué predijo el modelo.

Métricas Derivadas de la Matriz

Los cuatro conteos alimentan todas las métricas estándar de clasificación:

MétricaFórmulaQué mide
Exactitud(TP + TN) / (TP + TN + FP + FN)Fracción total de predicciones correctas
PrecisiónTP / (TP + FP)De todas las predicciones positivas, cuántas fueron correctas
Exhaustividad (Sensibilidad)TP / (TP + FN)De todos los positivos reales, cuántos fueron encontrados
EspecificidadTN / (TN + FP)De todos los negativos reales, cuántos se descartaron correctamente
F1-Score2 × Precisión × Exhaustividad / (Precisión + Exhaustividad)Media armónica de precisión y exhaustividad

Cuándo priorizar precisión vs. exhaustividad

  • Prioriza la exhaustividad cuando omitir un caso positivo es costoso — cribado médico, detección de fraude, filtros de spam que deben detectar cada mensaje de spam.
  • Prioriza la precisión cuando las falsas alarmas son costosas — recomendaciones quirúrgicas, marcado de documentos legales, sistemas de notificaciones push.
  • El F1-score equilibra ambas y es la métrica predeterminada cuando el conjunto de datos está desequilibrado.

Ejemplo Numérico Trabajado

Supón que un modelo examina a 100 pacientes para detectar una enfermedad:

  • TP = 50 (pacientes enfermos correctamente identificados)
  • FP = 5 (pacientes sanos marcados incorrectamente como enfermos)
  • FN = 10 (pacientes enfermos no detectados)
  • TN = 35 (pacientes sanos correctamente descartados)

Cálculos paso a paso:

Accuracy  = (50 + 35) / 100 = 0.85  (85 %)
Precision = 50 / (50 + 5)  ≈ 0.909 (90.9 %)
Recall    = 50 / (50 + 10) ≈ 0.833 (83.3 %)
F1-Score  = 2 × 0.909 × 0.833 / (0.909 + 0.833) ≈ 0.869 (86.9 %)

Observa que la exactitud (85 %) parece aceptable, pero la exhaustividad es solo del 83 % — lo que significa que 10 de cada 60 pacientes enfermos no fueron detectados. En un contexto médico, esa diferencia importa mucho más que el dato de exactitud.

Construir una Matriz de Confusión en Python

Usando scikit-learn

sklearn.metrics proporciona confusion_matrix() y un informe de texto listo para usar mediante classification_report().

from sklearn.metrics import confusion_matrix, classification_report

# Ground-truth labels and model predictions
y_true = [1, 1, 0, 0, 1, 0, 1, 0, 1, 0]
y_pred = [1, 0, 0, 1, 1, 0, 1, 0, 1, 1]

cm = confusion_matrix(y_true, y_pred)
print("Confusion Matrix:")
print(cm)
print()
print(classification_report(y_true, y_pred, target_names=["Negative", "Positive"]))

confusion_matrix() devuelve un array de NumPy. De forma predeterminada, las filas son las clases reales y las columnas son las clases predichas (coincidiendo con el diseño de la tabla mostrado anteriormente). La disposición del array es:

[[TN  FP]
 [FN  TP]]

Calcular métricas manualmente

Puedes extraer las cuatro celdas y calcular las métricas tú mismo para verificar:

from sklearn.metrics import confusion_matrix

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

tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()

accuracy  = (tp + tn) / (tp + tn + fp + fn)
precision = tp / (tp + fp)
recall    = tp / (tp + fn)
f1        = 2 * precision * recall / (precision + recall)

print(f"TP={tp}, FP={fp}, FN={fn}, TN={tn}")

print(f"Accuracy : {accuracy:.3f}")
print(f"Precision: {precision:.3f}")
print(f"Recall   : {recall:.3f}")
print(f"F1-Score : {f1:.3f}")

Salida esperada:

TP=4, FP=2, FN=1, TN=3
Accuracy : 0.700
Precision: 0.667
Recall   : 0.800
F1-Score : 0.727

Visualizar con seaborn

Un mapa de calor hace que la matriz de confusión sea más fácil de leer, especialmente para problemas multiclase:

import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import confusion_matrix

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

cm = confusion_matrix(y_true, y_pred)

sns.heatmap(
    cm,
    annot=True,
    fmt="d",
    cmap="Blues",
    xticklabels=["Negative", "Positive"],
    yticklabels=["Negative", "Positive"],
)
plt.xlabel("Predicted label")
plt.ylabel("True label")
plt.title("Confusion Matrix")
plt.tight_layout()
plt.savefig("confusion_matrix.png", dpi=150)
plt.show()

annot=True imprime el conteo dentro de cada celda; fmt="d" los formatea como enteros.

Matrices de Confusión Multiclase

Cuando hay más de dos clases, la matriz de confusión se expande a una cuadrícula N×N. Cada fila sigue representando las clases reales; cada columna representa las clases predichas. Las celdas de la diagonal son predicciones correctas; las celdas fuera de la diagonal son errores.

from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
import matplotlib.pyplot as plt

# Three classes: cat, dog, rabbit
y_true = ["cat", "dog", "rabbit", "cat", "dog", "rabbit",
          "cat", "dog", "cat", "rabbit"]
y_pred = ["cat", "dog", "rabbit", "dog", "dog", "cat",
          "cat", "rabbit", "cat", "rabbit"]

labels = ["cat", "dog", "rabbit"]
cm = confusion_matrix(y_true, y_pred, labels=labels)
print(cm)

disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=labels)
disp.plot(cmap="Blues")
plt.title("Multi-Class Confusion Matrix")
plt.tight_layout()
plt.savefig("cm_multiclass.png", dpi=150)
plt.show()

ConfusionMatrixDisplay (añadido en scikit-learn 0.24) es una alternativa conveniente de una sola línea al mapa de calor de seaborn y no requiere la dependencia de seaborn.

Para problemas multiclase, la precisión y la exhaustividad se calculan por clase y luego se promedian. classification_report() ofrece tres estrategias de promediado:

  • macro — promedio no ponderado entre clases (trata todas las clases por igual).
  • weighted — promedio ponderado por soporte (número de instancias reales por clase).
  • micro — agrega TP/FP/FN en todas las clases antes de dividir (da la exactitud general para conjuntos de datos equilibrados).

Errores Comunes

La exactitud es engañosa en conjuntos de datos desequilibrados

Considera un conjunto de datos donde el 95 % de las muestras son negativas. Un modelo que siempre predice negativo alcanza un 95 % de exactitud pero tiene una exhaustividad de cero — nunca detecta un caso positivo. La matriz de confusión revela esto de inmediato: toda la primera fila (Real Positivo) estará compuesta por FN.

Combina siempre la exactitud con la precisión, la exhaustividad o el F1-score en datos desequilibrados. Consulta el capítulo Train/Test Split para saber cómo crear una división representativa, y el capítulo Curva AUC-ROC para obtener una métrica de evaluación independiente del umbral.

Elegir la estrategia de promediado incorrecta

Usar el promediado macro cuando las clases están muy desequilibradas infla la puntuación de las clases poco frecuentes. Usa weighted para obtener una imagen realista de la calidad general del modelo sobre el conjunto de datos completo.

Olvidar la normalización

Los conteos brutos dependen del tamaño del conjunto de datos. Al comparar modelos entrenados en conjuntos de datos de diferentes tamaños, normaliza la matriz dividiendo cada fila por su suma (pasa normalize='true' a confusion_matrix()):

cm_normalized = confusion_matrix(y_true, y_pred, normalize="true")
print(cm_normalized.round(2))

Ahora cada fila suma 1.0, mostrando la fracción de cada clase real predicha correctamente.

Matriz de Confusión vs. Otras Herramientas de Evaluación

HerramientaIdeal para
Matriz de confusiónComprender los tipos específicos de errores que comete un modelo
Curva AUC-ROCComparar clasificadores en todos los umbrales de decisión
Validación CruzadaEstimar qué tan bien generaliza la matriz a datos no vistos
Grid SearchAjustar hiperparámetros usando una métrica elegida (p. ej., F1-score)

Conclusiones Clave

  • Una matriz de confusión desglosa las predicciones en TP, FP, TN y FN — cuatro conteos que revelan qué errores comete un modelo, no solo cuántos.
  • La exactitud por sí sola es insuficiente; comprueba siempre la precisión, la exhaustividad y el F1-score, especialmente en datos desequilibrados.
  • Usa sklearn.metrics.confusion_matrix() para el cálculo y seaborn o ConfusionMatrixDisplay para la visualización.
  • Las matrices multiclase siguen la misma convención de fila = real, columna = predicho y escalan a N×N.
  • Adapta la estrategia de promediado (macro, weighted, micro) a la distribución de clases de tu conjunto de datos.
Was this page helpful?