Modelos Globales con Modeltime

Una introducción a los modelos globales con modeltime

Modeltime 📈 y Modelos Globales 🌏

Modeltime es un paquete enfocado a series temporales que ha decidido apostar por los modelos globales como estrategia principal para afrontar los nuevos retos de escalabilidad que han venido surgiendo en los últimos años. El número de series temporales ha aumentado de manera exponencial: las organizaciones cada vez disponen de más información a su alcance y a un nivel más desagregado*. Desafortunadamente, las aproximaciones tradicionales, como los modelos ARIMA, en las que se calcula un modelo para cada una de las series temporales disponibles, termina por no ser escalable (Supongamos una organización con 10 mil productos, necesitaría iterar para crear 10 mil modelos y eso sin tener en cuenta hyperparameter tuning). Esta estrategia iterativa puede convertirse en una auténtica pesadilla a medida que las organizaciones crecen al no ser escalable.

¿Cuál es la alternativa propuesta por Modeltime?

La alternativa propuesta por Modeltime es utilizar datos en panel y modelos globales. ¿Qué significan estos conceptos? Los datos en panel son básicamente un dataset que contiene varias series temporales apiladas una encima de la otra. En la siguiente imagen puede verse un ejemplo:

Imagen extraída del artículo Forecasting Many Time Series (Using NO For-Loops) de Matt Dancho

Un modelo global es un modelo único que pronostica todas las series temporales a la vez. Los modelos globales son altamente escalables. Un ejemplo es un modelo XGBoost, que puede determinar las relaciones para todos los 1000 paneles de series temporales con un solo modelo. Veamos un ejemplo:

Imagen extraída del artículo Forecasting Many Time Series (Using NO For-Loops) de Matt Dancho

Caso de Uso: Predicción 🔮 de la Generación Eléctrica 💡 por Sectores de la Generalitat de Catalunya

⚠️ Advertencia️ ⚠️: El objetivo de este post no es alcanzar los mejores resultados posibles, pues ello requeriría de una dedicación considerable en tareas como Feature Engineering. Lo que se pretende es mostrar una metodología de trabajo a la hora de utilizar el paquete Modeltime para modelos globales.

Para este post vamos a utilizar el dataset que se encuentra en la página https://datos.gob.es/ subido por la Generalitat de catalunya en el que se mide la generación eléctrica (GWh) en el período 2005-2020 y cuyo análisis se realizará para diferentes sectores de la economía.

En primer lugar, vamos a cargar los paquetes 📦 necesarios y a leer los datos:

#CATBOOST: devtools::install_github('catboost/catboost', subdir = 'catboost/R-package')
#BOOSTIME: devtools::install_github("AlbertoAlmuinha/boostime")

library(boostime)
library(timetk)
library(lubridate)
library(modeltime)
library(tidymodels)
library(tidyverse)
library(sknifedatar)
library(gt)

url <- "https://analisi.transparenciacatalunya.cat/api/views/j7xc-3kfh/rows.csv?accessType=DOWNLOAD"

df <- read_csv(url)

El siguiente paso es limpiar los datos. Para ello seleccionamos aquellas columnas que nos interesan y transformamos el campo fecha para adaptarlo al formato que nos interesa para modelar.

df <- df %>%
    select(Data, starts_with("FEEI")) %>%
    mutate(Data = mdy_hms(Data) %>% date()) %>%
    rename(date = Data) %>%
    rename_with(.cols = starts_with("FEEI"),
                .fn   = ~str_replace(., "FEEI_", ""))

head(df) %>% 
  gt() %>% 
  tab_header(title = md('**Datos por Sector (Catalunya)**')) %>% 
  opt_align_table_header('left')
Datos por Sector (Catalunya)
date ConsObrPub SiderFoneria Metalurgia IndusVidre CimentsCalGuix AltresMatConstr QuimPetroquim ConstrMedTrans RestaTransforMetal AlimBegudaTabac TextilConfecCuirCalçat PastaPaperCartro AltresIndus
2014-08-01 20.7 116.3 12.9 32.0 29.3 23.0 421.1 58.1 107.3 182.1 61.3 77.1 153.3
2021-03-01 20.9 130.1 11.6 20.1 29.2 19.4 290.4 58.2 107.7 160.1 50.9 75.1 129.0
2021-04-01 24.4 128.6 12.9 27.0 36.6 22.6 336.3 64.9 110.4 183.8 54.8 83.2 136.6
2021-05-01 23.4 125.2 11.7 22.9 32.2 20.4 299.0 59.3 101.4 166.0 47.8 82.9 125.8
2005-01-01 24.1 96.0 13.4 29.0 67.2 32.3 359.8 48.7 119.4 133.7 104.0 69.3 161.2
2005-02-01 25.8 106.0 14.2 31.5 68.4 35.0 351.9 54.8 135.8 133.5 110.6 75.3 181.3

Si te fijas, nuestro dataset aún no está en el formato adecuado para ser utilizado por un modelo global, necesitamos poner cada serie temporal una encima de otra (panel data). Vamos a ello:

df <- df %>%
        pivot_longer(-date) %>%
        rename(id = name) %>%
        mutate(id = as.factor(id))

head(df) %>% 
  gt() %>% 
  tab_header(title = md('**Datos en Formato Panel**')) %>% 
  opt_align_table_header('left')
Datos en Formato Panel
date id value
2014-08-01 ConsObrPub 20.7
2014-08-01 SiderFoneria 116.3
2014-08-01 Metalurgia 12.9
2014-08-01 IndusVidre 32.0
2014-08-01 CimentsCalGuix 29.3
2014-08-01 AltresMatConstr 23.0

El siguiente paso será visualizar nuestras series temporales a través de la función plot_time_series(). Utilizaremos también la función plot_anomaly_diagnostics() para visualizar los outliers detectados por esta función en cada serie. Para la visualización haremos uso de la funcionalidad automagic_tabs2 para poder visualizar cada serie temporal en una tab diferente de manera cómoda.

nest_data <- df %>% 
    nest(data = -id) %>%
    mutate(ts_plots = map(data, 
                          ~ plot_time_series(.data = .x,
                                             .date_var = date,
                                             .value = value,
                                             .smooth = FALSE
                          )),
           ts_anomaly = map(data, 
                          ~ plot_anomaly_diagnostics(.data = .x,
                                                     .date_var = date,
                                                     .value = value,
                                                     .alpha = 0.05)
                          ))

xaringanExtra::use_panelset()

ConsObrPub

SiderFoneria

Metalurgia

IndusVidre

CimentsCalGuix

AltresMatConstr

QuimPetroquim

ConstrMedTrans

RestaTransforMetal

AlimBegudaTabac

TextilConfecCuirCalçat

PastaPaperCartro

AltresIndus