En el tema anterior vimos que la exactitud no siempre alcanza para evaluar un clasificador. Ahora vamos a profundizar en las herramientas que permiten entender qué tipo de aciertos y qué tipo de errores está cometiendo el modelo.
Eso es importante porque no todos los errores cuestan lo mismo. En algunos problemas, dejar pasar un caso positivo es grave. En otros, marcar demasiados positivos también puede ser un problema.
La matriz de confusión resume cómo se comparan las predicciones del modelo con los valores reales.
En un problema binario aparecen cuatro situaciones:
La utilidad de esta tabla es que deja de ocultar los errores dentro de un único número global.
Supongamos un sistema que intenta detectar si un paciente tiene una enfermedad:
En un problema médico, un falso negativo suele ser muy delicado, porque significa no detectar a tiempo un caso real.
La precisión responde a esta pregunta:
De todos los casos que el modelo marcó como positivos, ¿cuántos eran realmente positivos?
Si la precisión es baja, significa que el modelo está generando muchos falsos positivos.
En términos prácticos, la precisión importa cuando queremos que una predicción positiva sea confiable.
El recall responde a otra pregunta:
De todos los casos positivos reales, ¿cuántos logró detectar el modelo?
Si el recall es bajo, significa que el modelo está dejando escapar muchos positivos reales, es decir, tiene muchos falsos negativos.
Esta métrica es muy valiosa cuando detectar los casos positivos es especialmente importante.
La métrica F1 combina precisión y recall en un solo valor. No es un simple promedio común: está diseñada para penalizar situaciones donde una de las dos métricas es buena y la otra es mala.
Por eso, F1 resulta útil cuando necesitamos equilibrio entre ambas.
Vamos a usar un ejemplo pequeño y explícito. El objetivo es predecir si un paciente tiene una enfermedad a partir de dos variables:
Después de entrenar el modelo, construiremos la matriz de confusión y calcularemos precisión, recall y F1.
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score, accuracy_score
pacientes = pd.DataFrame({
"edad": [25, 30, 34, 38, 40, 43, 46, 50, 54, 58, 61, 65],
"marcador": [0.8, 1.0, 1.1, 1.4, 1.5, 1.7, 2.0, 2.1, 2.4, 2.6, 2.8, 3.0],
"enfermedad": [0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1]
})
X = pacientes[["edad", "marcador"]]
y = pacientes["enfermedad"]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.33, random_state=42, stratify=y
)
modelo = LogisticRegression()
modelo.fit(X_train, y_train)
y_pred = modelo.predict(X_test)
matriz = confusion_matrix(y_test, y_pred)
print("Valores reales:", y_test.values)
print("Predicciones:", y_pred)
print("Matriz de confusión:")
print(matriz)
print("Exactitud:", accuracy_score(y_test, y_pred))
print("Precisión:", precision_score(y_test, y_pred))
print("Recall:", recall_score(y_test, y_pred))
print("F1:", f1_score(y_test, y_pred))
nuevo_paciente = pd.DataFrame({
"edad": [52],
"marcador": [2.3]
})
prediccion = modelo.predict(nuevo_paciente)[0]
probabilidad = modelo.predict_proba(nuevo_paciente)[0, 1]
print("Predicción para el nuevo paciente:", prediccion)
print(f"Probabilidad de enfermedad: {probabilidad:.3f}")
Salida resumida esperada:
Valores reales: [...]
Predicciones: [...]
Matriz de confusión:
[[... ...]
[... ...]]
Exactitud: ...
Precisión: ...
Recall: ...
F1: ...
Predicción para el nuevo paciente: ...
Probabilidad de enfermedad: ...
En Scikit-learn, la matriz de confusión de un problema binario suele organizarse así:
Eso permite ver enseguida si el modelo se equivoca más por exceso de alarmas o por no detectar casos reales.
La conexión práctica es esta:
Por eso la matriz de confusión y estas métricas deben leerse juntas. Una tabla te muestra el detalle; las métricas te dan un resumen numérico.
Depende del problema:
No existe una métrica “mejor” en abstracto. Existe una métrica más coherente con el costo de error del problema real.
confusion_matrix(y_test, y_pred): construye la tabla de aciertos y errores.precision_score(...): mide la calidad de las predicciones positivas.recall_score(...): mide cuántos positivos reales fueron detectados.f1_score(...): resume el equilibrio entre precisión y recall.predict_proba(...): devuelve la probabilidad estimada de la clase positiva.El código es corto, pero conceptualmente muy importante. Con pocas líneas ya podemos entender bastante mejor el comportamiento del modelo.