El muestreo y el aprendizaje automático van de la mano. En el aprendizaje automático, con frecuencia empezamos con un gran conjunto de datos que queremos usar para predecir algo. Usualmente dividimos estos en datos de entrenamiento, construimos un modelo alrededor de este, y luego damos rienda suelta a un modelo totalmente entrenado en algún tipo de conjunto de datos de prueba para ver cual es la salida final del modelo. En algunos casos será muy difícil poner a correr nuestro modelo de aprendizaje automático en un conjunto de datos entero, mientras que podríamos tener una buena precisión ejecutando una pequeña muestra y probando cuando sea necesario. Esto puede deberse, por ejemplo, al tamaño de los datos.

Primero definamos algunos términos estadísticos. Una población es la colección entera (o universo) de cosas bajo consideración. Una muestra es una porción de población que seleccionamos para el análisis. Así, por ejemplo, podemos empezar con todo un conjunto de datos, tomar un fragmento de este como una muestra y a partir de ahí hacer nuestro entrenamiento. Otra forma de verlo es que algunos datos de los que nos dan para empezar pueden ser solo una muestra de un conjunto de datos mas grande.

Los datos de las encuestas son un ejemplo de muestreo, por lo general, se recopilan haciendo preguntas a las personas sobre datos demográficos específicos. Por diseño, los datos de las encuestas pueden ser solo un conjunto de una población general de un territorio, porque seria un gran logro preguntar a todas las personas de un país cual es su color favorito. Si tenemos un país con una población de 100 millones y hacemos una encuesta con 30 millones de respuestas, estaríamos realizando una especie de muestreo. Para entender completamente el color favorito de todas las personas en un país, necesitamos hacer alguna extrapolación de la muestra a la población para ser capaces de entenderla mejor.

En el mundo de ciencias estadísticas, tenemos valores asociados al total de la población (i.e a nivel nacional) y aquellos asociados con muestras mas pequeñas de población como se muestras en la Figura 3-1

Figura 3-1. Simbolos matemáticos usados para definir técnicas de muestreo estadístico

Cuando hablamos de valores relacionados a los términos media, varianza y desviación estandar con relación a la población total, serán llamados parámetros. Cuando hablamos sobre estos mismos valores, pero relacionados a un subconjunto especifico de datos, los llamamos estadísticas. Entonces, podríamos estar mirando un subconjunto específico de un país y observar la estadística media en este caso, comparándola con el parámetro medio de la población total. Por ejemplo, el número de personas en un país cuyo color favorito es azul seria el parámetro, y el número de personas en una ciudad particular cuyo color favorito es azul seria la estadística. Estos valores pueden ser diferentes entre la población y la muestra, pero también pueden variar entre muestras.

Sesgo

El Sesgo de un muestreo es aquello que pasa cuando se toman las muestras de datos de tal forma que las distribuciones en las muestras de datos no coinciden con la distribución de la población con la cual está trabajando. Suponga que encuesta a un país y el color favorito de la mitad norte es amarillo y de la mitad sur es verde. Si usted fuera a realizar una encuesta solo dirigida para gente de la parte norte, usted tendría que la distribución de color favorito sería enteramente amarilla y viceversa. Su muestra estaría sesgada severamente de cualquier manera. La variación de una muestra es la medida en que una estadística (quizá, comida favorita en lugar de color favorito) difiere de la población. Estos dos pueden ser controlados eligiendo de manera correcta la manera en que hagamos las muestras de datos.

El sesgo y la varianza con muestreo se puede representar de cuatro formas. La Figura 3-2 muestra cuatro blancos de dianas (punto central de un blanco de tiro), con el centro de cada una siendo la población media. Las cruces blancas pueden representar diferentes encuestas que se hicieron (diferentes muestras)

  • Sesgo bajo, varianza baja: El mejor caso y mejor escenario. Las muestras son bastante representativas de la población

  • Sesgo alto, varianza baja: Las muestras son todas bastante consistentes, pero no reflejan realmente la población.

  • Sesgo bajo, varianza alta: Las muestras varían enormemente en su consistencia, pero algunas pueden ser representativas de la población.

  • Sesgo alto, varianza alta Las muestras son un poco más consistentes, pero es probable que no sean representativas de la población.

Figura 3-2. Al tomar muestras de datos, debe tener cuidado con los cuatro niveles diferentes de sesgo y varianza

Una muestra aleatoria simple es una forma de controlar el sesgo al extraer muestras de una población. Esto es cuando selecciona valores aleatorios de sus datos tal que cada fila tenga el mismo chance de ser elegido, como se muestra en la Figura 3-3. Este es usualmente el mejor balance entre simplicidad y representación de la población en general. Al aplicar una muestra aleatoria simple a los mismos datos dos veces, si esta es realmente aleatoria, tendrá la posibilidad de seleccionar los mismos datos.

Figura 3-3. En una muestra aleatoria simple, se eligen los puntos de datos que se quieren usar de la población seleccionandolos de manera aleatoria

Otra forma común de muestreo se llama muestreo aleatorio estratificado (o sobremuestreo). Esto es cuando se separan los datos en grupos mutuamente excluyentes, llamados estratos, y luego hace una muestra aleatorio simple en cada estrato como se muestra en la Figura 3-4. Eso seria como hacer encuestas de forma aleatoria a lo largo de un estado de cada país. Esto tiene dos ventajas sobre una muestra aleatorio simple

  • Asegura la representación en cada estrato.
  • Puede ser más precisa que una muestra aleatoria simple si hay más variación en un estrato que en otros.

Si, por ejemplo, la muestras fueran esparcidas geográficamente o espacialmente, podría realizar un muestreo por conglomerados, por ejemplo, cuando tiene datos estratificados por país o ciudad. Esto es similar a realizar un muestreo aleatorio estratificado, pero eligiendo el estrato de forma aleatoria en lugar de hacer una muestra aleatoria simple dentro del estrato, como está ilustrado en la Figura 3-4

Figura 3-4. Una muestra aleatoria estratificada es cuando se selecciona aleatoriamente entre varios estratos de los datos (un estrato puede ser una agrupación o corte en los datos que separa una parte de los mismos de otra, lo que también puede deberse a variables de clasificación o de factor en los datos)

Figura 3-5. El muestreo por conglomerados es cuando se toman todos los puntos de datos de una determinada clase o corte de los datos, donde las propias clases o cortes se seleccionan al azar

El muestreo sistemático (Figura 3-6) es cuando se seleccionan al azar los primeros n puntos de datos y, a continuación, se seleccionan cada n puntos de datos

Figura 3-6. Con un procedimiento de muestreo sistemático, usted elige aleatoriamente un número, n, y luego elige cada n-ésimo punto de datos en el conjunto de datos

Hasta ahora hemos cubierto cuatro tipos diferentes de muestreo: Muestreo aleatorio simple, muestreo aleatorio estratificado, muestreo por conglomerados, y el muestreo sistemático. En casi todos los casos, se usará una muestra aleatoria simple por velocidad y facilidad de implementación. De cualquier forma, ciertos casos requerirán que los datos sean estratificados antes del muestreo. O, si los datos están arreglados de tal forma que están distribuidos en regiones geográficas, es posible que prefiera utilizar un método de conglomerados en su lugar.

Todo lo que hemos tratado hasta ahora habla sobre la implementación, pero no dice nada sobre qué tan grande debe ser tomada una muestra. La respuesta acá será, invariablemente, “depende”. Como lo verá en las secciones siguientes, tomar el 100% de la población como su muestra no siempre es la mejor aproximación. De cualquier forma,debe lograr un equilibrio tal que su muestra tenga suficientes puntos de datos para ser estadísticamente significativa y bien representativa de las estadísticas de población que está viendo.

Muestreo en R

Es bastante fácil realizar todas las técnicas de muestreo mencionadas anteriormente en R. Si empezamos con ejemplos de datos, por ejemplo, el conjunto de datos iris, podemos testear o probar algunas de estas técnicas de muestreo usando código R:

iris.df <- data.frame(iris)
sample.index <- sample(1:nrow(iris.df), nrow(iris) * 0.75, replace = FALSE)
head(iris[sample.index, ])
##     Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
## 107          4.9         2.5          4.5         1.7  virginica
## 98           6.2         2.9          4.3         1.3 versicolor
## 133          6.4         2.8          5.6         2.2  virginica
## 103          7.1         3.0          5.9         2.1  virginica
## 65           5.6         2.9          3.6         1.3 versicolor
## 114          5.7         2.5          5.0         2.0  virginica

Este fragmento de código hace una muestra aleatoria simple del conjunto de datos de iris generando primero los índices mediante los cuales necesita subconjuntos de los datos de iris. En este caso, seleccionamos al azar cinco filas de los datos sin reemplazo. Replacement es una opción que si se tiene activa, va a permitir que al extraer una fila de datos, tendrá la opción de extraerla nuevamente. De forma predeterminada, esta opción está desactivada en la función sample() en R, como es el caso de la mayoría de las funciones de muestreo que se ven en el mundo de la programación.

Veamos cómo hacer un muestreo estratificado en R. En contraste a una muestra aleatoria simple, el muestreo estratificado se puede realizar sobre diferentes características en el conjunto de datos. Ampliemos esto observando las distribuciones de datos en el conjunto de datos iris:

summary(iris)
##   Sepal.Length    Sepal.Width     Petal.Length    Petal.Width   
##  Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100  
##  1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300  
##  Median :5.800   Median :3.000   Median :4.350   Median :1.300  
##  Mean   :5.843   Mean   :3.057   Mean   :3.758   Mean   :1.199  
##  3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800  
##  Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500  
##        Species  
##  setosa    :50  
##  versicolor:50  
##  virginica :50  
##                 
##                 
## 

Aquí puede ver la población de los datos. Pretendemos obtener una muestra que tenga aproximadamente la misma distribución de valores para cualquiera de estas características. Note que algunas de esas columnas varían en un grado más alto que otras. En este caso, Petal.Length tiene la mayor cantidad de variación, seguido por Sepal.Length. Tenga esto en cuenta para el ejercicio de muestreo estratificado, por ahora hagamos una muestra aleatoria simple solo con los valores de Sepal.Length:

summary(iris[sample.index, ])
##   Sepal.Length    Sepal.Width     Petal.Length    Petal.Width   
##  Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100  
##  1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300  
##  Median :5.850   Median :3.000   Median :4.500   Median :1.400  
##  Mean   :5.884   Mean   :3.054   Mean   :3.825   Mean   :1.227  
##  3rd Qu.:6.500   3rd Qu.:3.300   3rd Qu.:5.200   3rd Qu.:1.800  
##  Max.   :7.700   Max.   :4.400   Max.   :6.900   Max.   :2.500  
##        Species  
##  setosa    :37  
##  versicolor:36  
##  virginica :39  
##                 
##                 
## 

Este ejemplo toma una muestra del 75% de los datos originales, y se puede ver que las distribuciones están bastante cerca de los valores de la población principal. Probemos ahora el muestreo estratificado. Para esto, necesita el paquete splitstackshape y la función stratified() así:

library('MASS')
library(splitstackshape)
summary(stratified(iris.df, "Sepal.Length", 0.7))
##   Sepal.Length    Sepal.Width     Petal.Length    Petal.Width   
##  Min.   :4.300   Min.   :2.000   Min.   :1.100   Min.   :0.100  
##  1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.375  
##  Median :5.800   Median :3.000   Median :4.450   Median :1.400  
##  Mean   :5.867   Mean   :3.031   Mean   :3.867   Mean   :1.256  
##  3rd Qu.:6.425   3rd Qu.:3.325   3rd Qu.:5.125   3rd Qu.:1.900  
##  Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500  
##        Species  
##  setosa    :34  
##  versicolor:34  
##  virginica :40  
##                 
##                 
## 

La muestra estratificada tiene los mismos valores aproximadamente. Realizamos un muestreo estratificado de los datos de iris utilizando la función estratified(), centrándonos específicamente en los estratos de Sepal.Length. Luego, el código solicita una muestra del 70%.

Sin embargo, con el muestreo estratificado, puede especificar sobre qué estrato particular desea hacer el muestreo. Si está muestreando muchos estratos, generalmente querrá comenzar con las características que varían menos y luego avanzar con las que más varían. Las características con la variación más baja en el conjunto de datos de iris son Sepal.Width y Petal.Width, así que comencemos con esas:

summary(stratified(iris, c("Sepal.Width", "Petal.Width"), 0.7))
##   Sepal.Length    Sepal.Width     Petal.Length    Petal.Width   
##  Min.   :4.300   Min.   :2.000   Min.   :1.100   Min.   :0.100  
##  1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300  
##  Median :5.800   Median :3.000   Median :4.400   Median :1.300  
##  Mean   :5.852   Mean   :3.055   Mean   :3.791   Mean   :1.228  
##  3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800  
##  Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500  
##        Species  
##  setosa    :37  
##  versicolor:40  
##  virginica :40  
##                 
##                 
## 

Puede ver en el resultado que el muestreo estratificado con múltiples grupos todavía tiene una buena representación de los datos de población (es decir, el conjunto de datos de iris completo) con el que comenzó. Las medias y las variaciones parecen bastante apropiadas para una muestra.

Para el muestreo sistemático, puede escribir una función simple que seleccione cada enésima fila secuencialmente dado un número de inicialización aleatorio:

sys.sample = function(N, n) {
k = ceiling(N/n)
r = sample(1:k, 1)
sys.samp = seq(r, r + k * (n - 1), k)
}
systematic.index <- sys.sample(nrow(iris), nrow(iris) * 0.75)
summary(iris[systematic.index, ])
##   Sepal.Length   Sepal.Width     Petal.Length    Petal.Width          Species  
##  Min.   :4.40   Min.   :2.000   Min.   :1.000   Min.   :0.100   setosa    :25  
##  1st Qu.:5.15   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.250   versicolor:25  
##  Median :5.80   Median :3.000   Median :4.500   Median :1.300   virginica :25  
##  Mean   :5.84   Mean   :3.064   Mean   :3.776   Mean   :1.219   NA's      :37  
##  3rd Qu.:6.45   3rd Qu.:3.400   3rd Qu.:5.100   3rd Qu.:1.850                  
##  Max.   :7.70   Max.   :4.100   Max.   :6.900   Max.   :2.500                  
##  NA's   :37     NA's   :37      NA's   :37      NA's   :37

Este fragmento de código define la función de muestreo sistemático y luego la ejecuta en los datos de iris. Para este ejemplo, ejecutamos dando el número de filas para el cual podemos obtener índices específicos, pero los resultados se ven bastante similares a lo que se han visto hasta ahora.

Entrenamiento y prueba

Al crear un modelo predictivo, debe pasar por fases de validación para asegurarse de que puede confiar en sus resultados. Si construye un modelo, necesita una forma verificable de asegurarse que está obteniendo algo que parece ser la respuesta correcta antes de volverse loco y comenzar a ponerlo en producción. Necesita una forma de ver cuáles serán los errores generados por el modelo para que también lo pueda ajustar mejor de manera apropiada.

Por ejemplo, si desea predecir el valor de algún precio de las acciones de mañana, para el que es imposible obtener los datos, puede crear un modelo que esté entrenado con datos de hace unos días y probarlo con datos que tenga de ayer. Ya que tiene las respuestas para los precios de las acciones de ayer, viendo lo que produce el modelo y comparando los números, puede proporcionar información valiosa para ver si el modelo está funcionando.

Es posible que haya visto modelos de aprendizaje automático utilizando una metodología de entrenamiento y prueba. Esto es, toma algunos datos, muestra la mayoría de ellos en un conjunto de entrenamiento y guarda lo que queda para un conjunto de prueba. Normalmente hacemos una división 70/30 de los datos en los subconjuntos de entrenamiento / prueba, pero no es raro ver divisiones 80/20 también. Lo que logra al hacer esto, es simular de manera efectiva el funcionamiento del modelo ejecutándolo primero en los datos que ya tiene, antes de hacerlo con datos completamente nuevos. Hay dos suposiciones principales con las que trabajamos cuando hacemos estas divisiones de entrenamiento / prueba:

  • Los datos son una representación justa de los procesos reales que desea modelar (es decir, el subconjunto refleja con precisión la población).

  • Los procesos que desea modelar son relativamente estables a lo largo del tiempo y un modelo creado con los datos del mes pasado debería reflejar con precisión los datos del mes siguiente.

Si sus suposiciones son correctas, un modelo construido a partir de los datos de hoy (o de ayer) debería funcionar con cualquier dato futuro que transmita. Sin embargo, debe tener cuidado con la forma en que divide sus datos de entrenamiento y prueba. La primera parte de este capítulo detalla diferentes formas en las que puede muestrear y crear subconjuntos de sus datos iniciales de manera que se conserven las distribuciones generales de las características en los datos. Por ejemplo, definitivamente no queremos subdividir nuestros datos iniciales en un subconjunto que tenga todas las respuestas de un tipo de flor, o todas las respuestas de una ciudad a una encuesta sobre el color favorito.

¿Cuál es el rol de los conjuntos de entrenamiento y prueba?

La base de datos se suele dividir entre el conjunto de prueba y el conjunto de entrenamiento, este último es el que se usa para entrenar el modelo. En la mayoría de algoritmos de aprendizaje no supervisados que usan este método, los coeficientes específicos que se obtienen son completamente basados en el conjunto de datos de entrenamiento y no en el conjunto de prueba.

El rol del conjunto de datos de entrenamiento es proveer una plataforma sobre la cual el modelo pueda determinar coeficientes de la manera más matemática posible. Por otro lado, el rol del conjunto de datos de prueba es notar que tan bien se aproxima el modelo con los datos reales.

¿Por qué hacer un conjunto de prueba?

Hay dos maneras de entender la importancia de hacer un conjunto de prueba para los propósitos de un modelo. La primera es verlo únicamente como una manera sólida de validar datos. Si se tenía un modelo que funcionaba muy bien para todo el conjunto de datos con el que fue entrenado, pero colapsa cuando son agregados nuevos datos, el modelo pierde todo su poder de predicción, en tal caso, lo mejor es un reporte estadístico. En el peor de los casos, los resultados pueden ser engañosos al mostrar aparentes conclusiones positivas. De esta manera, puede ser más favorable ver que el modelo funciona mal tempranamente.

La otra razón por la cual hacer un conjunto de prueba es importante, es porque algunos algoritmos de aprendizaje automático dependen de uno para existir. Por ejemplo, los árboles de clasificación y regresión (CARTs) pueden ser muy flexibles en sus capacidades para ser modelados, sin embargo, sí el árbol es suficientemente largo, a menudo se pueden obtener predicciones engañosas. Se pueden entrenar modelos de CART y ver que los elementos de salida son precisos en un 100%, pero en realidad el modelo funcionará mal con cualquier dato nuevo que se le ingrese. Desde el punto de vista estadístico, cualquier modelo que genere un 100.0% de precisión debe ser motivo de preocupación. Se puede usar un conjunto de prueba para evaluar la predictibilidad de los árboles en los datos para encontrar cuál de ellos tiene el menor error. Es decir, el conjunto de prueba no trabaja solamente como una manera de validar conjuntos de datos, sino también como una manera de seleccionar el modelo adecuado dependiendo del algoritmo en uso.

Conjuntos de entrenamiento y prueba: Modelo de regresión

La mejor manera de ilustrar cuál es la necesidad de tener un conjunto de prueba y entrenamiento es a través de ejemplos de regresión. Empecemos con algunos datos de prueba (Figura 3-7):

set.seed(123)
x <- rnorm(100, 2, 1)
y = exp(x) + rnorm(5, 0, 2)
plot(x, y)
linear <- lm(y ~ x)
abline(a = coef(linear[1], b = coef(linear[2], lty = 2)))
*Figura 3-7. Datos aleatorios con un ajuste lineal; el ajuste lineal se ajusta a algunos puntos de los datos, pero no todos (cuanto más se extiende X, más posible es que el ajuste lineal no aproxime muy bien los datos)*

Figura 3-7. Datos aleatorios con un ajuste lineal; el ajuste lineal se ajusta a algunos puntos de los datos, pero no todos (cuanto más se extiende X, más posible es que el ajuste lineal no aproxime muy bien los datos)

La siguiente salida es el resultado del código anterior a la Figura 3-7:

summary(linear)
## 
## Call:
## lm(formula = y ~ x)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -5.6481 -3.7122 -1.9390  0.9698 29.8283 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -13.6323     1.6335  -8.345 4.63e-13 ***
## x            11.9801     0.7167  16.715  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 6.51 on 98 degrees of freedom
## Multiple R-squared:  0.7403, Adjusted R-squared:  0.7377 
## F-statistic: 279.4 on 1 and 98 DF,  p-value: < 2.2e-16

Este fragmento de código es familiar. Toma unos datos de simulación para x y y, después genera una gráfica con el mejor ajuste lineal en la parte superior. Este ejemplo usa el 100% de los datos simulados del conjunto de entrenamiento. Particularmente, un R-cuadrado múltiple de 0.7 no es favorable. Se va a probar dividir los datos por muestreo aleatorio estándar 70/30 y ver cómo difiere.

Primero, se van a dividir los datos entre los conjuntos de entrenamiento y los de prueba mediante un muestreo aleatorio sencillo:

data <- data.frame(x, y)
data.samples <- sample(1:nrow(data), nrow(data) * 0.7, replace = FALSE)
training.data <- data[data.samples, ]
test.data <- data[-data.samples, ]

Se va a aplicar el modelo lineal sobre el conjunto de entrenamiento:

train.linear <- lm(y ~ x, training.data)

Ahora que se tiene el modelo entrenado, se va a comparar los valores de salida del modelo con los valores reales. Esto se puede hacer usando la función predict() en R, la cual toma el objeto train.linear y le aplica cualquier dato suministrado. Debido a que los datos de prueba están disponibles, es posible compararlos con:

train.output <- predict(train.linear, test.data)

De esta manera, se ha usado el conjunto de prueba, el cual tiene el mismo comportamiento subyacente que los datos del conjunto de entrenamiento para pasar a través de un modelo y obtener algunos resultados. El conjunto de prueba tiene una variable dependiente, x, y una variable independiente, y. Es necesario usar la variable dependiente para esta evaluación, ya que lo que se desea es comparar lo que el modelo piensa que son las respuestas correctas, dada la entrada x, comparada con los valores reales del conjunto de prueba, dados por y.

Para la regresión existen distintas maneras de hacer esto, dependiendo de los datos y el tipo de análisis de error que se desea en específico. En este caso, se puede usar una métrica de prueba llamada raíz del error cuadrático medio, (RMSE en inglés):

\[\text{RMSE}=\sqrt{\frac{1}{n}\sum(y_{predicción} - y_{real})^{2}}\]

De forma general, el RMSE sugiere tomar los valores de salida que el modelo generó por las entradas del conjunto de entrenamiento, restarlos con los valores y de los datos de prueba, elevarlos al cuadrado, dividir por el número total de observaciones n, sumar todos esos valores y, finalmente, tomar la raíz cuadrada. Así es el código:

RMSE.df = data.frame(predicted = train.output, actual = test.data$y,
SE = ((train.output - test.data$y)^2/length(train.output)))
head(RMSE.df)
##    predicted    actual         SE
## 2   7.874300  6.383579 0.07407499
## 3  28.504227 34.624423 1.24855995
## 4  11.341893  7.233768 0.56255641
## 5  12.019753  6.505638 1.01351529
## 12 14.678243 11.102747 0.42613909
## 15  4.118657  2.335049 0.10604193
sqrt(sum(RMSE.df$SE))
## [1] 6.946493

Considere el valor RMSE resultante de 6.9 como el error de este modelo. Para ver que tan bueno es este resultado se debe comparar con otro valor RMSE. Se puede ejecutar esta misma lógica en un ajuste de función de un grado más alto y ver que tipo de RMSE se obtiene como resultado final:

train.quadratic <- lm(y ~ x^2 + x, training.data)
quadratic.output <- predict(train.quadratic, test.data)
RMSE.quad.df = data.frame(predicted = quadratic.output, actual = test.data$y,
SE = ((quadratic.output - test.data$y)^2/length(train.output)))
head(RMSE.quad.df)
##    predicted    actual         SE
## 2   7.874300  6.383579 0.07407499
## 3  28.504227 34.624423 1.24855995
## 4  11.341893  7.233768 0.56255641
## 5  12.019753  6.505638 1.01351529
## 12 14.678243 11.102747 0.42613909
## 15  4.118657  2.335049 0.10604193
sqrt(sum(RMSE.quad.df$SE))
## [1] 6.946493

Este resultado demuestra que subir el grado del polinomio ayuda a disminuir el error en lo que el modelo está prediciendo (desde la variable quadratid.output) comparado con los valores reales. De manera intuitiva esto nos dice que los datos reales que se grafican parecen encajar bien por una cuadrática de todos modos.

Naturalmente, el siguiente paso es incrementar el grado del polinomio aún más y ver cómo afecta el valor RMSE:

train.polyn <- lm(y ~ poly(x, 4), training.data)
polyn.output <- predict(train.polyn, test.data)
RMSE.polyn.df = data.frame(predicted = polyn.output, actual = test.data$y,
SE = ((polyn.output - test.data$y)^2/length(train.output)))
head(RMSE.polyn.df)
##    predicted    actual           SE
## 2   5.228193  6.383579 0.0444972216
## 3  34.410640 34.624423 0.0015234381
## 4   7.312166  7.233768 0.0002048764
## 5   7.789798  6.505638 0.0549688692
## 12  9.946884 11.102747 0.0445339986
## 15  3.482548  2.335049 0.0438918352
sqrt(sum(RMSE.polyn.df$SE))
## [1] 0.8836878

Se puede ver que el RMSE ha aumentado en comparación con el ajuste cuadrático. Esto sigue el mismo patrón de un polinomio de mayor grado que sobrepase los datos.

Cuando se aprende por primera vez a ajustar una recta a una serie de puntos de datos en la educación temprana, no se suele aprender las complejidades de las técnicas de muestreo, ni a dividir datos en conjuntos de entrenamiento y prueba. Cuando se empieza a trabajar con ajustes de regresión, lo primero es hacer ajustes con una recta, como se muestra en Figura 3-8.

Figura 3-8. Un ajuste lineal simple a los datos caera en underfit* o subajuste, esto es cuando la recta ajustada dada por los coeficientes de salida del modelo no se alinean con los datos que se tienen*

La Figura 3-8 tiene algunos datos, como denotan las marcas en forma de x, y el ajuste del modelo, denotado por la recta superpuesta en la parte superior de ellos. También está la ecuación que describe este modelo: \(y=\theta_{0}-\theta_{1}x\), también escrita como \(y=b+mx\). Hay dos valores que se dan por el proceso de ajuste del modelo, \(\theta_{0}\) y \(\theta_{1}\).

Para esta simple gráfica tenemos un modelo bastante inadecuado para los datos. Esto significa que la recta en el gráfico que representa el modelo de aprendizaje automático (regresión lineal simple) no explica la mayoría de los datos; es un modelo demasiado simple. Los modelos lineales sólo pueden representar los datos que se están trazando. Si, por ejemplo, un modelo coincidía con una serie de puntos que eran una línea recta, sería una representación precisa. En el mejor de los casos, la regresión lineal puede ajustarse exactamente a los datos, pero es difícil que un procedimiento simple como este se ajuste demasiado a los datos. Debido a que los modelos lineales son difíciles de ajustar a los datos, rara vez se ve el uso de conjuntos de entrenamiento y prueba para evaluarlos. Volviendo al modelo donde coincidían los puntos con una línea recta, si se fuera a añadir otro punto que siguiera más o menos la misma forma, el modelo lineal seguirá divergiendo y no producirá un resultado favorable a largo plazo.

Comparemos el ajuste lineal con un ajuste cuadrático en la Figura 3-9. El ajuste, en este caso, es mejor que el ajuste lineal. El ajuste del modelo tiende a ajustarse a la forma de la mayoría de puntos de datos y el modelo se ha vuelto un poco más complejo. Se tiene una ecuación que describe el modelo y ahora se tienen más salidas derivadas del modelo. Si se quisiera añadir otro par de puntos datos a la gráfica de la misma forma aproximada, la cuadrática parece que encajaría bastante bien en el futuro.

Figura 3-9. Un ajuste cuadrático tiene un modelo ligeramente más complejo dado por los coeficientes que se obtienen del modelo. Al entrenar un modelo de aprendizaje automático con una muestra de entrenamiento específica y luego observar la diferencia entre esta y los datos de prueba guardados, se puede evaluar qué tan bien se ajustó el modelo a los datos

Por último, con algún tipo de modelo complejo como el que se ve en la Figura 3-10, casi todos los puntos de datos se ajustan al modelo exactamente sin margen de cambio. La desventaja de este será explicar los resultados a futuro. Si se sigue la misma lógica que antes y se añaden algunos puntos de datos más a la imagen, el modelo mostrado no encajará bien en todos y tendrá un error más grande.

Figura 3-10. En un escenario de ajuste de un modelo más complejo, donde el modelo es demasiado específico para los datos de entrenamiento, los nuevos datos de prueba que se le aplican probablemente tendrán errores mayores cuando evaluamos la salida del modelo frente a los datos de prueba

Cuando se hace la validación de prueba y entrenamiento en datos continuos como en el ejemplo de la anterior regresión, se puede elegir entre una serie de medidas estadísticas como el RSME. En términos generales, se desea comparar los valores de salida que le da el modelo, basado en un subconjunto de datos que utilizó para entrenar, con los datos que tenía para fines de prueba. Se debe tener una lista de números para las estimaciones del modelo y una lista de números que son los valores reales. De alguna forma, estos datos tendrán algún tipo de diferencia entre ellos, la cuál se puede encapsular con un cierto número agregado y comparar con otros métodos.

Para datos continuos similares a los que hemos estado trabajando hasta ahora, hay algunas pruebas estadísticas diferentes con las que se pueden comparar las salidas de error de sus resultados:

  • RMSE:

\[\text{RMSE}=\sqrt{\frac{1}{n}\sum(y_{predicción} - y_{real})^{2}}\]

  • Error Absoluto Medio (MAE): \[\text{MAE}=\frac{1}{n}\sum|y_{predicción} - y_{real}|\]
  • Error Cuadrático Relativo a la Raíz (RRSE): \[\text{RRSE}=\sqrt{\frac{\sum(y_{predicción} - y_{real})^{2}}{\sum(\overline{y}_{predicción} - y_{real})^{2}}}\]
  • Error Absoluto Relativo (RAE): \[\text{RAE}=\frac{\sum|y_{predicción} - y_{real}|}{\sum|\overline{y}_{predicción} - y_{real}|}\]

Para RMSE y MAE, se puede ver la “diferencia media” entre la salida del modelo, \(y_{predicción}\) y los valores que se tienen en el conjunto de prueba, \(y_{real}\). Estos se comparan en la misma escala de nuestra función. Se puede pensar esto como que 1 punto de error es una diferencia de 1 entre \(y_{predicción}\) y \(y_{real}\).

En RRSE y RAE aparece una nueva variable \(\overline{y}_{predicción}\), la cual es el valor medio de nuestro modelo de salida y es sólo un número escalar. Estas estadísticas dividen los valores de nuestros datos predichos y los reales por la variación de nuestra función, de modo que el resultado final esté en una escala de 0 a 1. Se tiende a multiplicar esto por 100 y así convertirlo en un porcentaje como resultado. Los denominadores de las dos ecuaciones nos indican cuánto se desvía la función de su valor promedio, por lo que se suelen llamar errores “relativos”.

Conjuntos de entrenamiento y prueba: Modelo de clasificación

El rendimiento de un modelo de clasificación se evalúa a partir de una “matriz de confusión”. En su forma más simple, puede tomar representación como una matriz de 2 × 2, en la que las clases predichas por el modelo se comparan con las clases reales y el recuento de las salidas del modelo en las celdas de la matriz. Esto le informa de cuántos verdaderos positivos, verdaderos negativos, falsos positivos y falsos negativos hay en total. Como en el caso del análisis de regresión, el análisis de clasificación tiene muchas herramientas con las que se puede evaluar el rendimiento final del modelo. Veamos algunas de ellas:

iris.df <- iris
iris.df$Species <- as.character(iris.df$Species)
iris.df$Species[iris.df$Species != "setosa"] <- "other"
iris.df$Species <- as.factor(iris.df$Species)
iris.samples <- sample(1:nrow(iris.df), nrow(iris.df) * 0.7,
replace = FALSE)
training.iris <- iris.df[iris.samples, ]
test.iris <- iris.df[-iris.samples, ]
library(randomForest)
iris.rf <- randomForest(Species ~ ., data = training.iris)
iris.predictions <- predict(iris.rf, test.iris)
table(iris.predictions, test.iris$Species)
##                 
## iris.predictions other setosa
##           other     34      0
##           setosa     0     11

En una tabla de verdad de clase binaria, hay dos resultados: o el valor predicho es de alguna clase, o no lo es. En este caso, nos centramos en si el modelo predijo una clase setosa o alguna otra . Hay cuatro valores para la tabla de confusión:

  • Verdaderos positivos: El modelo predijo las clases setosa y acertó.

  • Verdaderos negativos: El modelo predijo las clases other y acertó.

  • Falsos positivos: El modelo predijo las clases setosa, pero la clase correcta era other .

  • Verdaderos negativos: El modelo predijo las clases other, pero la clase correcta era setosa.

El resultado de esta tabla de verdad no es muy interesante ya que fue muy preciso. No hubo ninguna clase predicha incorrectamente. Sin embargo, en aras de una ilustración, vamos a suponer que obtuvimos salidas ligeramente inexactas en la matriz de confusión:

##
##        other setosa
## other     25      3
## setosa     2     15

Este ejemplo fuerza dos falsos positivos y tres falsos negativos. Así que ahora tenemos 25 verdaderos positivos (TP), 15 verdaderos negativos (TN), 2 falsos positivos (FP) y 3 falsos negativos (FN). Con modelos de clasificación como estos, obtenemos una serie de estadísticas entre las que podemos elegir para comprobar nuestra precisión:

  • Sensitivity:
    \[ \text{Sensitivity}=\dfrac{TP}{TP+FN}=0.89 \]

  • Specifity:
    \[ \text{Specifity}=\dfrac{TN}{TN+FP}=0.88 \]

  • Precision:
    \[ \text{Precision}=\dfrac{TP}{TP+FP}=0.92 \]

  • Accuracy:
    \[ \text{Accuracy}=\dfrac{TP+TN}{TP+TN+FP+FN}=0.88 \]

  • F1 score:
    \[ \text{F1}=\dfrac{2TP}{2TP+FP+FN}=0.90 \]

Muchos de estos valores se utilizan como puntos de referencia para los modelos de clasificación. Con los modelos de regresión, usted tenía el valor RMSE a mano, el cual podía comparar con otros modelos, así que ¿cuál sería el punto de referencia correspondiente para la precisión en este caso? Veamos las opciones disponibles:

  • Sensitivity: A menudo se denomina recall, esto es cuando se establece un umbral más bajo para el modelo de clasificación. Se establecería un umbral más bajo si no se quisiera perder ninguna planta que podría ser de un tipo de setosa.

  • Specifity: Lógicamente es lo mismo que precision, pero para el caso contrario, cuando se trata de predecir si una planta no es una variante setosa.

  • Precision: El número de verdaderos positivos que ha predicho dividido por el total de positivos predichos (falsos y verdaderos). Si se tuviera un modelo donde el valor de sensitivity es muy alto, se tendría que establecer un umbral en su modelo para decir: “Sólo clasificar una planta como setosa si está absolutamente seguro de ello”.

  • Accuracy: Número de casos verdaderos dividido por el total de casos verdaderos y falsos.

  • F1 score: Media ponderada de precision y sensitivity.

Podría estar tentado a señalar que su punto de referencia de precisión será accuracy. En el caso que tenga un número casi idéntico de falsos positivos y falsos negativos, esta sería una medida perfectamente válida. Sin embargo, si los falsos positivos o los falsos negativos están sesgados a favor de uno u otro, se necesita una prueba estadística más robusta para tener en cuenta ese comportamiento.

Aunque la puntuación F1 puede ser menos intuitiva que accuracy (otra medida de precisión o exactitud) a primera vista, suele ser más útil porque F1 y accuracy son casi el mismo número cuando las tasas de falsos positivos y falsos negativos son bajas. Puede ver la utilidad del número F1 si observa algunos modelos diferentes de “simulacro” que tienen varios valores de precisión (Precision) y sensibilidad (Recall). Podría estar tentado a tomar simplemente la media de precision y recall para obtener una métrica de rendimiento, que puede ver en la siguiente tabla:

Precision = c(0.50,0.70,0.02,0.00,1.00);
Recall = c(0.40,0.10,1.00,0.01,1.00);
Average = c(0.45,0.40,0.51,0.51,1.00);
F1_score = c(0.44,0.18,0.04,0.02,1.00);
table1 = data.frame(Precision,Recall,Average,F1_score)
knitr::kable(table1)
Precision Recall Average F1_score
0.50 0.40 0.45 0.44
0.70 0.10 0.40 0.18
0.02 1.00 0.51 0.04
0.00 0.01 0.51 0.02
1.00 1.00 1.00 1.00

Estos datos de ejemplo demuestran algunos modelos diferentes que muestran la precisión (Precision) y la sensibilidad (Recall) . Si se quiere evaluar el rendimiento del modelo basándose en la media de estos dos números, dicho enfoque fallará cuando se tenga una alta precisión y una baja sensibilidad o el caso opuesto. Sin embargo, el valor de F1 equilibra esas peculiaridades y proporciona una métrica más fiable con la que evaluar el rendimiento de su modelo de clasificación.

Validación cruzada (Cross Validation)

Hasta ahora, hemos hablado sobre cómo la ejecución de un modelo en el 100% de sus datos podría generar un resultado que no se generalice bien a los nuevos datos entrantes. Esta fue nuestra motivación para dividir los datos con los que comenzamos en un conjunto de entrenamiento, que generalmente toma alrededor del 70% de los datos y un conjunto de prueba que comprende el resto. Se corre el modelo en los datos de entrenamiento y luego se utiliza el conjunto de prueba para comprobar cuál es la salida del modelo en comparación con las respuestas que tiene a la mano.

Sin embargo, este proceso de entrenamiento y prueba de datos todavía es algo limitado. Cuando está probando la salida del modelo contra los datos reservados, está viendo sólo el error para esa agrupación exacta de los datos de prueba. En teoría, los datos de prueba deben ser representativos de todo el conjunto de datos como un todo, pero en la práctica hay casos en los que eso podría no ser cierto. Debería querer entrenar el modelo de tal manera que pueda estar seguro de que el error es representativo de todo el conjunto de datos, no solo del segmento específico que obtiene de la selección al azar que coloca en el conjunto de prueba.

La validación cruzada (cross-validation) es una técnica estadística mediante la cual toma todo su conjunto de datos, lo divide en una serie de pequeños segmentos de entrenamiento/prueba, evalúa el error para cada segmento y luego promedia esos errores finales. Este enfoque termina siendo una forma más precisa de evaluar si el modelo tiene problemas que podrían estar ocultos en varias combinaciones de las partes de entrenamiento y prueba del conjunto de datos.

De hecho, ya hemos realizado una forma de validación cruzada, la división 70/30, entrenamiento/prueba, que se hizo anteriormente en este capítulo se llama técnica de validación cruzada “Holdout”. Sin embargo, existen muchas otras técnicas estadísticas de validación cruzada y con R teniendo su base en el diseño estadístico, puede modelar muchos tipos diferentes de validación cruzada.

Validación cruzada k-Fold

En contraste con la validación cruzada “Holdout”, existe una técnica mucho más utilizada denominada validación cruzada k-fold. Esta consiste en tomar el conjunto de datos y dividirlo en k trozos (o chunks). Para cada uno de estos fragmentos, luego divide los datos en un conjunto pequeño de datos de entrenamiento/prueba y luego evalúa el error de ese fragmento individual. Después de que tenga todos los errores para todos los fragmentos, simplemente toma el promedio. La ventaja de este método es que luego puede ver el error en todos los aspectos de sus datos en lugar de solo pruebas en un subconjunto específico de él.

Figura 3-11. La validación cruzada es la práctica estadística de realizar muchos procedimientos de entrenamiento y prueba en nuestros datos; este ejemplo muestra una validación cruzada de 10 veces

En R, puede usar la función cut (convierte números a factor, divide el rango de x en intervalos y codifica los valores en x según el intervalo en el que caen. El intervalo más a la izquierda corresponde al nivel uno, el siguiente a la izquierda al nivel dos y así sucesivamente) para dividir uniformemente los índices de un conjunto de datos dado en subconjuntos. Luego, simplemente recorre los pliegues aplicados de sus datos, haciendo la división entrenamiento/prueba para cada pliegue:

set.seed(123) 
x <- rnorm(100, 2, 1) 
y = exp(x) + rnorm(5, 0, 2)
data <- data.frame(x, y)
head(data)
##          x         y
## 1 1.439524  2.797876
## 2 1.769823  6.383579
## 3 3.558708 34.624423
## 4 2.070508  7.233768
## 5 2.129288  6.505638
## 6 3.715065 39.640442
data.shuffled <- data[sample(nrow(data)), ] 
folds <- cut(seq(1, nrow(data)), breaks = 10, labels = FALSE)
errors <- c(0) 
for (i in 1:10) {
fold.indexes <- which(folds == i, arr.ind = TRUE)
test.data <- data[fold.indexes, ]
training.data <- data[-fold.indexes, ]
train.linear <- lm(y ~ x, training.data)
train.output <- predict(train.linear, test.data)
errors <- c(errors, sqrt(sum(((train.output - test.data$y)^2/length(train.output))))) #Cálculo del RMSE (Raiz del Error Cuadratico Medio)
}
errors[2:11]
##  [1]  4.696183  6.392002  4.769101  4.259850  9.634505  5.073442  7.547830
##  [8]  7.366703  3.974609 10.539853

Anteriormente en este capítulo, analizamos cómo un ajuste de regresión lineal en datos de ejemplo nos dio una estimación de error alrededor de cinco. El ejemplo anterior muestra que el error estimado puede variar en gran medida solo dentro de sus propios datos, dependiendo de cómo divida los conjuntos de entrenamiento y prueba. En este ejemplo, puede ver las salidas de los valores RMSE para 10 cortes diferentes de los datos. Algunos errores llegan a 3.9, otros tan altos como 10.5. Entonces, al usar la validación cruzada, no solo puede ver que hay un alto grado de variabilidad en el RMSE de estos datos, si no que puede mitigar eso tomando el promedio de esos valores para obtener un número final que sea más representativo del error en los datos en su conjunto.