Noventa y seis por ciento, e inútil
Un filtro de spam se prueba con 1000 mensajes. Acierta 960 veces, así que saca un 96 por ciento. El equipo está contento.
Entonces alguien descubre que el filtro dice «no es spam» a todos los mensajes sin excepción. Cuarenta de los 1000 eran spam. Una sola nota escondió todo el fallo.
Al final de esta lección
Nota
Puedo juzgar un clasificador con una matriz de confusión, la precisión y la exhaustividad, y no solo con la exactitud.
Palabras clave
| Palabra | Qué significa |
|---|---|
| Exactitud | la parte de todos los mensajes que el modelo clasificó bien |
| Desequilibrada | una etiqueta es mucho más frecuente que la otra |
| Matriz de confusión | una tabla de respuestas buenas y malas para cada etiqueta |
| Precisión | de los mensajes señalados, la parte que de verdad era spam |
| Exhaustividad | del spam real, la parte que se señaló (en inglés, recall) |
| Umbral | la puntuación a partir de la cual se señala un mensaje |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
La exactitud es un número para dos errores
La exactitud cuenta igual todas las respuestas correctas. Sirve cuando las etiquetas son más o menos igual de frecuentes.
Falla cuando la tabla está desequilibrada. Si 40 mensajes de 1000 son spam, un modelo que nunca dice «spam» acierta 960 veces. Acierta el 96 por ciento de las veces y no halla nada de spam.
Puntuar un modelo que nunca dice spam
docker exec jupyter python3 -c "t=[1]*40+[0]*960; g=[0]*1000; print(sum(a==b for a,b in zip(t,g))/1000)"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Contar las cuatro clases de respuesta
El spam es lo que buscamos: llámalo positivo. Cada mensaje cae en una de cuatro casillas.
Detectado: spam, señalado. Falsa alarma: no es spam, señalado. Pasado por alto: spam, sin señalar. Rechazo correcto: no es spam, sin señalar. Los cuatro recuentos juntos son la matriz de confusión.
Ejemplo resuelto: un filtro con 1000 mensajes
| Señalados como spam | Sin señalar | |
|---|---|---|
| De verdad spam (40) | Detectados: 30 | Pasados por alto: 10 |
| No es spam (960) | Falsas alarmas: 20 | Rechazos correctos: 940 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Imprimir la matriz, la precisión y la exhaustividad
docker exec jupyter python3 -c "from sklearn.metrics import confusion_matrix, precision_score, recall_score; t=[1]*40+[0]*960; g=[1]*30+[0]*10+[1]*20+[0]*940; print(confusion_matrix(t,g)); print(round(precision_score(t,g),3), round(recall_score(t,g),3), (30+940)/1000)"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Precisión y exhaustividad preguntan cosas distintas
La precisión pregunta: cuando el filtro dice spam, ¿acierta a menudo? Aquí, 30 de los 50 señalados, o sea 0,6.
La exhaustividad pregunta: del spam real, ¿cuánto halló el filtro? Aquí, 30 de 40, o sea 0,75. La exactitud era 0,97. El filtro es mejor que el que nunca dice spam, pero la exactitud apenas muestra cuánto.
Mover el umbral cambia una por otra
La mayoría de los modelos dan una puntuación, y un umbral la convierte en etiqueta. Si bajas el umbral, se señalan más mensajes. Se detecta más spam, pero también se señala más correo bueno.
Así que la precisión y la exhaustividad tiran en sentidos contrarios, y una persona tiene que elegir. Ejecuta el código y mira cómo se mueven los recuentos.
Cuatro umbrales con diez mensajes
# Diez mensajes: la puntuación que dio un modelo (de 0 a 1) y si de verdad era spam.
messages = [
(0.95, 1), (0.9, 1), (0.8, 0), (0.7, 1), (0.6, 0),
(0.5, 1), (0.4, 0), (0.3, 0), (0.2, 0), (0.1, 0),
]
for limit in [0.9, 0.7, 0.5, 0.3]:
caught = 0
false_alarms = 0
missed = 0
for score, spam in messages:
flagged = score >= limit
if flagged and spam == 1:
caught = caught + 1
if flagged and spam == 0:
false_alarms = false_alarms + 1
if not flagged and spam == 1:
missed = missed + 1
print("umbral", limit, "detectados", caught, "falsas alarmas", false_alarms, "pasados por alto", missed)
# ¿Qué umbral elegirías para un buzón de correo? ¿Y para un banco?
Ejemplo resuelto: lo que da cada umbral
| Umbral | Detectados | Falsas alarmas | Pasados por alto | Precisión | Exhaustividad |
|---|---|---|---|---|---|
| 0.9 | 2 | 0 | 2 | 1.0 | 0.5 |
| 0.7 | 3 | 1 | 1 | 0.75 | 0.75 |
| 0.5 | 4 | 2 | 0 | 0.667 | 1.0 |
| 0.3 | 4 | 4 | 0 | 0.5 | 1.0 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un error frecuente
Advertencia
Mucha gente cree que el mejor umbral es el de mejor nota en un solo número. No hay mejor umbral sin conocer el coste. Un buzón puede vivir con algo de spam. Un control de fraude no puede dejar pasar ninguno.
Para ir más lejos: el coste del error
Supón que un spam pasado por alto cuesta 1 minuto de lectura y que una falsa alarma cuesta 5 minutos buscando un mensaje perdido. Usa la tabla de los cuatro umbrales.
Calcula los minutos perdidos con cada umbral. ¿Qué umbral cuesta menos? ¿Cambiaría si una falsa alarma costara solo 1 minuto?