← Todos los capítulos
Capítulo 3 · Clasificación

Un modelo que no aprendió nada
y aun así acertó el 91%

70,000 dígitos escritos a mano. El objetivo del capítulo no es clasificarlos — es aprender a medir un clasificador, que resulta bastante más resbaladizo que medir una regresión.

Mejor exactitud0.976k-vecinos + aumento
Imágenes70,00028×28 píxeles
Ejercicios4 de 4del capítulo
Datasets3MNIST · Titanic · correo
El gancho del capítulo

La exactitud miente cuando una clase es rara

El primer ejercicio es un detector de una sola cosa: ¿esta imagen es un 5?

Solo el 9% de las imágenes son cincos. Así que un modelo que responda “no es un 5” a todo acierta el 91% de las veces sin haber mirado un solo píxel. Ese modelo tonto se entrena a propósito, para ponerlo al lado del real:

Clasificador real0.9696
Responder «no es 5» a todo0.9096

Seis puntos separan un modelo que aprendió de uno que no hizo nada. Y en la práctica las clases raras son la norma, no la excepción: el fraude, la enfermedad, la falla del equipo. Ahí la exactitud regala el 90% de entrada.

Lo que sí distingue
MétricaQué respondeValor
PrecisiónDe lo que llamó 5, ¿cuánto era 5?0.809
ExhaustividadDe todos los 5 que había, ¿cuántos encontró?0.868
F1Media armónica — penaliza el desequilibrio entre ambas0.838
Todas se calculan con validación cruzada: cada imagen la puntúa un modelo que no la vio al entrenarse. Medirlas sobre el propio entrenamiento daría números inflados.
La decisión que no es técnica

Precisión y exhaustividad se mueven en direcciones opuestas

Un clasificador no responde sí o no: calcula una puntuación y la compara contra un umbral. Subirlo lo vuelve más exigente — se equivoca menos cuando dice “sí”, pero se le escapan más.

Subir el umbral sube una métrica y baja la otra
Precisión y exhaustividad trazadas contra el umbral de decisión; las curvas se cruzan
Pedirle 90% de precisión a este modelo cuesta bajar la exhaustividad a 0.789: para fallar solo 1 de cada 10 veces que dice “es un 5”, deja escapar 1 de cada 5 cincos.

Dónde pararse en esa curva no es una decisión técnica. Un filtro de spam quiere precisión — mandar un correo importante a la basura es peor que dejar pasar publicidad. Un detector de tumores quiere exhaustividad — revisar de más es un susto, pasar uno por alto es otra cosa. Mismo modelo, distinto punto de operación, según lo que cueste equivocarse.

Comparar modelos sin fijar un umbral
Curva ROC comparando un modelo lineal y un bosque aleatorio
El área bajo la curva resume el desempeño en todos los umbrales a la vez: 0.971 para el modelo lineal, 0.998 para el bosque.

⚠️ Pero esta métrica engaña cuando la clase positiva es rara. La curva ROC usa la proporción de falsos positivos, y con 54,000 negativos contra 5,400 positivos el denominador es tan grande que la curva se ve optimista. Para clases desbalanceadas, la curva de precisión contra exhaustividad cuenta la verdad más incómoda.

Lo más útil del capítulo

Qué arreglar, no cuánto fallas

Saber que el modelo acierta el 91% no dice qué hacer después. La matriz de confusión sí: muestra qué dígito se confunde con cuál.

La diagonal hay que borrarla para ver algo
Dos matrices de confusión: con la diagonal y sin ella
Sin normalizar, la diagonal se lleva todo el color y los errores son invisibles. Normalizada por fila y con la diagonal en cero, aparece el patrón: el peor par es el 4 confundido con el 9, en el 5.1% de los casos.
Y aquí está el valor real del ejercicio
Montaje de imágenes de 4 y 9 correctamente clasificados y confundidos
Los 4 mal clasificados tienen la parte superior cerrada; los 9 mal clasificados la tienen abierta.

El modelo no está siendo tonto — esos dígitos son genuinamente ambiguos incluso para una persona. Y eso cambia qué se hace después.

No es “entrena más”: un modelo lineal ve píxeles sueltos y no puede representar «tiene un lazo cerrado arriba», que es justamente la diferencia entre un 4 y un 9. La solución no está en este capítulo, está en el 14 — redes convolucionales, que sí capturan forma.

Cuando la respuesta ya no es una etiqueta
Tres filas de dígitos: con ruido, limpiados por el modelo, y originales
Entrenar con imágenes ruidosas como entrada y limpias como objetivo: 784 salidas, cada una con 256 valores posibles. El error medio por píxel baja de 45.5 a 15.2.

Este ejercicio deja clara una frontera borrosa: quitar ruido de una imagen suena a regresión, no a clasificación. La distinción no siempre es nítida — las categorías del libro son herramientas, no compartimentos.

Los ejercicios

Dos errores que costaron más que los modelos

El Titanic: once puntos escondidos en el orden del archivo

0.70 → 0.81

La primera corrida daba 0.70 de exactitud, muy por debajo de lo normal en este dataset. La causa no era el modelo: el archivo viene ordenado por clase de pasaje, así que sin barajar, el primer pliegue de la validación cruzada era 100% primera clase y los dos últimos 100% tercera. El modelo se entrenaba con un perfil de pasajero y se evaluaba con otro.

Lo insidioso es que la partición estratificada no lo detecta: equilibra la supervivencia, no la clase. Basta barajar para pasar de 0.70 a 0.81. Es la lección del capítulo anterior —la partición importa— reapareciendo con otra cara.

El filtro de spam: elegir por una sola métrica también engaña

84 spam contra 28

3,000 correos reales, con cabeceras, HTML y codificaciones rotas. Aquí la precisión pesa más que la exhaustividad: mandar un correo legítimo a la basura es mucho peor que dejar pasar publicidad.

Pero optimizar solo precisión lleva a otro sitio. La regresión logística alcanza precisión perfecta —cero legítimos perdidos— a cambio de dejar pasar84 spam. El SVM lineal pierde 2 legítimos y solo deja pasar 28. Cuál conviene depende de cuánto duele cada error, y ninguna métrica sola lo responde.

k-vecinos, y una máquina congelada

3.00 GB → 0.49 GB

El ejercicio pide superar el 97% de exactitud. Se logra con k-vecinos afinado (0.9714) y sube a 0.9763 replicando cada imagen desplazada un píxel en las cuatro direcciones — el conjunto pasa de 60,000 a 300,000.

Pero la primera versión del script agotó la memoria de una máquina de 16 GB. Pedía paralelismo en dos niveles a la vez: la búsqueda lanzaba diez procesos, cada uno con su copia completa de los datos, y cada uno pedía otros diez hilos.

El culpable oculto fue un valor por defecto: scikit-learn reserva hasta1 GB por hilo para los bloques de distancias. Con diez núcleos, diez gigas. Bajarlo a 128 MB y usar precisión simple llevó el pico de 3.00 GB a 0.49 GB — y encima quedó más rápido.

El error de método fue peor que el bug: la estimación de costo se midió con una configuración y después se escribió el script con otra, sin volver a medir.

Detalles
Datos
MNIST, 70,000 dígitos de 28×28. Partición canónica 60k/10k, sin barajar.
Por qué no se baraja
Las 10,000 imágenes de prueba son las mismas desde 1998 y todos los resultados publicados las usan. Además vienen de personas distintas a las del entrenamiento — empleados del censo contra estudiantes.
Ejercicios
Los cuatro: k-vecinos afinado, aumento de datos, Titanic y filtro de spam.
Seguimiento
MLflow, mismo registro que el capítulo 2.