Validación cruzada y k-fold cross-validation

En este artículo veremos en qué consiste la validación cruzada y el algoritmo k-fold cross-validation, uno de los métodos más usados para el entrenamiento y validación de modelos de Machine Learning.

¡Así que listo, comencemos!

Video

Como siempre, en el canal de YouTube se encuentra el video de este post:

Introducción

En un artículo anterior vimos cómo usar los sets de entrenamiento, validación y prueba para encontrar los parámetros de un modelo y para elegir el mejor modelo de entre varios posibles.

Sin embargo, no siempre resulta conveniente usar este enfoque y muchas veces resulta más adecuado usar una alternativa que se conoce como la validación cruzada.

Así que en este artículo vamos a entender qué es la validación cruzada y vamos a ver en detalle y con un ejemplo práctico cómo funciona uno de los principales métodos utilizados que se conoce como k-fold cross-validation.

Repaso: parámetros e hiperparámetros

Antes de ver en qué consiste la validación cruzada vale la pena recordar qué son los parámetros e hiperparámetros de un modelo, de los cuales ya hablamos en un artículo anterior.

Uno de los objetivos del Machine Learning es la construcción de un modelo, que sea capaz de tomar datos de entrada y generar predicciones.

Y cuando construimos el modelo lo que buscamos es encontrar una serie de parámetros, que son simplemente los coeficientes numéricos internos del modelo y que se encuentran durante el proceso de entrenamiento.

Además, para construir ese modelo debemos definir los hiperparámetros, que son también unos coeficientes numéricos pero que nosotros, como programadores del algoritmo de entrenamiento tenemos que definir buscando generar las mejores predicciones posibles.

Repaso: selección del mejor modelo

Además, usualmente es necesario entrenar múltiples modelos, cada uno con diferentes parámetros e hiperparámetros, para luego decidir cuál de todos es el más adecuado para los datos que estamos procesando.

Y para hacer esto debemos ajustar los parámetros e hiperparámetros de cada modelo, cuantificar su desempeño y seleccionar aquel que genere las mejores predicciones (es decir, aquel modelo con el mejor desempeño).

La capacidad de generalización de un modelo

Y en todo esto entra en juego un concepto muy importante que se conoce como la capacidad de generalización de un modelo, que es simplemente su capacidad para hacer buenas predicciones en datos que no ha visto antes.

Entendamos esto con un ejemplo: supongamos que queremos construir un modelo que tome variables como el peso, la edad y algunos hábitos de las personas (como la cantidad de horas de ejercicio que hace semanalmente, por ejemplo) y con ello prediga si el sujeto tiene o no problemas cardiacos.

De nada sirve contar con un modelo que durante el entrenamiento acierte en la clasificación el 99% de las veces si al momento de presentarle nuevos datos, que nunca antes ha visto, esta tasa de aciertos se reduce a tan sólo al 70%.

Es decir, lo ideal sería que en condiciones reales (con datos nunca antes vistos) este desempeño fuese cercano al 99% obtenido durante el entrenamiento.

Los sets de entrenamiento, validación y prueba

Y para entrenar el modelo y evaluar su capacidad de generalización podemos usar los sets de entrenamiento, validación y prueba.

Con este enfoque tomamos nuestro set de datos y lo partimos en tres: entrenamiento (con aproximadamente el 70% de los datos), validación y prueba (cada uno con aproximadamente el 15% de los datos).

El set de entrenamiento nos permite obtener los parámetros del modelo y el de validación nos permite ajustar los hiper-parámetros y seleccionar el mejor modelo de entre varios posibles, mientras que el set de prueba nos permite medir la capacidad de generalización del modelo.

El problema de este enfoque es que para poder usarlo debemos tener una gran cantidad de datos (usualmente cientos de miles o incluso millones), lo cual no siempre es viable.

Pero además, al hacer la partición no necesariamente los tres sub-sets tendrán una distribución similar. Así, el set de entrenamiento puede contener datos ligeramente diferentes de los de validación y prueba y esto afecta tanto el entrenamiento como la validación del modelo.

Y por otra parte, al ajustar los parámetros y los hiperparámetros siempre con los mismos sets (de entrenamiento y validación) podríamos tener un modelo que se sobre-ajusta a los datos: el modelo tenderá a “memorizar” los datos de entrenamiento y validación y no genera buenas predicciones con el set de prueba (esto se conoce como overfitting).

La validación cruzada es precisamente una alternativa a estos inconvenientes, así que veamos en qué consiste.

La validación cruzada y k-fold cross-validation

La idea de la validación cruzada es simple: en lugar de usar diferentes sets para entrenamiento y validación ¡en la validación cruzada usaremos todos los datos!

Y aunque existen muchos métodos para lograr este objetivo el método más usado es el de la “validación cruzada de k iteraciones”, más conocida por su término en Inglés k-fold cross-validation.

Así que en lo que queda de este artículo nos enfocaremos en este tipo de validación. Veamos primero la estructura general del algoritmo y luego lo entenderemos con un ejemplo.

El algoritmo k-fold cross-validation

El algoritmo comienza con la mezcla aleatoria de los datos y con la inicialización del parámetro k que es simplemente un número entero que definirá el número de particiones de nuestro set de datos así como el número de iteraciones de entrenamiento y validación que se usarán al construir el modelo. Esto es lo que le da el nombre precisamente a este algoritmo.

Una vez definido el valor de k inicia este proceso de entrenamiento y validación. Así que por un total de k iteraciones se repiten estos pasos:

  1. Se toma una de las k particiones y se mantiene “oculta” al modelo
  2. Se toman las k-1 particiones restantes y con ellas se entrena el modelo (es decir se calculan de forma automática los parámetros, a través del algoritmo de entrenamiento)
  3. Una vez entrenado el modelo se almacena su desempeño para con el set de entrenamiento (k-1 particiones) y con el set oculto.

Luego se repiten los tres pasos anteriores pero cambiando la partición que se mantiene oculta.

Y una vez terminadas las iteraciones tendremos k medidas de desempeño para los sets de entrenamiento y validación usados en cada iteración. Así que el desempeño final del modelo será simplemente el promedio de los desempeños anteriores.

K-fold cross-validation: ejemplo práctico

Entendamos el algoritmo anterior con un ejemplo práctico. Volvamos al caso hipotético de la construcción de un modelo para predecir si una persona tiene o no problemas cardiacos.

Y para simplificar las cosas supondremos un set de datos muy pequeño (tan sólo 12 datos) y vamos a asumir que mediremos el desempeño como la exactitud que corresponde a la proporción de datos clasificada correctamente con respecto a la totalidad de datos.

En este caso el algoritmo comienza con la mezcla aleatoria de los datos, con lo cual podremos garantizar que el orden en el que presentemos los datos al modelo no afectará su desempeño.

Ahora asumamos que el valor de k es igual a 3. Es decir que partiremos el set de 12 datos en tres bloques (o “folds”) cada uno con un total de 4 datos.

Y ahora comenzamos las iteraciones de entrenamiento y validación. Como el valor de k es igual a 3, realizaremos tres iteraciones:

¡Perfecto!. Terminadas las iteraciones el último paso del algoritmo es determinar el desempeño final del modelo durante el entrenamiento y la validación.

Para el caso del entrenamiento simplemente tomamos los desempeños obtenidos durante las tres iteraciones de entrenamiento (es decir 82%, 84% y 80%) y los promediamos, obteniendo una exactitud promedio del 82%.

Y hacemos algo similar con los desempeños obtenidos durante las tres evaluaciones (es decir 80%, 81% y 79%) obteniendo una exactitud promedio del 80%.

Vemos que los desempeños durante entrenamiento y validación son muy similares y por tanto podemos concluir que no hay sobre-ajuste (u overfitting). Con esto confirmamos que el modelo ha sido entrenado y validado correctamente y que tiene una buena capacidad de generalización (pues la exactitud promedio de validación es muy cercana a la obtenida en el entrenamiento).

¿Cuál es el valor más adecuado del parámetro k?

Una pregunta obvia que surge tras haber visto cómo funciona el algoritmo es ¿cuántas particiones son las más adecuadas? Es decir, ¿cuál debería ser el valor de k?

En realidad no existe una única solución pues todo depende tanto de los datos que tengamos como del modelo que estemos entrenando.

Sin embargo, podemos analizar algunas situaciones extremas y con base en esto definir un rango de valores que podría resultar adecuado.

Si escogemos el valor más pequeño de k (es decir 2) tendremos tan sólo 2 particiones y es posible que el modelo no detecte adecuadamente los patrones en los datos, lo que hace que la mayoría de las predicciones sean erróneas.

Por otra parte, si escogemos un valor de k muy grande (comparado con el tamaño del set de datos) tendremos demasiadas particiones y cada una de ellas contendrá muy pocos datos. Esto hará que haya demasiada variabilidad en el desempeño entre una y otra partición y por tanto el entrenamiento y validación no resultarán fiables.

Además, si nuestro set de datos tiene muchos datos y a la vez usamos demasiadas particiones requeriremos más recursos computacionales para poder entrenar y validar el modelo por un total de k iteraciones.

Así que usualmente lo que se hace es usar valores intermedios de k dependiendo del tamaño del set de datos, es decir ni muy pequeños ni muy grandes. Por ejemplo, cuando tenemos unos cuantos cientos o algunos miles de datos generalmente podríamos usar valores de k iguales a 5, 10 o 20.

Y, lo que sí podemos hacer es entrenar y validar el modelo con por ejemplo estos tres valores y verificar cuál de ellos nos genera los mejores resultados para el modelo y set de datos que estemos usando en particular.

Conclusión

Muy bien, acabamos de ver en qué consiste la validación cruzada y específicamente uno de los algoritmos más usados que se conoce como k-fold cross-validation.

Esta validación cruzada es una alternativa a la partición del set de datos en entrenamiento, validación y prueba del que hablamos en un artículo anterior.

Y tiene además varias ventajas con respecto a ese método. La primera de ellas es que funciona para casos en los cuales tenemos relativamente pocos datos (es decir unos cuantos cientos o varios miles de datos).

La segunda ventaja es que nos da una validación más robusta, pues al final el modelo terminará siendo entrenado y validado con la totalidad de los datos. Así que con la validación cruzada tendremos una medida bastante fiable de la capacidad de generalización del modelo.

Y la tercera ventaja es que al entrenar y validar el modelo con diferentes porciones del set de datos evitaremos problemas como el sobre-ajuste u overfitting, lo que mejora nuevamente su capacidad de generalización.

Tal vez una de las desventajas de este método es su costo computacional pues al tener muchos datos y muchas particiones, debemos repetir el algoritmo de entrenamiento varias veces lo que hace que el entrenamiento y la validación requieran más tiempo en comparación con el enfoque de entrenamiento, validación y prueba.

Si quieres profundizar sobre varios de los temas que acabo de mencionar en este artículo, te invito a leer estos artículos relacionados: