#CAPITULO 12
library(h2o)
## Warning: package 'h2o' was built under R version 4.3.3
##
## ----------------------------------------------------------------------
##
## Your next step is to start H2O:
## > h2o.init()
##
## For H2O package documentation, ask for help:
## > ??h2o
##
## After starting H2O, you can use the Web UI at http://localhost:54321
## For more information visit https://docs.h2o.ai
##
## ----------------------------------------------------------------------
##
## Attaching package: 'h2o'
## The following objects are masked from 'package:stats':
##
## cor, sd, var
## The following objects are masked from 'package:base':
##
## %*%, %in%, &&, ||, apply, as.factor, as.numeric, colnames,
## colnames<-, ifelse, is.character, is.factor, is.numeric, log,
## log10, log1p, log2, round, signif, trunc
library(TSstudio)
## Warning: package 'TSstudio' was built under R version 4.3.3
library(plotly)
## Warning: package 'plotly' was built under R version 4.3.3
## Loading required package: ggplot2
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
library(lubridate)
## Warning: package 'lubridate' was built under R version 4.3.3
##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:h2o':
##
## day, hour, month, week, year
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
##PREVENSIÓN DE VENTAS MENSUALES DE VEHÍCULOS EN EE.UU.: Un estudio de caso. En este capitulo, nos centraremos en pronosticar las ventas mensuales totales de vehículos en los EE.UU. en los proximos 12 meses con metodos ML. Las ventas mensuales totales de vehiculos en la serie de EE.UU. estaan disponibles en el paquete TSstudio:
library(TSstudio)
data(USVSales)
Antes de comenzar a preparar la serie y crear nuevas funciones, realizaremos un breve analisis exploratorio de la serie para identificar las principales caracteristicas de la serie.
##Analisis exploratorio de la serie USVSales En este apartado nos centraremos en explorar y conocer las principales caracteristicas de la serie. Estos conocimientos se utilizaran para crear nuevas funciones como entradas para el modelo de aprendizaje automatico. El analisis exploratorio de la serie USVSales se centrará en los sgtes temas:
##La estructura serie. Comencemos con ts_info y revisemos la estructura de la serie USVSales:
ts_info(USVSales) #Obtenemos el sgte resultado
## The USVSales series is a ts object with 1 variable and 528 observations
## Frequency: 12
## Start time: 1976 1
## End time: 2019 12
# La serie es un objeto ts con 1 variable y 528 observaciones
# La frecuencia es de 12
# Su hora de inicio es de 1976 1
# Su hora de finalizacion es de 2019 1
La serie USVSale es un objeto ts mensual que representa las ventas totales de vehículos en EE.UU. entre 1976 y 2018 en miles de unidades. Tracemos la serie y revisemos su estructura con la funcion ts_plot
Obtenemos el sgte resultado:
ts_plot(USVSales,
title = "US Total Monthly Vehicle Sales",
Ytitle = "Thousand of Units",
Xtitle = "Year")
Como puede verse en el gráfico anterior, la serie tiene pratones cíclicos, lo cual es común para un indicador macroeconomico. En este caso, es un indicador macro de la economia estadounidense.
##Los componentes de las series Podemos obtener una vision mas profunda de los componentes de la serie descomponiendo la serie en sus componentes y trazandolos con la funcion ts_descompose:
En donde obtenemos el siguiente resultado:
ts_decompose(USVSales)
Ademas del componente de tendencia cíclica, podemos observar que el grafico tiene un fuerte patron estacional, que exploraremos a continuacion:
##Analisis estacional Para observar mas de cerca el componente estacional de la serie, restaremos de la serie, descompondremos la tendencia que analizamos anteriormente y usaremos la funcion ts_seasonal para trazar el diagrama de caja y bigote del componente estacional de la serie de tendencia:
Obtendremos el sgte resultado:
USVSales_detrend <- USVSales - decompose(USVSales)$trend
ts_seasonal(USVSales_detrend, type = "box")
## Warning: Ignoring 1 observations
## Warning: Ignoring 1 observations
## Warning: Ignoring 1 observations
## Warning: Ignoring 1 observations
## Warning: Ignoring 1 observations
## Warning: Ignoring 1 observations
## Warning: Ignoring 1 observations
## Warning: Ignoring 1 observations
## Warning: Ignoring 1 observations
## Warning: Ignoring 1 observations
## Warning: Ignoring 1 observations
## Warning: Ignoring 1 observations
Podemos ver en el grafico estacional anterior que, normalmente, el pico del año se produjo durante los meses de marzo, mayo y junio. Ademas, se puede ver que las ventas decaen a partir de los meses de verano y vuelven a alcanzar su punto maximo en diciembre durante las temporadas navideñas. Por otro lado, el mes de enero suele ser el mes más bajo del año en terminos de ventas.
##Analisis de correlacion Como vimos en el Capitulo 7, Analisis de correlacion, la serie USVSales tiene una alta correlacion con su primer rezafo estacional. Podemos revisar esta evaluacion con el uso de la funcion ts_acf del paquete TSstudio para revisar la autocorrelacion de la serie: Podemos ampliar la relacion de la serie con los tres ultimos desfases estacionales utilizando el funcion ts_lags:
ts_lags(USVSales, lags = c(12, 24, 36))
La relacion de la serie con el primer y segundo rezago estacional tiene una fuerte relacion lineal, como se muestra en el grafico de rezagos anterior.
#Analisis exploratorio: hallazgos clave Podemos concluir nuestro breve analisis exploratorio de la serie USVSales con las siguientes observaciones: - La serie USVSales es una serie mensual con una clara estacionalidad mensual. - La tendencia de la serie tiene una forma ciclica, por lo que la serie tiene un componente ciclico incorporado en la tendencia. - El ciclo mas reciente de la serie comienza justo despues del final de la crisis economica de 2008, entre 2009 y 2010. - Parece que el ciclo actual alcanzo su punto maximo a medida que la tendencia comienza a aplanarse. - La serie tiene una fuerte correlacion con su primer desfase estacional. Ademas, como pretendemos tener una prevision a corto plazo( de 12 meses), no tiene sentido utilizar la serie completa, ya que puede introducir algo de ruido en el modelo debido al cambio de direccion de la tendencia cada dos años. (Si intenta crear un pronostico a largo plazo, puede ser una buena idea utilizar todas o la mayor parte de las series). Por lo tanto, utilizaremos las observaciones de entrenamiento del modelo desde 2010 en adelante. Usaremos la funcion ts_to_prophet dek paquete TSstudio para transformar la serie de un objeto ts en data.frame y la funcion de window para subconjuntos de observaciones de la serie desde enero 2010:
Obtenemos el sgte resultado:
df <- ts_to_prophet(window(USVSales, start = c(2010,1)))
names(df) <- c("date", "y")
head(df)
## date y
## 1 2010-01-01 712.469
## 2 2010-02-01 793.362
## 3 2010-03-01 1083.953
## 4 2010-04-01 997.334
## 5 2010-05-01 1117.570
## 6 2010-06-01 1000.455
Antes de seguir adelante y comenzar con la etapa de ingeniera de carzcteristicas, tracemos y revisemos la serie de subconjuntos de USVSales con la funcion ts_plot:
Donde obtenemos lo sgte:
ts_plot(df,
title = "US Total Monthly Vehicle Sales (Subset)",
Ytitle = "Thousands of Units",
Xtitle = "Year")
##Ingenieria de caracteristicas La ingeniera de caracteristicas juega un papel muy importante con algoritmos de ML. Nuestro siguiente paso, basado en las observaciones anteriores, es crear nuevas caracteristicas que puedan usarse como informacion para el modelo. En el contexto de le prevision de series temporales, a continuacion se muestran algunos ejemplos de posibles nuevas caracteristicas que se pueden crear a partir de la propia serie: - La tendencia de la serie: Utiliza un indice numerico. Ademas, como la tendencia de la serie no es lineal, utilizaremos un segund polinomio del indice para capturar la curvatura general de la tendencia de la serie. - Componente estacional: Crea una variable categorica para el mes del año para capturar la estacionalidad de la serie. - Correlacion de series: Utiliza la fuerte correlacion de la serie con su desfase estacional y utiliza el desfase estacional (lag 12) como entrada al modelo.
Usaremos en este caso los paquetes dplyr y lubridate para crear esas funciones, como podemos ver en el sgte codigo:
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.3.3
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(lubridate)
df <- df %>% mutate(month = factor(lubridate::month(date, label = TRUE), ordered = FALSE),
lag12 = lag(y, n = 12)) %>%
filter(!is.na(lag12))
Luego sumaremos el componente de tendencia y su segundo polinomio(tendencia al cuadrado):
df$trend <- 1:nrow(df)
df$trend_sqr <- df$trend ^ 2
Veamos la estructura del objeto df despues de agregar las nuevas funciones:
A continuacion:
str(df)
## 'data.frame': 108 obs. of 6 variables:
## $ date : Date, format: "2011-01-01" "2011-02-01" ...
## $ y : num 836 1007 1277 1174 1081 ...
## $ month : Factor w/ 12 levels "ene","feb","mar",..: 1 2 3 4 5 6 7 8 9 10 ...
## $ lag12 : num 712 793 1084 997 1118 ...
## $ trend : int 1 2 3 4 5 6 7 8 9 10 ...
## $ trend_sqr: num 1 4 9 16 25 36 49 64 81 100 ...
Hay pasos de ingeniería de características adicionales, que en el caso de la serie USVSales no son necesarios, pero pueden ser necesarios en otros casos: - Escalado: esto puede ser necesario cuando las entradas numéricas de la regresión (ya sea la serie misma o al menos uno de los predictores numéricos de la regresión) están en una escala numérica diferente, por ejemplo, hacer una regresión de ingresos en miles de millones de USD con una bandera binaria ( por ejemplo, 0 o 1). Es posible que algunos modelos no encuentren coeficientes o no identifiquen la verdadera relación entre la variable. Algunos métodos de escalado comunes son los siguientes: • Transformación de registros • Normalizar la serie con Z-score • Escalar la entrada entre 0 y 1 • Resta la media de la entrada - Codificacion en caliente: Es posible que se requieran variables categoricas cuando el algoritmo no admite el uso de factores (variables categoricas) como entrada. En este caso, para una variable con N categorias, crearemos nuevas variables N+1, una variable para capturar la pendiente y N variables binarias y una para cada categoria.
Dado que los valores de la serie son entradas oscilan entre 800 y 1700, no es necesario escalar la serie y sus entradas. Ademas, dado que el paquete h2o admite las entradas como factores R, no es necesario aplicar codificacion en caliente.
##Entrenamiento, pruebas y evaluacion de modelos Para comparar los diferentes modelos que probaremos en este capitulo, usaremos las mismas entradas que usamos anteriormente. Esto incluye la ejecucion de las mismas particiones de entrenamiento y prueba a lo largo de este capitulo. Dado que nuestro horizonte de pronóstico es de 12 meses, dejeremos los ultimos 12 meses de la serie como particiones de prueba y usaremos el resto de la serie como particion de entrenamiento:
h <- 12
train_df <- df[1:(nrow(df) - h), ]
test_df <- df[(nrow(df) - h + 1):nrow(df), ]
Anteriormente, la variable h representaba el horizonte de pronostico, que, en este caso, tambien es igual a la longitud de la particion de prueba. Evaluaremos el rendimiento del modelo en funcion de la puntuacion MAPE en la participacion de prueba. Además, de las participaciones de entrenamiento y prueba, necesitamos crear las entradas para el pronostico en sí. Crearemos un data.frame con las fechas de los sgtes 12 mese y contruiremos el resto de caracteristicas:
forecast_df <- data.frame(date = seq.Date(from= max(df$date) + lubridate::month(1),
length.out = h, by = "month"), trend = seq(from = max(df$trend) + 1, length.out = h, by = 1))
forecast_df$trend_sqr <- forecast_df$trend ^ 2
# to avoid conflict with the h2o `month` function use the "lubridate::month" to explicly call the month from the lubridate function
forecast_df$month <- factor(lubridate::month(forecast_df$date, label = TRUE), ordered= FALSE)
Por ultimo, pero no menos importante extraeremos las ultimas 12 observaciones de la serie del objeto df y las asignaremos como regazos futuros de la serie:
forecast_df$lag12 <- tail(df$y, 12)
##Modelo de referencia Introducido en el Capítulo 8, Estrategias de pronóstico, el desempeño de un modelo de pronóstico debe medirse por la tasa de error, principalmente en la partición de prueba, pero también en la partición de entrenamiento. Debe evaluar el desempeño del modelo con respecto a algún modelo de referencia. En los capítulos anteriores, comparamos el pronóstico de la serie de gas estadounidense con el uso del modelo ingenuo estacional.
En este capítulo, dado que utilizamos una familia de modelos de regresión de ML, tiene más sentido utilizar un modelo de regresión como punto de referencia para los modelos de ML. Por lo tanto, entrenaremos un modelo de regresión lineal de series de tiempo, que presentamos en el Capítulo 9, Pronósticos con regresión lineal. Usando las particiones de entrenamiento y prueba que creamos anteriormente, entrenemos el modelo de regresión lineal y evaluemos su rendimiento con las particiones de prueba:
lr <- lm(y ~ month + lag12 + trend + trend_sqr, data = train_df)
Usaremos la función de summary para revisar los detalles del modelo, donde obtenemos el siguiente resultado:
summary(lr)
##
## Call:
## lm(formula = y ~ month + lag12 + trend + trend_sqr, data = train_df)
##
## Residuals:
## Min 1Q Median 3Q Max
## -146.625 -38.997 0.111 39.196 112.577
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 542.93505 72.59490 7.479 7.91e-11 ***
## monthfeb 112.73160 34.16141 3.300 0.001439 **
## monthmar 299.20932 54.24042 5.516 4.03e-07 ***
## monthabr 182.52406 42.53129 4.292 4.88e-05 ***
## monthmay 268.75603 51.28464 5.240 1.24e-06 ***
## monthjun 224.66897 44.26374 5.076 2.41e-06 ***
## monthjul 177.88564 42.21898 4.213 6.49e-05 ***
## monthago 241.63260 47.00693 5.140 1.86e-06 ***
## monthsept 152.99058 37.04199 4.130 8.76e-05 ***
## monthoct 125.16484 35.04896 3.571 0.000601 ***
## monthnov 127.97288 34.18772 3.743 0.000338 ***
## monthdic 278.67994 51.09552 5.454 5.21e-07 ***
## lag12 0.33906 0.10738 3.158 0.002236 **
## trend 7.73667 1.72415 4.487 2.36e-05 ***
## trend_sqr -0.05587 0.01221 -4.576 1.69e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 59.6 on 81 degrees of freedom
## Multiple R-squared: 0.9198, Adjusted R-squared: 0.9059
## F-statistic: 66.36 on 14 and 81 DF, p-value: < 2.2e-16
A continuacion, prediciremos los valores correspondientes de la serie en la particion de prueba con la funcion de prediccion usando test_df como entrada:
test_df$yhat <- predict(lr, newdata = test_df)
Ahora podemos evaluar el rendimiento del modelo en la particion de prueba, donde obtenemos el sgte resultado:
mape_lr <- mean(abs(test_df$y - test_df$yhat) / test_df$y)
mape_lr
## [1] 0.03594578
Por lo tanto, la puntuación MAPE del modelo de pronostico lineal es de 3,03%. Usaremos esto para comparar el rendimiento de los modelos ML.
##Iniciar un grupo de agua El paquete h2o se basa en el uso de computación distribuida y paralela para acelerar el tiempo de cómputo y poder escalar para big data. Todo esto se realiza en clústeres de procesamiento distribuido en memoria (basado en la RAM interna de la computadora) o en paralelo (por ejemplo, AWS, Google Cloud, etc.). Por lo tanto, cargaremos el paquete y luego configuraremos el clúster en memoria con h2o.init función de inicio:
library(h2o)
h2o.init(max_mem_size = "16G")
##
## H2O is not running yet, starting it now...
##
## Note: In case of errors look at the following log files:
## C:\Users\UserHp\AppData\Local\Temp\Rtmpa8sSCj\file29504a886e45/h2o_UserHp_started_from_r.out
## C:\Users\UserHp\AppData\Local\Temp\Rtmpa8sSCj\file295097b1347/h2o_UserHp_started_from_r.err
##
##
## Starting H2O JVM and connecting: . Connection successful!
##
## R is connected to the H2O cluster:
## H2O cluster uptime: 14 seconds 587 milliseconds
## H2O cluster timezone: America/Bogota
## H2O data parsing timezone: UTC
## H2O cluster version: 3.44.0.3
## H2O cluster version age: 4 months and 9 days
## H2O cluster name: H2O_started_from_R_UserHp_tip223
## H2O cluster total nodes: 1
## H2O cluster total memory: 14.21 GB
## H2O cluster total cores: 2
## H2O cluster allowed cores: 2
## H2O cluster healthy: TRUE
## H2O Connection ip: localhost
## H2O Connection port: 54321
## H2O Connection proxy: NA
## H2O Internal Security: FALSE
## R Version: R version 4.3.2 (2023-10-31 ucrt)
## Warning in h2o.clusterInfo():
## Your H2O cluster version is (4 months and 9 days) old. There may be a newer version available.
## Please download and install the latest version from: https://h2o-release.s3.amazonaws.com/h2o/latest_stable.html
h2o.init le permite configurar el tamaño de la memoria del cluster con el argumento max_mem_size. El resultado de la funicon, como se muestra en el codigo anterior, proporciona informacion sobre la configuracion del clúster. Cualquier dato que el paquete h2o utilice durante el proceso de entrenamiento y prueba de los modelos deber cargarse en el propio clúster. La funcion as.h2o nos permite transformar cualquier data.frame objeto en un grupo de h2o:
train_h <- as.h2o(train_df)
##
|
| | 0%
|
|======================================================================| 100%
test_h <- as.h2o(test_df)
##
|
| | 0%
|
|======================================================================| 100%
Además, transformaremos el objeto predict_df(los valores futuros de las entradas de la serie) en un objeto h2o, que se utilizara para generar, mas adelante en este capitulo, el pronóstico final:
forecast_h <- as.h2o(forecast_df)
##
|
| | 0%
|
|======================================================================| 100%
Para nuestra comodidad, etiquetaremos los nombres de las variables dependientes e independientes:
x <- c("month", "lag12", "trend", "trend_sqr")
y <- "y"
Ahora que los datos se han cargado en el clúster de trabajo, podemos comenzar el proceso de capacitación.
##Entrenando un modelo de ML
El paquete h2o proporciona un conjunto de herramientas para entrenar y probar modelos de ML. Los enfoques de entrenamiento de modelos más comunes son los siguientes: • Entrenamiento/prueba: Esto se basa en dividir los datos de entrada en particiones de entrenamiento y prueba asignando la mayor parte de los datos de entrada a la partición de entrenamiento y dejando el resto a la partición de prueba. Como lo implican los nombres de las particiones, el conjunto de entrenamiento se usa para entrenar el modelo, mientras que la partición de prueba se usa para probar su rendimiento con datos nuevos. Las asignaciones típicas son 70/30 (es decir, 70% de los datos a la partición de entrenamiento y 30 % a la partición de prueba), o aproximadamente cerca de esa proporción, donde la asignación de datos entre las dos particiones debe ser aleatoria. • Entrenamiento/pruebas/validación: Esto es relativamente similar al enfoque anterior, excepto con particiones de validación agregadas. La partición de validación se utiliza durante el proceso de entrenamiento para evaluar el ajuste de los parámetros del modelo. Luego, los modelos sintonizados se prueban en la partición de prueba. • Validación cruzada: este es uno de los métodos de entrenamiento más populares para modelos de ML, ya que reduce la posibilidad de sobreajuste del modelo. Este método se basa en los siguientes pasos: 1. Dividir el conjunto de entrenamiento, aleatoriamente, en K carpetas. 2. Entrenar el modelo K veces, dejando cada vez una carpeta diferente como partición de prueba y entrenar el modelo con las carpetas K-1 restantes. 3. A lo largo del proceso de capacitación, el modelo ajusta los parámetros del modelo. 4. El modelo final se prueba en la partición de prueba.
A lo largo de este capítulo, utilizaremos el enfoque de validación cruzada (CV) para entrenar estos modelos.
Ahora que hemos preparado los datos, creado nuevas funciones y lanzado un clúster de agua, estamos listos para construir nuestro primer modelo de pronóstico con el algoritmo Random Forest (RF). El algoritmo RF es uno de los modelos ML más populares y se puede utilizar tanto para problemas de clasificación como de regresión. En pocas palabras, el algoritmo de RF se basa en un conjunto de múltiples modelos de árboles. Como su nombre lo indica, tiene dos componentes principales:
• Aleatorio: la entrada para cada modelo de árbol se basa en una muestra aleatoria, junto con el reemplazo tanto de las columnas como de las filas de los datos de entrada. Este método también se conoce como embolsado. • Bosque: la colección de modelos basados en árboles, que eventualmente crea el bosque.
Una vez construido el bosque, el algoritmo reúne la predicción de todos los árboles del bosque en una sola salida. Esta combinación de aleatorizar la entrada para cada modelo de árbol y luego promediar sus resultados reduce la probabilidad de sobreajustar el modelo.
RF tiene varios parámetros de ajuste que le permiten controlar el nivel de aleatorización del proceso de muestreo y la profundidad del bosque. La función h2o.randomForest del paquete h2o proporciona el marco para entrenar y ajustar el modelo de RF. Los siguientes son los principales parámetros del agua. función de bosque aleatorio: •x: un vector de caracteres con nombres de variables independientes •y: una cadena, que es el nombre de la variable dependiente •Training_frame: Los datos de entrada deben ser datos. marco del paquete h20 • validation_frame: opcional; debe usarse al aplicar un enfoque de entrenamiento con el conjunto de validación •nfolds: el número de K-folds para el proceso CV •ntrees: Número de árboles a crear •sample_rate: define el número de filas para muestrear por árbol •max_ Depth: establece la profundidad máxima del árbol (número de nodos); A medida que los árboles crecen más profundos, la complejidad del modo aumenta, así como el riesgo de sobreajuste. •semilla: establece el valor inicial del generador de números aleatorios.
Además. esta funcion tiene varios argumentos de control, lo que le permite controlar el tiempo de ejecucion del modelo. Ademas, le permiten establecer criterios de parada para el modo si agregar arboles adicionales no mejora el rendimiento del modelo. Estos argumentos son los sgtes: • stop_metric: define el tipo de metrica de error que se utilizará para evaluar si el modelo debe deternerse y construir nuevos arboles ya que no hay mejoras adicionales. • stop_tolerance: establece la mejora mínima que se requiere para continuar el proceso de formacion. • stop_rounds: establece el numero de rondas que se deben utilizar antes de detener el entrenamiento.
Comenzaremos con un modelo de RF simplista utilizando 500 arboles y entrenamiento CV de 5 carpetas. Además, agregaremos un criterio de parada para evitar que el modelo se ajuste al modelo mientras no haya cambios significativos en el rendimiento del modelo. En este caso, estableceremos la métrica de parada como RMSE, la tolerancia de parada como 0.0001 y los redondeos de parada a 10:
rf_md <- h2o.randomForest(training_frame = train_h,
nfolds = 5,
x = x,
y = y,
ntrees = 500,
stopping_rounds = 10,
stopping_metric = "RMSE",
score_each_iteration = TRUE,
stopping_tolerance = 0.0001,
seed = 1234)
##
|
| | 0%
|
|================================================ | 68%
|
|======================================================================| 100%
La funcion h2o.randomForest devuelve un objeto con informacion sobre la configuracion de los parametros del modelo y su rendimiento en el conjunto de entrenamiento (y validacion, si se usa). Podemos ver la contribucion de las entradas del modelo con el h2o.varimp_plot. Esta funcion devuelve un grafico con la clasificacion de la contribucion de las variables de entrada al rendimiento del modelo utilizando una escala entre 0 y 1, como se muestra a continuación:
h2o.varimp_plot(rf_md)
Como podemos ver en el gráfico de importancia de la variable anterior, la variable de retraso, lag12, es la más importante para el modelo. Esto no debería ser una sorpresa ya que vimos la fuerte relación entre la serie y su desfase estacional en el análisis de correlación. Inmediatamente después de esto, las variables más importantes son trend_sqr, mes y tendencia.
La salida del modelo contiene (además del modelo en sí) información sobre el rendimiento y los parámetros del modelo. Repasemos el resumen del modelo:
rf_md@model$model_summary
## Model Summary:
## number_of_trees number_of_internal_trees model_size_in_bytes min_depth
## 1 41 41 31588 8
## max_depth mean_depth min_leaves max_leaves mean_leaves
## 1 12 10.04878 45 66 56.70732
Podemos ver que utilizamos sólo 42 árboles de los 500 establecidos por el argumento ntrees. Esto se debe a los parámetros de parada que se utilizaron en el modelo. El siguiente gráfico demuestra el proceso de aprendizaje del modelo en función del número de árboles:
library(plotly)
tree_score <- rf_md@model$scoring_history$training_rmse
plot_ly(x = seq_along(tree_score), y = tree_score,
type = "scatter", mode = "line") %>%
layout(title = "Random Forest Model - Trained Score History",
yaxis = list(title = "RMSE"),
xaxis = list(title = "Num. of Trees"))
## Warning: Ignoring 1 observations
Por último, pero no menos importante, midamos el rendimiento del modelo en la participacion de prueba. Usaremos la funicon de h2o.predict para predecir los valores correspondientes de la serie en la partición de prueba:
test_h$pred_rf <- h2o.predict(rf_md, test_h)
##
|
| | 0%
|
|======================================================================| 100%
A continuación, podemos tranferir el marco de datos de agua de un data.frame de marco con la funcion as.data.frame:
test_1 <- as.data.frame(test_h)
Ahora podemos calcular la puntuacion MAPE del modelo RF en la particion de prueba:
mape_rf <- mean(abs(test_1$y - test_1$pred_rf) / test_1$y)
mape_rf
## [1] 0.04647164
Como puede ver en la puntuación de error del modelo, el modelo RF con su configuración predeterminada pudo lograr una tasa de error más baja que nuestro modelo de referencia, es decir, el modelo de regresión lineal, con una puntuación MAPE del 3,7 % en comparación con el 4 %.
Generalmente, cuando se utiliza la opción predeterminada para los parámetros del modelo, el modelo puede funcionar bien, pero es posible que quede algo de espacio para optimización y mejora adicionales con respecto al rendimiento del modelo. Existe una variedad de técnicas para la optimización del modelo y el ajuste de parámetros, como el ajuste manual, la búsqueda en cuadrícula y sintonización basada en algoritmos. En los capítulos anteriores, analizamos ejemplos de estos tres enfoques: ajustamos manualmente el modelo ARMA en el Capítulo 11, Pronósticos con modelos ARIMA, usamos la función ts_grid en el Capítulo 10, Pronósticos con modelos de suavizado exponencial, para ajustar el modelo Holt-Winters. parámetros con búsqueda de cuadrícula y automatizó el ajuste del modelo ARIMA (nuevamente en el Capítulo 11, Pronósticos con modelos ARIMA) con el algoritmo auto.arima.
Demostraremos un enfoque de búsqueda de cuadrícula para ajustar un modelo de ML con la función h2o.grid. Más adelante en este capítulo, veremos un enfoque basado en algoritmos para ajustar un modelo N ML con la función h2o.automl.
La funcion h2o.grid le permite establecer un conjunto de valores para algunos parámetros seleccionados y probar su rendimiento en el modelo para identificar los parámetros de ajuste que optimizan el rendimiento del modelo. Los principales argumentos de esta función son los siguientes: • algorithm: Define el tipo de algoritmo a utilizar en la búsqueda en grid. • hyper_params: establece los valores del parámetro de búsqueda. • search_criteria: establece roles para la búsqueda, como la métrica de detención del modelo, el número de modelos y el tiempo de ejecución.
Cualquiera de los enfoques de entrenamiento del paquete h2o (como CV, entrenamiento con validación) se puede aplicar con la funcion h2o.grid.
Empezaremos configurando los parametros de busqueda:
hyper_params_rf <- list(mtries = c(2, 3, 4),
sample_rate = c(0.632, 0.8, 0.95),
col_sample_rate_per_tree = c(0.5, 0.9, 1.0),
max_depth = c(seq(1, 30, 3)),
min_rows = c(1, 2, 5, 10))
Aquí, los parametros que seleccionamos son los sgtes:
Cuanto mas parametros agregue o defina para una amplia gama de valores, mayor será la combinacion de busqueda posible. Esto podría llegar facilmente a cientos de combinaciones, que pueden ejecutarse durante un par de horas (segun la potenica informatica disponible). Por lo tanto, establecer el argumento search.criteria es muy importante por razones de eficencia. El argumento de estrategia del search.criteria le permite hacer unaj busqueda cartesiana (Cartesian) o una busqueda aleatoria (RandomDiscrete). La busqueda cartesiana iteria y calcula los modelos para todas las opciones de busquedas posibles en orden cronologico. Por otro lado, la busqueda aleatoria selecciona aleatoriamente una combinacion de busqueda de la tabla de busqueda de la cuadricula.
Tendria sentido utilizar el metodo cartesiano cuando el numero de combinaciones de busqueda sea bastante pequeño o cuando no este limitado en el tiempo de busqueda. Por otro lado, para una gran cantidad de combinaciones de busqueda, o cuando tenemos una limitacion de tiempo, se recomienda utilizar la busqueda aleatoria. Por razones de eficiencia, estableceremos una busqueda aleatoria y restringiremos el tiempo de busqueda a 20 minutos con max_runtime_sec. Usaremos la misma metrica que parada que usamos anteriormente:
search_criteria_rf <- list(strategy = "RandomDiscrete",
stopping_metric = "rmse",
stopping_tolerance = 0.0001,
stopping_rounds = 10,
max_runtime_secs = 60 * 20)
Despues de configurar los argumentos de busqueda para la funcion de h2o.grid, podemos iniciar la busqueda:
rf2 <- h2o.grid(algorithm = "randomForest",
search_criteria = search_criteria_rf,
hyper_params = hyper_params_rf,
x = x,
y = y,
training_frame = train_h,
ntrees = 5000,
nfolds = 5,
grid_id = "rf_grid",
seed = 1234)
##
|
| | 0%
|
|== | 2%
|
|== | 3%
|
|=== | 4%
|
|=== | 5%
|
|==== | 5%
|
|==== | 6%
|
|===== | 7%
|
|===== | 8%
|
|====== | 8%
|
|====== | 9%
|
|======= | 10%
|
|======= | 11%
|
|======== | 11%
|
|========= | 12%
|
|========== | 14%
|
|========== | 15%
|
|=========== | 16%
|
|============ | 17%
|
|============= | 19%
|
|============== | 21%
|
|=============== | 21%
|
|=============== | 22%
|
|================ | 22%
|
|================ | 23%
|
|================= | 25%
|
|================== | 25%
|
|================== | 26%
|
|=================== | 26%
|
|=================== | 27%
|
|=================== | 28%
|
|==================== | 28%
|
|==================== | 29%
|
|===================== | 30%
|
|===================== | 31%
|
|====================== | 31%
|
|====================== | 32%
|
|======================= | 32%
|
|======================= | 33%
|
|======================== | 34%
|
|======================== | 35%
|
|=========================== | 38%
|
|=========================== | 39%
|
|============================ | 39%
|
|============================ | 40%
|
|============================ | 41%
|
|============================= | 41%
|
|============================= | 42%
|
|============================== | 42%
|
|============================== | 43%
|
|=============================== | 44%
|
|================================ | 46%
|
|================================= | 47%
|
|================================== | 48%
|
|================================== | 49%
|
|=================================== | 50%
|
|==================================== | 51%
|
|==================================== | 52%
|
|===================================== | 52%
|
|===================================== | 53%
|
|====================================== | 54%
|
|====================================== | 55%
|
|======================================= | 55%
|
|======================================= | 56%
|
|======================================== | 57%
|
|======================================== | 58%
|
|========================================= | 58%
|
|========================================= | 59%
|
|========================================== | 60%
|
|=========================================== | 61%
|
|=========================================== | 62%
|
|============================================ | 62%
|
|============================================ | 63%
|
|============================================= | 64%
|
|============================================= | 65%
|
|================================================= | 70%
|
|================================================== | 71%
|
|================================================== | 72%
|
|=================================================== | 72%
|
|=================================================== | 73%
|
|==================================================== | 74%
|
|==================================================== | 75%
|
|===================================================== | 75%
|
|===================================================== | 76%
|
|====================================================== | 76%
|
|====================================================== | 77%
|
|====================================================== | 78%
|
|======================================================= | 78%
|
|======================================================= | 79%
|
|======================================================== | 79%
|
|======================================================== | 80%
|
|======================================================== | 81%
|
|========================================================= | 81%
|
|========================================================= | 82%
|
|========================================================== | 82%
|
|========================================================== | 83%
|
|=========================================================== | 84%
|
|=========================================================== | 85%
|
|============================================================ | 85%
|
|============================================================ | 86%
|
|============================================================= | 87%
|
|============================================================= | 88%
|
|=============================================================== | 90%
|
|================================================================ | 91%
|
|================================================================ | 92%
|
|================================================================= | 93%
|
|================================================================== | 94%
|
|================================================================== | 95%
|
|=================================================================== | 95%
|
|=================================================================== | 96%
|
|==================================================================== | 96%
|
|==================================================================== | 97%
|
|==================================================================== | 98%
|
|===================================================================== | 98%
|
|===================================================================== | 99%
|
|======================================================================| 99%
|
|======================================================================| 100%
Notaras que mantuvimos el mismo enfoque de capacitacion, es decir, 5 carpetas de CV y la cantidad de arboles como 5000.
Ahora extraeremos los resultados de la cuadricula, ordenaremos los modelos por su puntuacion RMSE y extraeremos el modelo principial:
rf2_grid_search <- h2o.getGrid(grid_id = "rf_grid",
sort_by = "rmse",
decreasing = FALSE)
rf_grid_model <- h2o.getModel(rf2_grid_search@model_ids[[1]])
Probemos el modelo en la particion de prueba y evaluemos su rendimiento:
test_h$rf_grid <- h2o.predict(rf_grid_model, test_h)
##
|
| | 0%
|
|======================================================================| 100%
test_1 <- as.data.frame(test_h)
mape_rf2 <- mean(abs(test_1$y - test_1$rf_grid) / test_1$y)
mape_rf2
## [1] 0.03891532
El paso de optimizacion adicional contribuyo a aumentar la precision del modelo, con una puntuacion MAPE de 3.33% en comparacion con 3.7% y 4% para el primer modelo de RF que entrenamos y el modelo de regresion lineal, respectivamente. El stge grafico proporciona una vista adicional del rendimiento del modelo:
plot_ly(data = test_1) %>%
add_lines(x = ~ date, y = ~y, name = "Actual") %>%
add_lines(x = ~ date, y = ~ yhat, name = "Linear Regression", line = list(dash = "dot")) %>%
add_lines(x = ~ date, y = ~ pred_rf, name = "Random Forest", line = list(dash = "dash")) %>%
add_lines(x = ~ date, y = ~ rf_grid, name = "Random Forest (grid)", line = list(dash = "dash")) %>%
layout(title = "Total Vehicle Sales - Actual vs. Prediction (Random Forest)",
yaxis = list(title = "Thousands of Units"),
xaxis = list(title = "Month"))
##Pronosticar con el modelo GBM El algoritmo GBM es otro modelo basado en conjuntos y árboles. Utiliza el enfoque de impulso para entrenar diferentes subconjuntos de datos y repite el entrenamiento de subconjuntos que tenía el modelo con una alta tasa de error. Esto permite que el modelo aprenda de los errores pasados y mejore el poder predictivo del modelo.
Los principales argumentos del modelo GBM son los sgtes: - x: un vector de caracteres con los nombres de las variables independientes. - y: una cadena, que es el nombre de la variable dependiente. - training_frame: los datos de entrada deben ser data.frame del paquete de h2o. - validation_frame:opcional; esto debe usarse cuando aplicamos un enfoque de entrenamiento con el conjunto de validacion. - nfolds: el numero de K-folds para el proceso CV. - ntrees: numero de arboles a crear. - sample_rate: define el numero de filas para muestrear por arbol - max_depth: establece la profundidad maxima del arbol(numero de nodos). A medido que los arboles crecen mas prfundos, aumenta la complejidad del modo, asi como el riesgo de sobreajuste. - learn_rate: define la tasa de aprendizaje del modelo con valores entre 0 y 1. La tasa predeterminada es 0.1. A medida que la tasa de aprendizaje se acerque a 0, mejor será el aprendizaje del modelo, con el costo de un mayor tiempo de calculo, junto con una mayor cantidad de arboles. - seed: establece el valor inicial del generados de numeros aleatorios.
El sgte ejemplo demuestra el uso de la funcion h2o.gbm para entrenar el modelo GBM con los mismos datos de entrada que usamos anteriormente:
gbm_md <- h2o.gbm(
training_frame = train_h,
nfolds = 5,
x = x,
y = y,
max_depth = 20,
distribution = "gaussian",
ntrees = 500,
learn_rate = 0.1,
score_each_iteration = TRUE
)
##
|
| | 0%
|
|= | 1%
|
|== | 2%
|
|=== | 4%
|
|==== | 5%
|
|===== | 6%
|
|====== | 8%
|
|======= | 10%
|
|======== | 11%
|
|========== | 14%
|
|========== | 15%
|
|=========== | 15%
|
|=========== | 16%
|
|============ | 17%
|
|============= | 18%
|
|============== | 20%
|
|============== | 21%
|
|=============== | 22%
|
|================ | 23%
|
|================ | 24%
|
|================= | 24%
|
|================= | 25%
|
|================== | 25%
|
|================== | 26%
|
|=================== | 27%
|
|=================== | 28%
|
|==================== | 28%
|
|==================== | 29%
|
|===================== | 30%
|
|===================== | 31%
|
|====================== | 32%
|
|======================= | 32%
|
|======================= | 33%
|
|======================== | 35%
|
|=========================== | 38%
|
|============================ | 40%
|
|=============================== | 44%
|
|================================ | 46%
|
|================================= | 47%
|
|================================== | 48%
|
|================================== | 49%
|
|====================================== | 54%
|
|====================================== | 55%
|
|======================================= | 55%
|
|======================================= | 56%
|
|======================================== | 57%
|
|========================================= | 59%
|
|=========================================== | 61%
|
|============================================ | 64%
|
|============================================= | 64%
|
|============================================== | 65%
|
|============================================== | 66%
|
|================================================ | 68%
|
|================================================ | 69%
|
|================================================= | 70%
|
|================================================== | 71%
|
|================================================== | 72%
|
|==================================================== | 74%
|
|==================================================== | 75%
|
|===================================================== | 76%
|
|====================================================== | 77%
|
|====================================================== | 78%
|
|======================================================= | 78%
|
|======================================================= | 79%
|
|========================================================= | 82%
|
|========================================================== | 83%
|
|=========================================================== | 84%
|
|============================================================ | 85%
|
|============================================================= | 87%
|
|============================================================== | 88%
|
|============================================================== | 89%
|
|=============================================================== | 90%
|
|================================================================ | 91%
|
|================================================================ | 92%
|
|================================================================= | 93%
|
|================================================================= | 94%
|
|================================================================== | 94%
|
|================================================================== | 95%
|
|=================================================================== | 95%
|
|=================================================================== | 96%
|
|==================================================================== | 97%
|
|==================================================================== | 98%
|
|===================================================================== | 98%
|
|===================================================================== | 99%
|
|======================================================================| 99%
|
|======================================================================| 100%
De manera similar al modelo RF, podemos revisar el rango de importancia de las variables del modelo con la funcion h2o.varimp_plot:
h2o.varimp_plot(gbm_md)
Para RF, el modelo GBM clasifica la variable de retraso 12 como la mas importante para el modelo. Probemos el rendimiento del modelo en el conjunto de prueba:
test_h$pred_gbm <- h2o.predict(gbm_md, test_h)
##
|
| | 0%
|
|======================================================================| 100%
test_1 <- as.data.frame(test_h)
mape_gbm <- mean(abs(test_1$y - test_1$pred_gbm) / test_1$y)
mape_gbm
## [1] 0.03857898
El modelo GBM obtuvo el MAPE mas bajjo entre los modelos que hemos probado hasta ahora con una tasa de error del 3,8%, en comparacion con el 3,3% y el 4% del modelo RF (con busqueda de cuadrícula) y el modelo de regresión lineal, respectivamente. Sería un gran ejercicio aplicar una busqueda en cuadricula en el modelo GBM y probar si se pueden lograr mejoras adicionales.
Visualicemos los resultados y comparemos la prediccion con la prediccion real y de referencia:
plot_ly(data = test_1) %>%
add_lines(x = ~ date, y = ~y, name = "Actual") %>%
add_lines(x = ~ date, y = ~ yhat, name = "Linear Regression", line = list(dash = "dot")) %>%
add_lines(x = ~ date, y = ~ pred_gbm, name = "Gradient Boosting Machine", line = list(dash = "dash")) %>%
layout(title = "Total Vehicle Sales - Actual vs. Prediction (Gradient Boosting Machine)",
yaxis = list(title = "Thousands of Units"),
xaxis = list(title = "Month"))
##Pevision con el modelo AUTOML Hasta ahora, en este capitulo, hemos analizado dos enfoques de modelado: el primero utiliza la configuracion predetermindad del algoritmo con los modelos RF y GBM, y el segundo aplica una busqueda de cuadricula con el modleo RF. Echemos un vistazo a un tercer enfoque para ajustar los modelos de ML. Aqui usaremos la funcion h2o.automl. La funcion h2o.automl proporciona un enfoque automatizado para entrenar, ajustar y probar multiples algoritmos de ML antes de seleccionar el modelo que funcionó mejor segun la evaluacion del modelo. Utiliza algoritmos como RF, GBM, DL y otro que utilizan diferentes enfoque de ajuste.
Del mismo modo, la funcion h2o.grid de cuadricula puede aplicar cualquiera de los enfoques de entrenamiento (CV, entrenamiento con validacion, etc.) durante el proceso de entrenamiento de los modelos. Usemos la misma entrada que antes y entremos el modelo de pronostico:
autoML1 <- h2o.automl(training_frame = train_h,
x = x,
y = y,
nfolds = 5,
max_runtime_secs = 60*20,
seed = 1234)
##
|
| | 0%
## 21:13:15.397: AutoML: XGBoost is not available; skipping it.
## 21:13:20.250: _min_rows param, The dataset size is too small to split for min_rows=100.0: must have at least 200.0 (weighted) rows, but have only 96.0.
|
|=== | 5%
|
|===== | 7%
|
|====== | 8%
|
|======= | 10%
|
|======== | 12%
|
|========= | 12%
|
|============ | 17%
|
|============= | 18%
|
|============== | 20%
|
|================== | 26%
|
|=================== | 27%
|
|=================== | 28%
|
|==================== | 28%
|
|==================== | 29%
|
|===================== | 29%
|
|===================== | 30%
|
|===================== | 31%
|
|====================== | 31%
|
|====================== | 32%
|
|======================= | 32%
|
|======================= | 33%
|
|======================= | 34%
|
|======================== | 34%
|
|======================== | 35%
|
|========================= | 35%
|
|========================= | 36%
|
|========================== | 37%
|
|========================== | 38%
|
|=========================== | 38%
|
|=========================== | 39%
|
|============================ | 40%
|
|============================= | 41%
|
|============================= | 42%
|
|============================== | 43%
|
|=============================== | 44%
|
|=============================== | 45%
|
|================================ | 45%
|
|================================ | 46%
|
|================================= | 47%
|
|================================== | 48%
|
|================================== | 49%
|
|=================================== | 49%
|
|=================================== | 50%
|
|=================================== | 51%
|
|==================================== | 51%
|
|==================================== | 52%
|
|===================================== | 52%
|
|===================================== | 53%
|
|====================================== | 54%
|
|======================================= | 55%
|
|======================================= | 56%
|
|======================================== | 57%
|
|======================================== | 58%
|
|========================================= | 58%
|
|========================================= | 59%
|
|========================================== | 60%
|
|=========================================== | 61%
|
|=========================================== | 62%
|
|============================================= | 65%
|
|============================================== | 66%
|
|================================================= | 70%
|
|================================================= | 71%
|
|================================================== | 72%
|
|=================================================== | 72%
|
|====================================================== | 78%
|
|======================================================= | 78%
|
|======================================================= | 79%
|
|======================================================== | 80%
|
|========================================================= | 81%
|
|========================================================= | 82%
|
|========================================================== | 82%
|
|========================================================== | 83%
|
|=========================================================== | 84%
|
|=========================================================== | 85%
|
|============================================================ | 85%
|
|============================================================ | 86%
|
|============================================================= | 87%
|
|============================================================= | 88%
|
|============================================================== | 88%
|
|============================================================== | 89%
|
|=============================================================== | 90%
|
|=============================================================== | 91%
|
|================================================================ | 91%
|
|================================================================ | 92%
|
|================================================================= | 93%
|
|================================================================== | 94%
|
|================================================================== | 95%
|
|=================================================================== | 95%
|
|=================================================================== | 96%
|
|==================================================================== | 97%
|
|==================================================================== | 98%
|
|===================================================================== | 98%
|
|===================================================================== | 99%
|
|======================================================================| 99%
|
|======================================================================| 100%
En este ejmplo de prediccion, la funcion corre en un tiempo de 20 minutos. A lo que la funcion retorna en la lista con los leaderboard de todos los modelos presentes:
autoML1@leaderboard
## model_id rmse mse
## 1 StackedEnsemble_BestOfFamily_3_AutoML_1_20240429_211315 62.20578 3869.559
## 2 GBM_grid_1_AutoML_1_20240429_211315_model_126 62.44813 3899.769
## 3 DeepLearning_grid_1_AutoML_1_20240429_211315_model_1 62.98852 3967.554
## 4 GBM_grid_1_AutoML_1_20240429_211315_model_107 63.63573 4049.507
## 5 GBM_grid_1_AutoML_1_20240429_211315_model_109 63.85539 4077.511
## 6 GBM_grid_1_AutoML_1_20240429_211315_model_70 63.90181 4083.441
## mae rmsle mean_residual_deviance
## 1 50.12492 0.04747200 3869.559
## 2 50.49076 0.04852091 3899.769
## 3 49.88275 0.04794982 3967.554
## 4 50.47346 0.04789169 4049.507
## 5 51.93394 0.05014322 4077.511
## 6 49.69000 0.04933614 4083.441
##
## [138 rows x 6 columns]
Podemos ver que en este caso, los mejores modelos de DL con diferentes configuraciones de ajuste. Seleccionaremos el modelo lider y probaremos su rendimiento en el conjunto de pruebas:
test_h$pred_autoML <- h2o.predict(autoML1@leader, test_h)
##
|
| | 0%
|
|======================================================================| 100%
test_1 <- as.data.frame(test_h)
mape_autoML <- mean(abs(test_1$y - test_1$pred_autoML) / test_1$y)
mape_autoML
## [1] 0.03489004
El modelo GBM obtuvo el MAPE más bajo entre los modelos que hemos probado hasta ahora con una tasa de error del 3,7%, en comparacion con el 3,3% y el 4% del modelo RF (con busqueda de cuadrícula) y el moelo de regresion lineal, respectivamente. Sería un gran ejercicio aplicar una busqueda en cuadricula en el modelo GBM y probar si se pueden lograr mejoras adicionales.
Visualicemos los resultados y comparemos la prediccion con la prediccion real y de referencia:
plot_ly(data = test_1) %>%
add_lines(x = ~ date, y = ~y, name = "Actual") %>%
add_lines(x = ~ date, y = ~ yhat, name = "Linear Regression", line = list(dash = "dot")) %>%
add_lines(x = ~ date, y = ~ pred_autoML, name = "autoML", line = list(dash = "dash")) %>%
layout(title = "Total Vehicle Sales - Actual vs. Prediction (Auto ML Model)",
yaxis = list(title = "Thousands of Units"),
xaxis = list(title = "Month"))
La principal ventaja del h2o.autmol es que puede ampliarse teniendo multiples series para pronosticar con una minima intervencion por parte del usuario. Esto, por supuesto, conlleva potenica de calculo adicional y coste de tiempo.
##Seleccionando el modelo final
Ahora que hemos terminado el proceso de entrenamiento y prueba de los modelos, es hora de finalizar el proceso y elegir el modelo a pronosticar con la serie. Entrenamos los siguientes modelos: • Modelo de referencia: modelo de regresión lineal con puntuación MAPE del 4% en la partición de prueba • RF: uso de parámetros de ajuste predeterminados con puntuación MAPE del 3,74 % en la partición de prueba • RF: uso de búsqueda de cuadrícula para ajustar los parámetros del modelo con una puntuación MAPE del 3,33 % en la partición de prueba • GBM: uso de los parámetros de ajuste predeterminados con una puntuación MAPE del 2,75 % en la partición de prueba • AutoML: selección de un modelo de aprendizaje profundo con una puntuación MAPE del 3,48 % en la partición de prueba
Dado que todos estos modelos lograron mejores resultados que el modelo de referencia, podemos descartar el modelo de referencia. Además, dado que el segundo modelo de RF (con búsqueda de cuadrícula) logró mejores resultados que el primero, no tiene sentido conservar el primer modelo. Esto nos deja con tres modelos de pronóstico, es decir, RF (con búsqueda de cuadrícula), GBM y AutoML. Generalmente, dado que el modelo GBM logró los mejores resultados MAPE, lo seleccionaremos. Sin embargo, siempre es bueno trazar el pronóstico real y comprobar cómo se ve el pronóstico real. Antes de trazar los resultados, usemos estos tres modelos para pronosticar los próximos 12 meses usando los datos. pronóstico de marco que creamos en las secciones Pronóstico con el modelo Random Forest y Pronóstico con el modelo GBM:
forecast_h$pred_gbm <- h2o.predict(gbm_md, forecast_h)
##
|
| | 0%
|
|======================================================================| 100%
forecast_h$pred_rf <- h2o.predict(rf_grid_model, forecast_h)
##
|
| | 0%
|
|======================================================================| 100%
forecast_h$pred_automl <- h2o.predict(autoML1@leader, forecast_h)
##
|
| | 0%
|
|======================================================================| 100%
Ellos podrian transformarse en objecto volviendo a data.frame con la funcion as.dat.frame:
final_forecast <- as.data.frame(forecast_h)
Ahora, nosotros podemos visualizar los pronosticos con el paquete plotly:
plot_ly(x = df$date, y = df$y,
type = "scatter",
mode = "line",
name = "Actual") %>%
add_lines(x = final_forecast$date, y = final_forecast$pred_rf, name = "Random Forest") %>%
add_lines(x = final_forecast$date, y = final_forecast$pred_gbm, name = "GBM") %>%
add_lines(x = final_forecast$date, y = final_forecast$pred_automl, name = "Auto ML") %>%
layout(title = "Total Vehicle Sales - Final Forecast",
yaxis = list(title = "Thousands of Units", range = c(1100, 1750)),
xaxis = list(title = "Month", range = c(as.Date("2016-01-01"), as.Date("2020-01-01"))))
Parece que los tres modelos capturan el componente estacional de la serie de ventas de vehículos. Sin embargo, parece que la oscilación de AutoML es mayor con respecto a uno de los modelos RF y GBM. Por lo tanto, tendría sentido seleccionar los modelos GBM o RF como pronóstico final. Un enfoque más conservador sería crear y combinar los tres pronósticos ponderándolos según el promedio regular. Por ejemplo, puede utilizar una función simple para probar el promedio diferente de diferentes modelos y seleccionar la combinación que minimice la tasa de error de pronóstico en el conjunto de prueba.