Cómo leer una matriz de confusión en Machine Learning
Después de entrenar un modelo de clasificación, la pregunta más importante es simple: ¿dónde acierta y dónde falla? La matriz de confusión responde a eso en una sola tabla y es la base para calcular métricas como accuracy, precision y recall. Aprender a leer una matriz de confusión en Machine Learning te evita la trampa habitual de confiar solo en la accuracy, que a menudo engaña.
Requisitos previos
- Python 3 instalado en tu ordenador.
- Las librerías scikit-learn y matplotlib (instálalas con
pip install scikit-learn matplotlib). - Nociones básicas de clasificación: un modelo que predice una de dos clases (0 o 1).
- No necesitas datos propios, porque vamos a generar un conjunto de ejemplo.
Paso 1: Entrenar un modelo de clasificación sencillo
Primero necesitamos un modelo y algunas predicciones para analizar. Para que el ejemplo sea reproducible, generamos un conjunto de datos binario con make_classification y entrenamos una regresión logística. El random_state garantiza que obtengas exactamente los mismos números de este tutorial.
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
# Binary dataset with 30% of class 1 (imbalanced)
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5,
weights=[0.7, 0.3], random_state=42)
# Split into train (80%) and test (20%)
X_treino, X_teste, y_treino, y_teste = train_test_split(
X, y, test_size=0.2, random_state=42)
modelo = LogisticRegression(max_iter=10000)
modelo.fit(X_treino, y_treino)Paso 2: Generar la matriz de confusión
Con el modelo entrenado, hacemos predicciones sobre los datos de prueba y las comparamos con los valores reales. La función confusion_matrix devuelve una tabla que cruza lo que ocurrió en la realidad con lo que el modelo predijo.
from sklearn.metrics import confusion_matrix
y_previsto = modelo.predict(X_teste)
matriz = confusion_matrix(y_teste, y_previsto)
print(matriz)En este ejemplo, el resultado es:
[[127 6]
[ 35 32]]Paso 3: Leer los cuatro cuadrantes de la matriz de confusión
En una clasificación binaria, las filas representan la clase real y las columnas la clase predicha por el modelo. Cada celda tiene un nombre y un significado concreto:
- Verdaderos Negativos (VN) = 127: eran clase 0 y el modelo acertó (esquina superior izquierda).
- Falsos Positivos (FP) = 6: eran clase 0, pero el modelo dijo 1 (falsa alarma).
- Falsos Negativos (FN) = 35: eran clase 1, pero el modelo dijo 0 (casos reales que se escaparon).
- Verdaderos Positivos (VP) = 32: eran clase 1 y el modelo acertó (esquina inferior derecha).
Puedes extraer los cuatro valores directamente a variables con ravel(), lo que resulta útil para calcular las métricas a continuación:
vn, fp, fn, vp = matriz.ravel()
print(vn, fp, fn, vp) # 127 6 35 32Paso 4: Calcular accuracy, precision y recall
A partir de los cuatro números salen las métricas esenciales. Fíjate en cómo cada una cuenta una historia diferente sobre el mismo modelo:
- Accuracy = (VP + VN) / total = (32 + 127) / 200 = 0,80. El porcentaje total de aciertos.
- Precision = VP / (VP + FP) = 32 / 38 = 0,84. De las veces que el modelo predijo 1, cuántas eran correctas.
- Recall = VP / (VP + FN) = 32 / 67 = 0,48. De los casos reales de la clase 1, cuántos detectó el modelo.
No necesitas hacer estas cuentas a mano: scikit-learn lo calcula todo de una vez con classification_report.
from sklearn.metrics import classification_report
print(classification_report(y_teste, y_previsto))Fíjate ahora en el punto más importante de este ejemplo: la accuracy es del 80%, lo que parece bueno, pero el recall de la clase 1 es solo del 48%. Es decir, el modelo falla más de la mitad de los casos positivos reales. Este es exactamente el tipo de error que revela la matriz de confusión y que la accuracy por sí sola oculta.
Paso 5: Visualizar la matriz de confusión
Un gráfico hace la lectura inmediata, sobre todo para compartir con compañeros o incluir en un informe. ConfusionMatrixDisplay dibuja la misma tabla con colores a partir de las predicciones.
import matplotlib.pyplot as plt
from sklearn.metrics import ConfusionMatrixDisplay
ConfusionMatrixDisplay.from_predictions(y_teste, y_previsto)
plt.show()Verificar el resultado
Para confirmar que todo está correcto, suma las cuatro celdas: 127 + 6 + 35 + 32 = 200, que es exactamente el número de ejemplos de prueba. Si la suma coincide con el tamaño de tu conjunto de prueba, la matriz está bien construida. Compara también los valores de precision y recall que calculaste a mano con los que aparecen en el classification_report: deben coincidir hasta el segundo decimal.
Conclusión
Con estos pasos pasaste de un único porcentaje a una lectura completa del comportamiento del modelo, distinguiendo los errores que más cuestan (aquí, los falsos negativos). El siguiente paso natural es probar a ajustar el umbral de decisión (threshold) o mirar el F1-score, que equilibra precision y recall, y después repetir el análisis para problemas con más de dos clases. ¿Qué métrica es más crítica en tu problema: evitar falsos positivos o no dejar escapar falsos negativos?