El Machine Learning (aprendizaje automático) es una rama de la inteligencia artificial que estudia el diseño de algoritmos que “pueden aprender”. Las tareas típicas del Machine Learning son el aprendizaje conceptual, el aprendizaje funcional o el “modelado predictivo”, la agrupación y la búsqueda de patrones predictivos. Estas tareas se aprenden a través de los datos disponibles que se observaron a través de experiencias o instrucciones, por ejemplo. El aprendizaje automático espera que incluir la experiencia en sus tareas eventualmente mejore el aprendizaje. El objetivo final es mejorar el aprendizaje de tal manera que se vuelva automático, de modo que los humanos ya no tengan que interferir.
Una visualización es el primer paso para comprender cómo planearemos abordar el problema de pronóstico. Dividiremos los datos en dos regiones: una región de entrenamiento y una región de prueba.
Para visualizar el código completo del taller visita mi repositorio en el link siguiente:
(Mouse botón derecho-abrir enlace en una pestaña nueva)
Utilizaremos el conjunto de datos Bike Sharing del repositorio de aprendizaje automático UCI. Descargar los datos y seleccionar el archivo “day.csv” de periodicidad diaria.
Fuente: Fanaee-T, Hadi y Gama, Joao, ‘Etiquetado de eventos que combina detectores de conjunto y conocimientos básicos’, Progress in Artificial Intelligence (2013): pp. 1-15, Springer Berlin Heidelberg
Se dividen los datos en entrenamiento y conjunto de pruebas.
Comenzando con el conjunto de entrenamiento, que tiene las columnas “Date” y “Value”.
## # A tibble: 547 x 2
## date value
## <date> <dbl>
## 1 2011-01-01 985
## 2 2011-01-02 801
## 3 2011-01-03 1349
## 4 2011-01-04 1562
## 5 2011-01-05 1600
## 6 2011-01-06 1606
## 7 2011-01-07 1510
## 8 2011-01-08 959
## 9 2011-01-09 822
## 10 2011-01-10 1321
## # ... with 537 more rows
El primer paso es agregar la especificación de la serie temporal al conjunto de entrenamiento, que se usará para aprender los patrones. El paquete timetk 0.1.3 será la integración con el paquete “recipe” de R:
El paquete “recipe” nos permite agregar pasos de preprocesamiento que se aplican secuencialmente como parte de un “pipeline” de transformación de datos.
El timetkhas step_timeseries_signature(), se utiliza para agregar una serie de características que pueden ayudar a los modelos de aprendizaje automático.
Podemos ver qué sucede cuando aplicamos una receta preparada prep()usando la bake()función. Se agregaron muchas columnas nuevas de la función de “Date” de fecha y hora. Estas son características que podemos usar en nuestros modelos de aprendizaje automático.
## # A tibble: 547 x 29
## date value date_index.num date_year date_year.iso date_half
## <date> <dbl> <int> <int> <int> <int>
## 1 2011-01-01 985 1293840000 2011 2010 1
## 2 2011-01-02 801 1293926400 2011 2010 1
## 3 2011-01-03 1349 1294012800 2011 2011 1
## 4 2011-01-04 1562 1294099200 2011 2011 1
## 5 2011-01-05 1600 1294185600 2011 2011 1
## 6 2011-01-06 1606 1294272000 2011 2011 1
## 7 2011-01-07 1510 1294358400 2011 2011 1
## 8 2011-01-08 959 1294444800 2011 2011 1
## 9 2011-01-09 822 1294531200 2011 2011 1
## 10 2011-01-10 1321 1294617600 2011 2011 1
## # ... with 537 more rows, and 23 more variables: date_quarter <int>,
## # date_month <int>, date_month.xts <int>, date_month.lbl <ord>,
## # date_day <int>, date_hour <int>, date_minute <int>, date_second <int>,
## # date_hour12 <int>, date_am.pm <int>, date_wday <int>, date_wday.xts <int>,
## # date_wday.lbl <ord>, date_mday <int>, date_qday <int>, date_yday <int>,
## # date_mweek <int>, date_week <int>, date_week.iso <int>, date_week2 <int>,
## # date_week3 <int>, date_week4 <int>, date_mday7 <int>
A continuación, se aplican varios pasos de preprocesamiento para mejorar el comportamiento de modelado.
recipe_spec_final <- recipe_spec_timeseries %>%
step_rm(date) %>%
step_rm(contains("iso"), contains("minute"), contains("hour"),
contains("am.pm"), contains("xts")) %>%
step_normalize(contains("index.num"), date_year) %>%
step_dummy(contains("lbl"), one_hot = TRUE) %>%
step_ns(date_index.num, deg_free = 3)
## # A tibble: 547 x 39
## value date_year date_half date_quarter date_month date_day date_second
## <dbl> <dbl> <int> <int> <int> <int> <int>
## 1 985 -0.705 1 1 1 1 0
## 2 801 -0.705 1 1 1 2 0
## 3 1349 -0.705 1 1 1 3 0
## 4 1562 -0.705 1 1 1 4 0
## 5 1600 -0.705 1 1 1 5 0
## 6 1606 -0.705 1 1 1 6 0
## 7 1510 -0.705 1 1 1 7 0
## 8 959 -0.705 1 1 1 8 0
## 9 822 -0.705 1 1 1 9 0
## 10 1321 -0.705 1 1 1 10 0
## # ... with 537 more rows, and 32 more variables: date_wday <int>,
## # date_mday <int>, date_qday <int>, date_yday <int>, date_mweek <int>,
## # date_week <int>, date_week2 <int>, date_week3 <int>, date_week4 <int>,
## # date_mday7 <int>, date_month.lbl_01 <dbl>, date_month.lbl_02 <dbl>,
## # date_month.lbl_03 <dbl>, date_month.lbl_04 <dbl>, date_month.lbl_05 <dbl>,
## # date_month.lbl_06 <dbl>, date_month.lbl_07 <dbl>, date_month.lbl_08 <dbl>,
## # date_month.lbl_09 <dbl>, date_month.lbl_10 <dbl>, date_month.lbl_11 <dbl>,
## # date_month.lbl_12 <dbl>, date_wday.lbl_1 <dbl>, date_wday.lbl_2 <dbl>,
## # date_wday.lbl_3 <dbl>, date_wday.lbl_4 <dbl>, date_wday.lbl_5 <dbl>,
## # date_wday.lbl_6 <dbl>, date_wday.lbl_7 <dbl>, date_index.num_ns_1 <dbl>,
## # date_index.num_ns_2 <dbl>, date_index.num_ns_3 <dbl>
Podemos combinar la receta de preprocesamiento y el modelo usando un workflow().
## == Workflow ============================================================
## Preprocessor: Recipe
## Model: linear_reg()
##
## -- Preprocessor --------------------------------------------------------
## 6 Recipe Steps
##
## * step_timeseries_signature()
## * step_rm()
## * step_rm()
## * step_normalize()
## * step_dummy()
## * step_ns()
##
## -- Model ---------------------------------------------------------------
## Linear Regression Model Specification (regression)
##
## Main Arguments:
## penalty = 0.001
## mixture = 0.5
##
## Computational engine: glmnet
El flujo de trabajo se puede entrenar con la función fit()
Con un modelo adecuado a la mano, podemos pronosticar utilizando el conjunto de “prueba” para fines de validación.
## # A tibble: 184 x 3
## .pred date value
## <dbl> <date> <dbl>
## 1 6288. 2012-07-01 5531
## 2 6541. 2012-07-02 6227
## 3 6728. 2012-07-03 6660
## 4 6570. 2012-07-04 7403
## 5 6798. 2012-07-05 6241
## 6 6821. 2012-07-06 6207
## 7 6718. 2012-07-07 4840
## 8 6516. 2012-07-08 4672
## 9 6520. 2012-07-09 6569
## 10 6707. 2012-07-10 6290
## # ... with 174 more rows
La precisión del pronóstico fuera de la muestra se puede medir con yardstick.
## # A tibble: 3 x 3
## .metric .estimator .estimate
## <chr> <chr> <dbl>
## 1 rmse standard 1465.
## 2 rsq standard 0.371
## 3 mae standard 1197.
A continuación, podemos visualizar los residuos del conjunto de prueba. Los residuos del modelo no son perfectos, pero podemos trabajar con él. Los residuos muestran que el modelo pronostica baja en octubre y alta en diciembre.
En este punto, se puede volver al modelo e intentar ajustar las características usando interacciones o términos polinómicos, agregando otras características que puedan conocerse en el futuro (por ejemplo, la temperatura del día se puede pronosticar con relativa precisión dentro de los 7 días), o intentar una técnica diferente de modelado con la esperanza de mejores predicciones en el conjunto de prueba. Una vez que sienta que su modelo está optimizado, avance al paso final de pronósticos.
Se usará el modelo para predecir cuáles son los valores futuros esperados para los próximos seis meses. El primer paso es crear la secuencia de fechas. Usemos tk_get_timeseries_summary()para revisar el resumen de las fechas del conjunto de datos original, “Bikes”.
Los primeros seis parámetros son información de resumen general.
## # A tibble: 1 x 6
## n.obs start end units scale tzone
## <int> <date> <date> <chr> <chr> <chr>
## 1 731 2011-01-01 2012-12-31 days day UTC
## # A tibble: 1 x 6
## diff.minimum diff.q1 diff.median diff.mean diff.q3 diff.maximum
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 86400 86400 86400 86400 86400 86400
Por el resumen, sabemos que los datos son 100% regulares porque la mediana y las diferencias de medias son 86400 segundos o 1 día. No necesitamos hacer ninguna inspección especial cuando usamos tk_make_future_timeseries(). Si los datos fueran irregulares, lo que significa que se excluyeron los fines de semana o días festivos, se debe tener esto en cuenta. De lo contrario, el pronóstico sería inexacto.
Se vuelve a entrenar la especificación del modelo en el conjunto de datos completo, luego pronósticos para los próximos 6 meses.
Un pronóstico nunca es perfecto. Necesitamos intervalos de predicción para tener en cuenta la varianza de las predicciones del modelo a los datos reales. Hay varios métodos para lograr esto. Seguiremos la metodología del intérvalo de predicción de pronóstico.
test_resid_sd <- prediction_tbl %>%
summarize(stdev = sd(value - .pred))
future_predictions_tbl <- future_predictions_tbl %>%
mutate(
lo.95 = .pred - 1.96 * test_resid_sd$stdev,
lo.80 = .pred - 1.28 * test_resid_sd$stdev,
hi.80 = .pred + 1.28 * test_resid_sd$stdev,
hi.95 = .pred + 1.96 * test_resid_sd$stdev
)
El pronóstico utilizando los paquetes de series de tiempo puede ser muy preciso, especialmente cuando hay patrones basados en el tiempo en los datos subyacentes. Como con la mayoría de las aplicaciones de Machine Learning, la predicción es tan buena como los patrones en los datos. El pronóstico utilizando este enfoque puede no ser adecuado cuando los patrones no están presentes o cuando el futuro es altamente incierto (es decir, el pasado no es un predictor adecuado del rendimiento futuro). Sin embargo, en muchas situaciones, el paquete de serie temporal puede proporcionar un pronóstico preciso.
Los grandes minoristas, la cadena de suministro y los expertos en logística están utilizando el pronóstico de aprendizaje automático para ayudar a mejorar la participación del cliente y producir pronósticos de demanda más precisos mejor que las técnicas de pronóstico tradicionales.
Jesús B Zerpa |Economist & Data Scientist|