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.
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.
Elige una respuesta y tu grado de seguridad.
Responde para desbloquear el experimento.
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.
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.
Descargar el notebook (.ipynb). Ábrelo en Jupyter o súbelo a Google Colab; descarga por sí solo los datos que falten.
Para profesionales
- Ajusta cada paso aprendido (escalado, imputación, selección de variables) dentro de cada pliegue. En scikit-learn, ponlos en un
Pipeliney pásalo across_val_score. - En clasificación usa pliegues estratificados, para que cada pliegue tenga todas las clases.
cross_val_scorelo hace por defecto en los clasificadores cuandocves 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_wineestá ordenado por clase, así que pasaStratifiedKFold(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.
¿Te ha sido útil?
¡Gracias! Nos ayuda a mejorar.
Profundiza en el Atlas
Entradas de la enciclopedia sobre las ideas de esta lección: