• Introducción
  • Librerías
  • Datos
  • XGBoost
  • LightGBM
  • CatBoost
  • RAPIDS cuML
  • Información de sesión
  • Instrucciones para citar


Más sobre forecasting en: cienciadedatos.net


Introducción

La mayoría de los algoritmos de machine learning se ejecutan en CPU (unidades centrales de procesamiento), procesadores de propósito general capaces de gestionar una amplia variedad de tareas. Sin embargo, las CPU no están optimizadas para las operaciones matriciales altamente paralelizadas de las que dependen muchos algoritmos, lo que a menudo da lugar a tiempos de entrenamiento más lentos y una escalabilidad limitada. En cambio, las GPU (unidades de procesamiento gráfico) están diseñadas específicamente para el procesamiento paralelo y son capaces de realizar miles de operaciones matemáticas simultáneas. Esto las hace especialmente adecuadas para entrenar e implantar modelos de machine learning a gran escala.

Varias librerías de machine learning permiten la ejecución en la GPU, entre ellas XGBoost, LightGBM, CatBoost y CuML. Al aprovechar las capacidades de la GPU, estas librerías pueden reducir drásticamente los tiempos de entrenamiento y mejorar la escalabilidad. En las siguientes secciones se muestra cómo ejecutar skforecast con aceleración en la GPU para entrenar modelos de forecasting.

✎ Note

La ventaja en el rendimiento al utilizar una GPU depende en gran medida de la tarea específica y del tamaño del conjunto de datos. En general, la aceleración mediante GPU ofrece los mayores beneficios al trabajar con conjuntos de datos grandes y modelos complejos, donde sus capacidades de procesamiento paralelo pueden reducir significativamente los tiempos de entrenamiento.

  • En el forecasting recursivo (ForecasterRecursive y ForecasterRecursiveMultiseries), la fase de predicción debe ejecutarse de forma secuencial, ya que cada paso de tiempo depende de la predicción anterior. Esta dependencia inherente impide la paralelización durante la inferencia, lo que explica por qué el ajuste del modelo es sustancialmente más rápido en una GPU, mientras que la predicción puede ser incluso más lenta en comparación con una CPU. Para superar esta limitación, skforecast cambia automáticamente el regresor para que utilice la CPU durante la predicción, incluso si fue entrenado en una GPU.
  • Los forecasters directos (ForecasterDirect, ForecasterDirectMultivariate) no dependen de predicciones anteriores durante la inferencia. Esta independencia permite que tanto el entrenamiento como la predicción se beneficien completamente de la aceleración mediante GPU.

✎ Note

A pesar de las importantes ventajas que ofrecen las GPUs para acelerar los cálculos de *machine learning*, el acceso a ellas suele ser limitado debido a los altos costos u otras restricciones prácticas. Afortunadamente, Google Colaboratory (Colab), un entorno gratuito de notebooks Jupyter, permite a los usuarios ejecutar código Python en la nube, con acceso a GPUs. Los siguientes enlaces proporcionan acceso a notebooks de Google Colab que demuestran cómo usar skforecast con aceleración por GPU.

Librerías

Las librerías necesarias para ejecutar el código de este tutorial son:

# Librerías
# ==============================================================================
import numpy as np
import pandas as pd
import torch
import psutil
import xgboost
from xgboost import XGBRegressor
import lightgbm
from lightgbm import LGBMRegressor
import catboost
from catboost import CatBoostRegressor
import cuml
from sklearn.ensemble import RandomForestRegressor
import warnings
import skforecast
from skforecast.recursive import ForecasterRecursive
from skforecast.model_selection import backtesting_forecaster, TimeSeriesFold

print(f"skforecast : {skforecast.__version__}")
print(f"xgboost    : {xgboost.__version__}")
print(f"lightgbm   : {lightgbm.__version__}")
print(f"catboost   : {catboost.__version__}")
print(f"cuml       : {cuml.__version__}")
skforecast version : 0.16.0
xgboost version    : 2.1.2
lightgbm version   : 4.5.0
catboost version   : 1.2.8
# Mostrar información sobre la GPU y la CPU
# ==============================================================================
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print('Using device:', device)

if device.type == 'cuda':
    print(torch.cuda.get_device_name(0))
    print('Memory Usage:')
    print('Allocated :', round(torch.cuda.memory_allocated(0) / 1024**3, 1), 'GB')
    print('Reserved  :', round(torch.cuda.memory_reserved(0) / 1024**3, 1), 'GB')

print(f"CPU RAM Free: {psutil.virtual_memory().available / 1024**3:.2f} GB")
Using device: cuda
NVIDIA T1200 Laptop GPU
Memory Usage:
Allocated : 0.0 GB
Reserved  : 0.0 GB
CPU RAM Free: 13.62 GB

Datos

Se simula una serie temporal con un millón de observaciones.

# Datos
# ==============================================================================
n = 1_000_000
data = pd.Series(
    data  = np.random.normal(size=n), 
    index = pd.date_range(start="1990-01-01", periods=n, freq="h"),
    name  = 'y'
)
data.head(2)
1990-01-01 00:00:00    1.500408
1990-01-01 01:00:00   -1.112868
Freq: h, Name: y, dtype: float64

XGBoost

Para ejecutar un modelo de XGBoost (versión 2.0 o superior) en una GPU, se debe establecer el argumento device='cuda' durante la inicialización.

# Suppress warnings
# ==============================================================================
warnings.filterwarnings(
    "ignore",
    message=".*Falling back to prediction using DMatrix.*",
    category=UserWarning,
    module="xgboost"
)
# Crear y entrenar un forecaster con un XGBRegressor usando GPU
# ==============================================================================
forecaster = ForecasterRecursive(
                 regressor = XGBRegressor(
                                 n_estimators = 1000,
                                 device       = 'cuda',
                                 verbosity    = 1
                             ),
                 lags = 50
             )

start_time = pd.Timestamp.now()
forecaster.fit(y=data)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Training time using GPU: {elapsed_time}")

# Predict
# ==============================================================================
start_time = pd.Timestamp.now()
forecaster.predict(steps=100)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Prediction time using GPU: {elapsed_time}")

# Backtesting
# ==============================================================================
cv = TimeSeriesFold(
         steps              = 100,
         initial_train_size = 990_000,
         refit              = False,
         verbose            = False
     )
start_time = pd.Timestamp.now()
_ = backtesting_forecaster(
        forecaster = forecaster,
        y          = data,
        cv         = cv,
        metric     = 'mean_absolute_error'

    )
elapsed_time = pd.Timestamp.now() - start_time

print(f"Backtesting time using GPU: {elapsed_time}")
Training time using GPU: 0 days 00:00:28.760755
Prediction time using GPU: 0 days 00:00:00.095367
  0%|          | 0/100 [00:00<?, ?it/s]
Backtesting time using GPU: 0 days 00:00:43.120299
# Crear y entrenar un forecaster con un XGBRegressor usando CPU
# ==============================================================================
forecaster = ForecasterRecursive(
                 regressor = XGBRegressor(n_estimators=1000),
                 lags      = 50
             )

start_time = pd.Timestamp.now()
forecaster.fit(y=data)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Training time using CPU: {elapsed_time}")

# Predict
# ==============================================================================
start_time = pd.Timestamp.now()
forecaster.predict(steps=100)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Prediction time using CPU: {elapsed_time}")

# Backtesting
# ==============================================================================
start_time = pd.Timestamp.now()
_ = backtesting_forecaster(
        forecaster = forecaster,
        y          = data,
        cv         = cv,
        metric     = 'mean_absolute_error'

    )
elapsed_time = pd.Timestamp.now() - start_time

print(f"Backtesting time using CPU: {elapsed_time}")
Training time using CPU: 0 days 00:00:44.323256
Prediction time using CPU: 0 days 00:00:00.143112
  0%|          | 0/100 [00:00<?, ?it/s]
Backtesting time using CPU: 0 days 00:00:48.289869

LightGBM

# Suppress warnings
# ==============================================================================
warnings.filterwarnings(
    "ignore",
    message="'force_all_finite' was renamed to 'ensure_all_finite' in 1.6 and will be removed in 1.8.",
    category=FutureWarning,
    module="sklearn.utils.deprecation"
)

Si se está utilizando Google Colab, ejecute lo siguiente en una celda del notebook para asegurarse de que LightGBM pueda utilizar la GPU NVIDIA al ejecutarse en Google Colab.

!mkdir -p /etc/OpenCL/vendors && echo "libnvidia-opencl.so.1" > /etc/OpenCL/vendors/nvidia.icd
# Crear y entrenar un forecaster con un LGBMRegressor usando GPU
# ==============================================================================
forecaster = ForecasterRecursive(
                 regressor = LGBMRegressor(n_estimators=1000, device='gpu', verbose=-1),
                 lags      = 50
             )

start_time = pd.Timestamp.now()
forecaster.fit(y=data)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Training time using GPU: {elapsed_time}")

# Predict
# ==============================================================================
start_time = pd.Timestamp.now()
forecaster.predict(steps=100)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Prediction time using GPU: {elapsed_time}")

# Backtesting
# ==============================================================================
start_time = pd.Timestamp.now()
_ = backtesting_forecaster(
        forecaster = forecaster,
        y          = data,
        cv         = cv,
        metric     = 'mean_absolute_error'

    )
elapsed_time = pd.Timestamp.now() - start_time

print(f"Backtesting time using GPU: {elapsed_time}")
Training time using GPU: 0 days 00:00:21.657198
Prediction time using GPU: 0 days 00:00:00.059898
  0%|          | 0/100 [00:00<?, ?it/s]
Backtesting time using GPU: 0 days 00:00:24.554291
# Crear y entrenar un forecaster con un LGBMRegressor usando CPU
# ==============================================================================
forecaster = ForecasterRecursive(
                 regressor = LGBMRegressor(n_estimators=1000, device='cpu', verbose=-1),
                 lags      = 50
             )

start_time = pd.Timestamp.now()
forecaster.fit(y=data)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Training time using CPU: {elapsed_time}")

# Predict
# ==============================================================================
start_time = pd.Timestamp.now()
forecaster.predict(steps=100)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Prediction time using CPU: {elapsed_time}")

# Backtesting
# ==============================================================================
start_time = pd.Timestamp.now()
_ = backtesting_forecaster(
        forecaster = forecaster,
        y          = data,
        cv         = cv,
        metric     = 'mean_absolute_error'

    )
elapsed_time = pd.Timestamp.now() - start_time

print(f"Backtesting time using CPU: {elapsed_time}")
Training time using CPU: 0 days 00:00:27.196106
Prediction time using CPU: 0 days 00:00:00.044868
  0%|          | 0/100 [00:00<?, ?it/s]
Backtesting time using CPU: 0 days 00:00:25.313712

CatBoost

# Crear y entrenar un forecaster con un CatBoostRegressor usando GPU
# ==============================================================================
forecaster = ForecasterRecursive(
                 regressor = CatBoostRegressor(n_estimators=1000, task_type='GPU', silent=True, allow_writing_files=False),
                 lags      = 50
             )

start_time = pd.Timestamp.now()
forecaster.fit(y=data)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Training time using GPU: {elapsed_time}")

# Predict
# ==============================================================================
start_time = pd.Timestamp.now()
forecaster.predict(steps=100)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Prediction time using GPU: {elapsed_time}")

# Backtesting
# ==============================================================================
start_time = pd.Timestamp.now()
_ = backtesting_forecaster(
        forecaster = forecaster,
        y          = data,
        cv         = cv,
        metric     = 'mean_absolute_error'

    )
elapsed_time = pd.Timestamp.now() - start_time

print(f"Backtesting time using GPU: {elapsed_time}")
Training time using GPU: 0 days 00:00:26.810713
Prediction time using GPU: 0 days 00:00:00.109821
  0%|          | 0/100 [00:00<?, ?it/s]
Backtesting time using GPU: 0 days 00:00:30.199580
# Crear y entrenar un forecaster con un CatBoostRegressor usando CPU
# ==============================================================================
forecaster = ForecasterRecursive(
                 regressor = CatBoostRegressor(n_estimators=1000, task_type='CPU', silent=True, allow_writing_files=False),
                 lags      = 50
             )

start_time = pd.Timestamp.now()
forecaster.fit(y=data)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Training time using CPU: {elapsed_time}")

# Predict
# ==============================================================================
start_time = pd.Timestamp.now()
forecaster.predict(steps=100)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Prediction time using CPU: {elapsed_time}")

# Backtesting
# ==============================================================================
start_time = pd.Timestamp.now()
_ = backtesting_forecaster(
        forecaster = forecaster,
        y          = data,
        cv         = cv,
        metric     = 'mean_absolute_error'

    )
elapsed_time = pd.Timestamp.now() - start_time

print(f"Backtesting time using CPU: {elapsed_time}")
Training time using CPU: 0 days 00:01:13.747194
Prediction time using CPU: 0 days 00:00:00.101679
  0%|          | 0/100 [00:00<?, ?it/s]
Backtesting time using CPU: 0 days 00:01:06.052743

RAPIDS cuML

cuML es una librería para ejecutar algoritmos de machine learning en GPUs con una API que sigue de cerca la API de scikit-learn. Para usar cuML con skforecast, necesitas instalar la librería RAPIDS cuML. El proceso de instalación puede variar dependiendo de tu entorno y la versión de CUDA que tengas instalada. Puedes encontrar instrucciones detalladas de instalación en la documentación de RAPIDS.

# Crear y entrenar un forecaster con un RandomForestRegressor usando GPU
# ==============================================================================
forecaster = ForecasterRecursive(
                regressor = cuml.ensemble.RandomForestRegressor(
                                n_estimators=200,
                                max_depth=5,
                            ),
                lags = 20
             )

start_time = pd.Timestamp.now()
forecaster.fit(y=data)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Training time using GPU: {elapsed_time}")

# Predict
# ==============================================================================
start_time = pd.Timestamp.now()
forecaster.predict(steps=100)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Prediction time using GPU: {elapsed_time}")

# Backtesting
# ==============================================================================
cv = TimeSeriesFold(
         steps              = 100,
         initial_train_size = 90_000,
         refit              = False,
         verbose            = False
     )
start_time = pd.Timestamp.now()
_ = backtesting_forecaster(
        forecaster = forecaster,
        y          = data,
        cv         = cv,
        metric     = 'mean_absolute_error'

    )
elapsed_time = pd.Timestamp.now() - start_time

print(f"Backtesting time using GPU: {elapsed_time}")
# Crear y entrenar un forecaster con un RandomForestRegressor usando CPU
# ==============================================================================
forecaster = ForecasterRecursive(
                RandomForestRegressor(n_estimators=200, max_depth=5),
                lags = 20
             )

start_time = pd.Timestamp.now()
forecaster.fit(y=data)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Training time using CPU: {elapsed_time}")

# Predict
# ==============================================================================
start_time = pd.Timestamp.now()
forecaster.predict(steps=100)
elapsed_time = pd.Timestamp.now() - start_time

print(f"Prediction time using CPU: {elapsed_time}")

# Backtesting
# ==============================================================================
cv = TimeSeriesFold(
         steps              = 100,
         initial_train_size = 90_000,
         refit              = False,
         verbose            = False
     )
start_time = pd.Timestamp.now()
_ = backtesting_forecaster(
        forecaster = forecaster,
        y          = data,
        cv         = cv,
        metric     = 'mean_absolute_error'

    )
elapsed_time = pd.Timestamp.now() - start_time

print(f"Backtesting time using CPU: {elapsed_time}")

Información de sesión

import session_info
session_info.show(html=False)

Instrucciones para citar

¿Cómo citar este documento?

Si utilizas este documento o alguna parte de él, te agradecemos que lo cites. ¡Muchas gracias!

Acelerar modelos de forecasting con GPU por Joaquín Amat Rodrigo y Javier Escobar Ortiz, disponible bajo una licencia Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0 DEED) en https://cienciadedatos.net/documentos/py65-acelerar-models-forecasting-gpu.html

¿Cómo citar skforecast?

Si utilizas skforecast, te agradeceríamos mucho que lo cites. ¡Muchas gracias!

Zenodo:

Amat Rodrigo, Joaquin, & Escobar Ortiz, Javier. (2024). skforecast (v0.16.0). Zenodo. https://doi.org/10.5281/zenodo.8382788

APA:

Amat Rodrigo, J., & Escobar Ortiz, J. (2024). skforecast (Version 0.16.0) [Computer software]. https://doi.org/10.5281/zenodo.8382788

BibTeX:

@software{skforecast, author = {Amat Rodrigo, Joaquin and Escobar Ortiz, Javier}, title = {skforecast}, version = {0.16.0}, month = {03}, year = {2025}, license = {BSD-3-Clause}, url = {https://skforecast.org/}, doi = {10.5281/zenodo.8382788} }

¿Te ha gustado el artículo? Tu ayuda es importante

Tu contribución me ayudará a seguir generando contenido divulgativo gratuito. ¡Muchísimas gracias! 😊

Become a GitHub Sponsor Become a GitHub Sponsor

Creative Commons Licence

Este documento creado por Joaquín Amat Rodrigo y Javier Escobar Ortiz tiene licencia Attribution-NonCommercial-ShareAlike 4.0 International.

Se permite:

  • Compartir: copiar y redistribuir el material en cualquier medio o formato.

  • Adaptar: remezclar, transformar y crear a partir del material.

Bajo los siguientes términos:

  • Atribución: Debes otorgar el crédito adecuado, proporcionar un enlace a la licencia e indicar si se realizaron cambios. Puedes hacerlo de cualquier manera razonable, pero no de una forma que sugiera que el licenciante te respalda o respalda tu uso.

  • No-Comercial: No puedes utilizar el material para fines comerciales.

  • Compartir-Igual: Si remezclas, transformas o creas a partir del material, debes distribuir tus contribuciones bajo la misma licencia que el original.