ML Atlas

Machine learning desde cero · Lección 3.2 · 15 de 33 lecciones listas · 10 min

Validación y validación cruzada

En pocas palabras

Elegir ajustes con el conjunto de prueba lo estropea. La validación cruzada evalúa con cada parte de los datos por turnos y muestra si la nota es estable.

Calentamiento Dos preguntas de lecciones anteriores. Un minuto, y no bloquea la lección.
De la lección 3.1: Sobreajuste: cuando un modelo memoriza ¿Por qué más datos de entrenamiento suelen hacer más seguro un modelo flexible?

Ver la respuesta

Respuesta correcta: Porque con más puntos el ruido se promedia y la curva ya no persigue puntos sueltos

El ruido de cada punto sigue ahí, pero con muchos puntos se compensa, así que el ajuste sigue la tendencia real.

De la lección 2.6: Métrica y umbral según el coste de los errores Un fallo cuesta 10, una falsa alarma 1, y el modelo está calibrado. ¿Qué umbral sale de la teoría de la decisión?

Ver la respuesta

Respuesta correcta: 1 / (1 + 10) ≈ 0,09, porque la alarma ya compensa con un riesgo pequeño

La alarma compensa cuando p · 10 > (1 − p) · 1, es decir, p > 1/11. En el lab el umbral 0,09 cuesta 125. El umbral más barato, 0,06, cuesta 111 solo en las puntuaciones con las que se eligió.

En la lección anterior elegimos el mejor grado del polinomio echando un vistazo al conjunto de prueba. Parecía inofensivo, pero piensa en lo que significa: probamos varios modelos y nos quedamos con el que más le gustó al conjunto de prueba. Ese conjunto ya no es un examen que nunca vimos; se ha convertido en un juez al que consultamos mientras nos preparábamos. ¿Cómo elegir ajustes sin estropear nuestra única medida honesta? Pruébalo tú mismo antes de leer la explicación.

Predice y comprueba Subes el número de pliegues k de 2 a 10 (178 vinos en total). ¿Qué ocurre con la diferencia entre el peor y el mejor pliegue?
¿Qué tan seguro estás?

Experimento interactivo

Este experimento interactivo funciona en un navegador con JavaScript activado. El texto que lo rodea describe lo que muestra.

Ver la respuesta

Respuesta correcta: Aumenta, porque cada pliegue de prueba tiene menos vinos

Con k = 2 el peor pliegue tiene un 94,4 % y el mejor un 97,8 % (diferencia de 3,4 puntos). Con k = 10 el rango va del 83,3 % al 100,0 % (16,7 puntos), porque un pliegue de prueba tiene solo 17 o 18 vinos y un error pesa más de 5 puntos. La media apenas cambia (96,1 % y 96,7 %).

Prueba esto

  • Pon el control de k en su valor más pequeño y lee la exactitud de cada pliegue. ¿Cuánto se diferencian los pliegues entre sí?
  • Sube el control de k paso a paso. Observa la media y la dispersión, y fíjate en que cada pliegue contiene ahora menos vinos.
  • Con un k grande, busca pliegues con una exactitud inusualmente baja o alta. Con solo un puñado de vinos en un pliegue, un solo error mueve mucho la puntuación de ese pliegue.
  • Compara la dispersión con las diferencias entre ajustes que quizá quieras afinar. ¿Una pequeña mejora en la media es mayor que la dispersión?

La idea en pocas palabras

La primera solución es un tercer montón de datos. Divide las filas en conjuntos de entrenamiento, validación y prueba. Entrena los modelos candidatos con el conjunto de entrenamiento, compáralos con el de validación, elige al ganador y solo entonces abre el conjunto de prueba, una vez, para informar la puntuación final. El conjunto de validación absorbe todos los vistazos para que el de prueba no tenga que hacerlo.

El problema: cada división cuesta datos. Con un conjunto de datos pequeño, un conjunto de validación lo bastante grande para ser fiable deja muy poco para entrenar, y la lección 2 mostró que un conjunto pequeño da una puntuación que salta. La validación cruzada lo resuelve reutilizando los datos con ingenio.

Imagina que tienes que evaluar a una cocinera nueva. Probar un solo plato dice poco: quizá fue el mejor que hace, quizá el peor. Así que le pides varios platos en días distintos y miras el promedio y cuánto varían. La validación cruzada hace lo mismo con un modelo.

Por qué funciona

En la validación cruzada de k pliegues, los datos (sin contar el conjunto de prueba final) se cortan en k partes iguales llamadas pliegues (folds). El modelo se entrena k veces. En cada una, un pliegue se reserva para la validación y los k − 1 restantes se usan para entrenar. Al final, cada fila se ha usado exactamente una vez para validar y k − 1 veces para entrenar. Cada entrenamiento ve esta proporción de los datos:

proporción de entrenamiento = (k − 1) / k

El resultado no es una puntuación, sino k puntuaciones, una por pliegue. Su media es una estimación más fiable que cualquier división única, porque no depende de un reparto de filas con buena o mala suerte. Su dispersión es igual de valiosa: muestra cuánto depende la puntuación de qué filas le tocaron al modelo. Dos modelos cuyas medias difieren menos que esa dispersión no se pueden distinguir de verdad.

Elegir k es un compromiso. Un k pequeño (por ejemplo 2) entrena cada modelo con solo la mitad de los datos, así que cada modelo es más débil que el que construirás al final, y la estimación es pesimista. Un k grande entrena con casi todos los datos, pero cada pliegue es pequeño, así que las puntuaciones de cada pliegue se vuelven más ruidosas, y el cálculo tarda k veces lo que un solo ajuste. Los valores 5 o 10 son un compromiso habitual.

El ejemplo de esta lección es el conjunto de datos Wine: 178 vinos de una misma región de Italia, elaborados con tres cultivares de uva distintos, cada uno descrito con 13 resultados de un análisis químico. La tarea es distinguir los tres cultivares.

Error frecuente

La validación cruzada solo te protege si todo lo que se aprende de los datos ocurre dentro de cada pliegue. Si primero escalas las características o seleccionas las «mejores» usando todas las filas y después haces la validación cruzada, la información de los pliegues de validación ya se ha filtrado al entrenamiento y las puntuaciones son demasiado optimistas. El segundo error es afinar decenas de ajustes con validación cruzada e informar la mejor puntuación de validación cruzada como resultado final. Tras tantas comparaciones, el ganador tiene parte de suerte; por eso sigue importando un conjunto de prueba aparte, usado una sola vez.

Con la evaluación honesta en nuestra caja de herramientas podemos explorar modelos más potentes sin engañarnos. En la próxima lección conocemos el más legible de todos: el árbol de decisión.

Test

Tres preguntas para comprobar lo aprendido. Elige una respuesta o despliega la solución bajo cada pregunta. Con el teclado: las flechas eligen, Enter o Espacio confirma.

1. En una validación cruzada de 5 pliegues, ¿cuántas veces se usa cada fila para validar?
Ver la respuesta

Respuesta correcta: Exactamente una vez, en el pliegue que le toca

Cada fila pertenece a un pliegue, y cada pliegue hace de conjunto de validación en exactamente una de las cinco ejecuciones.

2. El modelo A tiene una exactitud media de validación cruzada algo superior a la del modelo B, pero la dispersión entre pliegues es mucho mayor que la diferencia. ¿Qué se deduce?
Ver la respuesta

Respuesta correcta: Que los datos no muestran una diferencia fiable entre los dos modelos

Cuando la diferencia de medias es menor que la variación entre pliegues, puede deberse fácilmente al azar.

3. ¿Por qué es un error escalar las características con todas las filas antes de la validación cruzada?
Ver la respuesta

Respuesta correcta: Porque información de la validación se filtra al entrenamiento y las puntuaciones salen demasiado optimistas

Cada paso que aprende de los datos debe ajustarse solo con los pliegues de entrenamiento; si no, los pliegues de validación dejan de ser datos no vistos.

Ideas clave

  • Elegir ajustes con el conjunto de prueba lo estropea; usa en su lugar un conjunto de validación o validación cruzada.
  • En la validación cruzada de k pliegues, cada fila se usa para validar exactamente una vez.
  • La media de las puntuaciones de los pliegues estima el rendimiento; la dispersión muestra cuánto depende de la división.
  • Toda preparación que aprende de los datos debe hacerse dentro de cada pliegue para evitar fugas.

Más a fondo: fórmula, código, práctica

Las matemáticas

En la validación cruzada de k pliegues, las n filas se cortan en k pliegues. Cada ajuste entrena con n · (k − 1) / k filas y prueba con las n / k restantes. La puntuación es el promedio de los pliegues: CV = (1/k) · Σ score_f. La dispersión es su desviación estándar s = √( Σ (score_f − CV)² / (k − 1) ).

Un pliegue de m filas de prueba da una exactitud que se mueve en saltos de 1 / m. Si la exactitud verdadera es p, su error estándar es de aproximadamente √( p · (1 − p) / m ). Eso crece al reducirse m, y por eso cada pliegue por separado se vuelve más ruidoso cuando k sube, aunque la media sea menos pesimista. Con 178 vinos y k = 10, un error en un pliegue de 17 o 18 vinos cuesta de 5,6 a 5,9 puntos.

Las puntuaciones de los pliegues no son totalmente independientes: los conjuntos de entrenamiento se solapan. Por eso s / √k subestima la incertidumbre real de la media.

En código (Python)

Los 178 vinos con 5 vecinos más cercanos y variables estandarizadas. Para ver el patrón detrás de la mezcla única del lab, la brecha entre el peor y el mejor pliegue se promedia sobre 20 mezclas. Los pliegues son estratificados y se mezclan con una semilla, así que los números no son los 3,4 y 16,7 puntos del lab:

import numpy as np
from sklearn.datasets import load_wine
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

X, y = load_wine(return_X_y=True)
model = make_pipeline(StandardScaler(), KNeighborsClassifier(n_neighbors=5))  # el escalador se reajusta dentro de cada pliegue
for k in (2, 10):
    runs = [cross_val_score(model, X, y, cv=StratifiedKFold(k, shuffle=True, random_state=s)) for s in range(20)]
    gap = np.mean([a.max() - a.min() for a in runs])
    print(f"k={k:2d}: mean accuracy {np.mean(runs):.3f}, average worst-to-best gap {gap:.3f}")

Resultado

k= 2: mean accuracy 0.956, average worst-to-best gap 0.020
k=10: mean accuracy 0.966, average worst-to-best gap 0.113

La media casi no se mueve (0,956 y 0,966), pero la brecha media entre el peor y el mejor pliegue crece de 0,020 a 0,113 cuando k pasa de 2 a 10.

Para profesionales
  • Ajusta cada paso aprendido (escalado, imputación, selección de variables) dentro de cada pliegue. En scikit-learn, ponlos en un Pipeline y pásalo a cross_val_score.
  • En clasificación usa pliegues estratificados, para que cada pliegue tenga todas las clases. cross_val_score lo hace por defecto en los clasificadores cuando cv es un número, pero ese valor por defecto no mezcla.
  • Mezcla antes de cortar los pliegues si las filas están ordenadas, por ejemplo por clase o por fecha. load_wine está ordenado por clase, así que pasa StratifiedKFold(k, shuffle=True, random_state=0), como arriba. En series temporales no mezcles: usa una partición hacia adelante.
  • Si las filas pertenecen a grupos (varias filas por paciente), mantén cada grupo en un solo pliegue con GroupKFold. Si no, el mismo paciente está en entrenamiento y en validación.
  • Informa la media y la dispersión. Si dos modelos difieren menos que la dispersión, no digas que uno es mejor.

Profundiza en el Atlas

Entradas de la enciclopedia sobre las ideas de esta lección: