Contenido del curso

- XGBoost para Predicción de Demanda Energética

XGBoost para Predicción de Demanda Energética

La predicción precisa de la demanda energética es crucial para la estabilidad de la red, la optimización de costos y la integración de energías renovables. En esta lección, aplicamos XGBoost a este problema de regresión, abordando los desafíos de las series temporales y la estacionalidad. Aprenderás a preparar datos, entrenar modelos, ajustar hiperparámetros y analizar resultados.

Objetivo de la Lección: Dominar la aplicación de XGBoost para predecir demanda energética, desde la ingeniería de características hasta la optimización y evaluación del modelo.

1. Preparación de Datos: Ingeniería de Características

La clave para una buena predicción con XGBoost está en las características. Debemos transformar la serie temporal en un problema supervisado. Las características se agrupan en:

Características de Fecha y Hora:
  • Estacionalidad Diaria: Hora del día (0-23), minuto (0-59), período del día (mañana, tarde, noche).
  • Estacionalidad Semanal: Día de la semana (lunes=0, domingo=6), es fin de semana (0/1).
  • Estacionalidad Anual: Mes (1-12), día del año (1-366), estación del año (primavera, verano, otoño, invierno).
  • Características Cíclicas: Para horas y meses, usamos seno y coseno para preservar la naturaleza circular.
Características Climáticas y Contextuales:
  • Temperatura: Temperatura actual, máxima y mínima del día, y temperatura las últimas 24 horas.
  • Días Festivos: Indicador binario (1 si es festivo, 0 si no). También se puede incluir el tipo de festivo.
  • Retardos (Lags): Demanda de las últimas 24 horas (lag_1, lag_2, ..., lag_24). Capturan patrones recientes.
  • Medias Móviles: Promedio de demanda de las últimas 6, 12 y 24 horas para suavizar ruido.

# Ejemplo de creación de características en Python
import pandas as pd
import numpy as np

def create_features(df, target='demand'):
    df = df.copy()
    # Fecha y hora
    df['hour'] = df['datetime'].dt.hour
    df['dayofweek'] = df['datetime'].dt.dayofweek
    df['month'] = df['datetime'].dt.month
    df['dayofyear'] = df['datetime'].dt.dayofyear
    
    # Características cíclicas para hora
    df['hour_sin'] = np.sin(2 * np.pi * df['hour'] / 24)
    df['hour_cos'] = np.cos(2 * np.pi * df['hour'] / 24)
    
    # Retardos (24 horas previas)
    for lag in [1, 2, 3, 6, 12, 24]:
        df[f'lag_{lag}'] = df[target].shift(lag)
    
    # Medias móviles
    df['rolling_mean_6'] = df[target].rolling(window=6).mean()
    df['rolling_mean_24'] = df[target].rolling(window=24).mean()
    
    return df.dropna()
    

2. Entrenamiento del Modelo XGBoost

Con los datos preparados, dividimos en conjuntos de entrenamiento y prueba (respetando el orden temporal). Luego configuramos el modelo:

Configuración Inicial:
  • Objetivo: reg:squarederror (para regresión).
  • Número de Árboles: Comenzamos con 1000 para permitir un buen aprendizaje.
  • Tasa de Aprendizaje (learning_rate): 0.01 para evitar sobreajuste y permitir más iteraciones.
  • Profundidad Máxima (max_depth): 6, balanceando complejidad y generalización.
  • Submuestreo (subsample): 0.8, para mayor robustez.

import xgboost as xgb

# Dividir datos (cuidado: no mezclar aleatoriamente en series temporales)
train_size = int(len(df) * 0.8)
train, test = df.iloc[:train_size], df.iloc[train_size:]

X_train = train.drop('demand', axis=1)
y_train = train['demand']
X_test = test.drop('demand', axis=1)
y_test = test['demand']

# Crear modelo con parámetros base
model = xgb.XGBRegressor(
    objective='reg:squarederror',
    n_estimators=1000,
    learning_rate=0.01,
    max_depth=6,
    subsample=0.8,
    colsample_bytree=0.8,
    random_state=42
)

# Entrenar con early stopping
model.fit(
    X_train, y_train,
    eval_set=[(X_test, y_test)],
    early_stopping_rounds=50,
    verbose=False
)
    

3. Ajuste de Hiperparámetros mediante Validación Cruzada

Para optimizar el rendimiento, usamos validación cruzada especializada para series temporales (TimeSeriesSplit) y evaluamos diferentes combinaciones de hiperparámetros. Los parámetros más relevantes son:

Hiperparámetro Rango de Búsqueda Impacto
max_depth 3 - 10 Controla la complejidad del árbol. Valores altos pueden sobreajustar.
learning_rate 0.001 - 0.1 Controla la velocidad de aprendizaje. Valores bajos requieren más árboles.
n_estimators 500 - 2000 Número de árboles. Combinado con early stopping.
subsample 0.6 - 1.0 Fracción de muestras por árbol. Reduce sobreajuste.
colsample_bytree 0.6 - 1.0 Fracción de características por árbol. Añade aleatoriedad.
min_child_weight 1 - 10 Peso mínimo para dividir un nodo. Ayuda a regularizar.
Recomendación: Usa RandomizedSearchCV o Optuna para una búsqueda eficiente. Prioriza la reducción del error cuadrático medio (RMSE) como métrica de optimización.

from sklearn.model_selection import TimeSeriesSplit, RandomizedSearchCV

tscv = TimeSeriesSplit(n_splits=3)

param_grid = {
    'max_depth': [3, 5, 7, 10],
    'learning_rate': [0.001, 0.01, 0.05, 0.1],
    'subsample': [0.6, 0.8, 1.0],
    'colsample_bytree': [0.6, 0.8, 1.0],
    'min_child_weight': [1, 3, 5, 10]
}

xgb_model = xgb.XGBRegressor(objective='reg:squarederror', n_estimators=1000, random_state=42)

random_search = RandomizedSearchCV(
    xgb_model, param_grid, n_iter=50,
    cv=tscv, scoring='neg_root_mean_squared_error',
    random_state=42, n_jobs=-1
)

random_search.fit(X_train, y_train)
best_model = random_search.best_estimator_
    

4. Análisis de Importancia de Características

XGBoost ofrece tres métricas clave para entender qué variables influyen más en la predicción:

  • Gain (Ganancia): Mejora promedio en la función de pérdida cuando se usa una característica para dividir. Es la métrica más útil.
  • Cover (Cobertura): Número promedio de observaciones afectadas por las divisiones basadas en la característica.
  • Frequency (Frecuencia): Número de veces que la característica se usa para dividir.

import matplotlib.pyplot as plt

# Obtener importancia basada en 'gain'
importance = best_model.feature_importances_
feature_names = X_train.columns

# Crear DataFrame para visualización
feat_imp = pd.DataFrame({
    'feature': feature_names,
    'importance': importance
}).sort_values('importance', ascending=False).head(15)

plt.figure(figsize=(10, 6))
plt.barh(feat_imp['feature'], feat_imp['importance'])
plt.xlabel('Importancia (Gain)')
plt.title('Top 15 Características más Importantes')
plt.gca().invert_yaxis()
plt.show()
    
Resultados típicos: Los retardos de demanda (especialmente lag_1 y lag_2), la hora del día y la temperatura suelen ser las características más importantes. Los días festivos tienen menor impacto, pero son significativos en fechas señaladas.

5. Evaluación del Modelo

Compararemos el rendimiento de XGBoost frente a otros métodos comunes para predicción de series temporales:

Modelo RMSE (kWh) MAE (kWh) Timepo de Entrenamiento
Promedio Histórico 450.3 320.1 0.62 0.1 s
ARIMA 380.5 275.4 0.73 5.2 s
Random Forest 310.2 210.8 0.82 45.0 s
XGBoost (sin ajuste) 295.6 198.3 0.84 12.3 s
XGBoost (optimizado) 265.1 175.6 0.87 15.1 s
Conclusiones Clave:
  • XGBoost supera claramente al promedio histórico y ARIMA, capturando no linealidades.
  • El ajuste de hiperparámetros reduce el error en ~10% adicional.
  • XGBoost es más eficiente que Random Forest en tiempo de entrenamiento, especialmente con early stopping.
  • La inclusión de características temporales y climatológicas es fundamental para lograr estos resultados.

6. Mejores Prácticas y Consideraciones

Para llevar tu modelo a producción y obtener resultados confiables, considera:

  • Validación Temporal: Nunca uses validación cruzada aleatoria en series temporales. Siempre respeta el orden cronológico.
  • Feature Engineering Avanzado: Agrega características como temperatura aparente, humedad, o índices de precios de energía si están disponibles.
  • Monitoreo de Deriva: Los patrones de consumo cambian con el tiempo. Reentrena el modelo periódicamente con datos nuevos.
  • Interpretabilidad: Usa SHAP values para entender predicciones individuales, especialmente en casos atípicos.
  • Manejo de Festivos Móviles: Incluye características como "días antes/después de festivo" para capturar efectos de puentes.
Resumen Final:

XGBoost es una herramienta poderosa para la predicción de demanda energética. Su capacidad para manejar no linealidades, interacciones entre características y datos faltantes lo convierte en la opción preferida frente a modelos estadísticos clásicos. La clave del éxito reside en una buena ingeniería de características y un ajuste cuidadoso de hiperparámetros. Con la metodología presentada, estarás preparado para implementar modelos robustos y precisos en entornos reales.

Odisea Algorítmica | De la Regresión al Aprendizaje Profundo | Lección: XGBoost para Predicción Energética
Se aplica XGBoost a la predicción de demanda energética, un problema de regresión con series temporales y estacionalidad. Se preparan los datos: características de fecha, hora, temperatura y días festivos. Se entrena un modelo XGBoost y se ajustan hiperparámetros mediante validación cruzada. Se analiza la importancia de características y la capacidad predictiva frente a otros métodos.
Calificación
0 0

No hay comentarios por ahora.