Validación Cruzada

Ajuste de modelos: Optimización vs generalización

He escrito esta entrada como una introducción a lo que se cuenta aquí, aquí y aquí sobre el asunto de la relación entre la optimización (como parte del proceso de ajuste de modelos) y la generalización (o su capacidad para aprender sobre el mundo y no solo sobre los datos de entrenamiento). En los enlaces, el lector encontrará planteadas una serie de cuestiones sobre cómo y por qué generalizan los (o cierto tipo de) modelos en lugar de, simplemente, no hacerlo.

Sobre la correlación entre Y y la predicción de Y

Supongamos que tenemos un modelo construido sobre unos datos $(x_i, y_i)$. Para cada $x_i$, el valor $y_i$ es una realización de una variable aleatoria $Y_i$ con distribución $F_i(y)$. Por simplificar, podemos suponer, además, que para el ajuste se utiliza el error cuadrático. Entonces, lo mejor que puede hacer el modelo es encontrar la media $\mu_i$ de cada $Y_i$ —bueno, en realidad, querría encontrar $\mu_x$ para cada $x$ potencial, pero hoy vamos a dejar esa discusión aparcada—.

Sobre el error de generalización (porque a veces se nos olvida)

Al construir modelos, queremos minimizar $$ l(\theta) = \int L(y, f_\theta(x)) dP(x,y),$$ donde $L$ es una determinada función de pérdida (y no, no me refiero exclusivamente a la que tiene un numerillo 2). Pero como de $latex P(x,y)$ solo conocemos una muestra $latex (x_i, y_i)$ (dejadme aprovechar la ocasión para utilizar una de mis palabras favoritas: $latex P(x,y)$ es incognoscible), hacemos uso de la aproximación $$ \int f(x) dP(x) \approx \frac{1}{N} \sum f(x_i)$$

¿Vale realmente el "bootstrap" para comparar modelos?

Es una pregunta legítima —en el sentido de que ignoro la respuesta— que tengo. Para plantearla en sus debidos términos: Contexto: Tenemos modelos y queremos compararlos. Queremos que funcionen en el universo, pero solo disponemos de él una muestra. Acto 1: Para desatascar el nudo lógico, recurrimos a técnicas como: Entrenamiento y validación,j jackknife y sobre todo, su popular evolución, la validación cruzada. Todas ellas bien sabidas y discutidas en todos los manuales.

Validación cruzada en R

Está de moda usar caret para estas cosas, pero yo estoy todavía acostumbrado a hacerlas a mano. Creo, además, que es poco instructivo ocultar estas cuestiones detrás de funciones de tipo caja-negra-maravillosa a quienes se inician en el mundo de la construcción y comparación de modelos. Muestro, por tanto, código bastante simple para la validación cruzada de un modelo con R: # genero ids ids <- rep(1:10, length.out = nrow(cars)) # Nota: da igual si nrow(df) no es múltiplo de 10 # los aleatorizo ids <- sample(ids) # esto devuelve una lista de dfs: preds.

Validación cruzada en paralelo

R
Estoy sin tiempo, así que os suelto el código y me largo a casa a no cenar. Es así: library(parallel) cl <- makeCluster(8) # solo si hay aleatorización # clusterSetRNGStream(cl, 123) clusterEvalQ(cl, { # las librerías necesarias tienen que cargarse # en cada esclavo library(rpart) # en la práctica, hay que cargar los datos # (¿desde fichero?) en cada esclavo my.data <- iris # lo mismo con las funciones necesarias foo <- function(x, dat){ train <- 1:nrow(dat) %% 10 !