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—.
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)$$
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.
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.
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 !