Más sobre forecasting en: cienciadedatos.net


Introducción

La interpretabilidad de los modelos predictivos, también conocida como explicabilidad, se refiere a la capacidad de entender, interpretar y explicar las decisiones o predicciones tomadas por los modelos de una forma comprensible para el ser humano. Su objetivo es comprender cómo un modelo llega a un determinado resultado o decisión.

Debido a la naturaleza compleja de muchos modelos modernos de machine learning, como los métodos ensemble, que a menudo funcionan como cajas negras, es difícil comprender por qué se ha hecho una predicción concreta. Las técnicas de explicabilidad pretenden desmitificar estos modelos, proporcionando información sobre su funcionamiento interno y ayudando a generar confianza, a mejorar la transparencia y a cumplir los requisitos normativos en diversos ámbitos. Mejorar la explicabilidad de los modelos no solo ayuda a comprender su comportamiento, sino también a identificar sesgos, a mejorar el rendimiento de los modelos y a permitir que las partes interesadas tomen decisiones más informadas basadas en los conocimientos del aprendizaje automático.

La librería skforecast es compatible con algunos de los métodos de interpretabilidad más utilizados: valores SHAP, gráficos de dependencia parcial y métodos específicos de los modelos.

Librerías

Librerías utilizadas en este documento.

# Manipulación de datos
# ==============================================================================
import pandas as pd
import numpy as np
from skforecast.datasets import fetch_dataset

# Gráficos
# ==============================================================================
import matplotlib.pyplot as plt
import shap
from skforecast.plot import set_dark_theme

# Modelado y forecasting
# ==============================================================================
import sklearn
import lightgbm
import skforecast
from sklearn.inspection import PartialDependenceDisplay
from lightgbm import LGBMRegressor
from skforecast.recursive import ForecasterRecursive
from skforecast.preprocessing import RollingFeatures
from skforecast.model_selection import backtesting_forecaster, TimeSeriesFold

color = '\033[1m\033[38;5;208m'
print(f"{color}Versión skforecast: {skforecast.__version__}")
print(f"{color}Versión scikit-learn: {sklearn.__version__}")
print(f"{color}Versión lightgbm: {lightgbm.__version__}")
print(f"{color}Versión shap: {shap.__version__}")
Versión skforecast: 0.25.0
Versión scikit-learn: 1.7.2
Versión lightgbm: 4.7.0
Versión shap: 0.52.0

Datos

# Descarga de los datos
# ==============================================================================
data = fetch_dataset(name="vic_electricity")
data.head(3)
╭──────────────────────────── vic_electricity ─────────────────────────────╮
│ Description:                                                             │
│ Half-hourly electricity demand for Victoria, Australia                   │
│                                                                          │
│ Source:                                                                  │
│ O'Hara-Wild M, Hyndman R, Wang E, Godahewa R (2022).tsibbledata: Diverse │
│ Datasets for 'tsibble'. https://tsibbledata.tidyverts.org/,              │
│ https://github.com/tidyverts/tsibbledata/.                               │
│ https://tsibbledata.tidyverts.org/reference/vic_elec.html                │
│                                                                          │
│ URL:                                                                     │
│ https://raw.githubusercontent.com/skforecast/skforecast-                 │
│ datasets/main/data/vic_electricity.csv                                   │
│                                                                          │
│ Shape: 52608 rows x 4 columns                                            │
╰──────────────────────────────────────────────────────────────────────────╯
Demand Temperature Date Holiday
Time
2011-12-31 13:00:00 4382.825174 21.40 2012-01-01 True
2011-12-31 13:30:00 4263.365526 21.05 2012-01-01 True
2011-12-31 14:00:00 4048.966046 20.70 2012-01-01 True
# Agregación a frecuencia diaria
# ==============================================================================
data = data.resample('D').agg({'Demand': 'sum', 'Temperature': 'mean'})
data.head(3)
Demand Temperature
Time
2011-12-31 82531.745918 21.047727
2012-01-01 227778.257304 26.578125
2012-01-02 275490.988882 31.751042
# Crear variables de calendario
# ==============================================================================
data['day_of_week'] = data.index.dayofweek
data['month'] = data.index.month
data.head(3)
Demand Temperature day_of_week month
Time
2011-12-31 82531.745918 21.047727 5 12
2012-01-01 227778.257304 26.578125 6 1
2012-01-02 275490.988882 31.751042 0 1
# División train-test
# ==============================================================================
end_train = '2014-12-01 23:59:00'
data_train = data.loc[: end_train, :]
data_test  = data.loc[end_train:, :]
print(f"Fechas train : {data_train.index.min()} --- {data_train.index.max()}  (n={len(data_train)})")
print(f"Fechas test  : {data_test.index.min()} --- {data_test.index.max()}  (n={len(data_test)})")
Fechas train : 2011-12-31 00:00:00 --- 2014-12-01 00:00:00  (n=1067)
Fechas test  : 2014-12-02 00:00:00 --- 2014-12-31 00:00:00  (n=30)

Modelos de forecasting

Se creará un modelo de forecasting para predecir la demanda de energía utilizando los últimos 7 valores (última semana), una media móvil de los últimos 24 días como variable de ventana (window feature), y la temperatura junto con dos variables de calendario (día de la semana y mes) como variables exógenas.

# Crear un forecaster recursivo de múltiples pasos (ForecasterRecursive)
# ==============================================================================
window_features = RollingFeatures(stats=['mean'], window_sizes=24)
exog_features = ['Temperature', 'day_of_week', 'month']
forecaster = ForecasterRecursive(
                 estimator       = LGBMRegressor(random_state=123, verbose=-1),
                 lags            = 7,
                 window_features = window_features
             )

forecaster.fit(
    y    = data_train['Demand'],
    exog = data_train[exog_features],
)
forecaster

ForecasterRecursive

General Information
  • Estimator: LGBMRegressor
  • Lags: [1 2 3 4 5 6 7]
  • Window features: ['roll_mean_24']
  • Calendar features: None
  • Window size: 24
  • Series name: Demand
  • Exogenous included: True
  • Categorical features: auto
  • Weight function included: False
  • Differentiation order: None
  • Drop NaN from series: False
  • Creation date: 2026-09-24 13:22:04
  • Last fit date: 2026-09-24 13:22:09
  • Skforecast version: 0.25.0
  • Python version: 3.13.14
  • Forecaster id: None
Exogenous Variables

Temperature, day_of_week, month

Data Transformations
  • Transformer for y: None
  • Transformer for exog: None
Training Information
  • Training range: [Timestamp('2011-12-31 00:00:00'), Timestamp('2014-12-01 00:00:00')]
  • Training index type: DatetimeIndex
  • Training index frequency: D
Estimator Parameters
    {'boosting_type': 'gbdt', 'class_weight': None, 'colsample_bytree': 1.0, 'importance_type': 'split', 'learning_rate': 0.1, 'max_depth': -1, 'min_child_samples': 20, 'min_child_weight': 0.001, 'min_split_gain': 0.0, 'n_estimators': 100, 'n_jobs': None, 'num_leaves': 31, 'objective': None, 'random_state': 123, 'reg_alpha': 0.0, 'reg_lambda': 0.0, 'subsample': 1.0, 'subsample_for_bin': 200000, 'subsample_freq': 0, 'verbose': -1}
Fit Kwargs
    {}

📖 API Reference    📝 User Guide

Importancia de predictores específica de los modelos

La importancia de los predictores en modelos de machine learning determina la relevancia de cada predictor (o variable) en la predicción de un modelo. En otras palabras, mide cuánto contribuye cada predictor al resultado del modelo.

La importancia de los predictores puede utilizarse para varios fines, como identificar aquellos más relevantes para una predicción determinada, comprender el comportamiento de un modelo y seleccionar el mejor conjunto de predictores para una tarea determinada. También puede ayudar a identificar posibles sesgos o errores en los datos utilizados para entrenar el modelo. Es importante señalar que la importancia de un predictor no es una medida definitiva de causalidad. El hecho de que una característica se identifique como importante no significa necesariamente que haya causado el resultado. También pueden intervenir otros factores, como las variables de confusión.

El método utilizado para calcular la importancia de los predictores puede variar en función del tipo de modelo de machine learning que se utilice. Los distintos modelos pueden tener distintos supuestos y características que afecten al cálculo de la importancia. Por ejemplo, los modelos basados en árboles de decisión, como Random Forest y Gradient Boosting, suelen utilizar métodos que miden la disminución de impurezas o el impacto de las permutaciones. Los modelos de regresión lineal suelen utilizar los coeficientes. La magnitud del coeficiente refleja la magnitud y la dirección de la relación entre el predictor y la variable objetivo.

La importancia de los predictores incluidos en un forecaster se puede obtener utilizando el método get_feature_importances(). Este método accede a los atributos coef_ y feature_importances_ del regresor interno.

⚠ Warning

El método `get_feature_importances()` solo devolverá valores si el regresor del forecaster tiene el atributo `coef_` o `feature_importances_`, que es el nombre por defecto en scikit-learn.
# Extraer importancia de los predictores
# ==============================================================================
importance = forecaster.get_feature_importances()
importance
feature importance
8 Temperature 568
0 lag_1 426
1 lag_2 291
6 lag_7 248
4 lag_5 243
2 lag_3 236
7 roll_mean_24 227
10 month 224
5 lag_6 200
3 lag_4 177
9 day_of_week 160

De acuerdo con este ranking, Temperature es el predictor más relevante, seguido de lag_1 y lag_2. Estos valores deben interpretarse con cautela: en LGBMRegressor, el atributo feature_importances_ cuenta por defecto el número de veces que un predictor se utiliza para dividir los datos (importance_type='split'), no la mejora que esas divisiones producen. Un predictor puede participar en muchas divisiones con poco efecto, o en unas pocas muy influyentes. Especificar importance_type='gain' al crear el modelo, o utilizar los valores SHAP que se presentan en la siguiente sección, suele ofrecer una imagen más fiel de la contribución real de cada predictor.

Valores SHAP (SHapley Additive exPlanations)

SHAP (SHapley Additive exPlanations) es un método ampliamente adoptado para explicar modelos de machine learning. Proporciona tanto información visual como cuantitativa sobre cómo las variables predictoras influyen en el modelo. Los valores SHAP cumplen dos propósitos principales:

  • Interpretabilidad global: Los valores SHAP permiten cuantificar cómo influye cada variable en el modelo durante su entrenamiento. Al promediar los valores SHAP en todo el conjunto de datos, se pueden ordenar las variables según su importancia general y obtener una visión del proceso de toma de decisiones del modelo.

  • Interpretabilidad local: Los valores SHAP también explican predicciones individuales indicando cuánto contribuye cada variable a una salida específica. Esto permite desglosar predicciones individuales para entender el papel que desempeñó cada variable en el resultado.

Se pueden generar explicaciones con valores SHAP para modelos de skforecast utilizando dos componentes:

  • El regresor interno del forecaster, accesible mediante forecaster.estimator.

  • Las matrices internas utilizadas para el ajuste, backtesting y predicción del modelo. Estas matrices son accesibles a través del método create_predict_X() y estableciendo el argumento return_predictors=True en la función backtesting_forecaster().

Al aprovechar estos elementos, los usuarios pueden generar explicaciones claras e interpretables para sus modelos de forecasting. Estas explicaciones pueden utilizarse para evaluar la fiabilidad del modelo, identificar las variables más influyentes y comprender su impacto en las predicciones.

⚠ Warning

Los valores SHAP y los gráficos de dependencia parcial cuantifican la asociación entre los predictores y las predicciones del modelo, no miden causalidad. Además, al perturbar o combinar valores de los predictores, estos métodos pueden generar escenarios poco realistas en datos autocorrelacionados como las series temporales: los lags están fuertemente correlacionados entre sí (por ejemplo, es improbable que un valor muy alto de lag_1 coincida con un valor muy bajo de roll_mean_24). Las explicaciones deben interpretarse, por tanto, como una descripción de cómo el modelo utiliza los predictores, no como propiedades del proceso subyacente.

Shap: importancia global de los predictores

Al promediar los valores SHAP en el conjunto de datos utilizado para entrenar el modelo, es posible obtener una estimación de la contribución (tanto en magnitud como en dirección) de cada predictor en el modelo. Cuanto mayor sea el valor absoluto del valor SHAP, mayor será su importancia. El signo del valor SHAP indica si la característica tiene un impacto positivo o negativo en la predicción.

Primero, se crean las matrices de entrenamiento utilizadas para ajustar el modelo con el método create_train_X_y().

# Matrices de entrenamiento usadas por el forecaster para ajustar el regresor interno
# ==============================================================================
X_train, y_train = forecaster.create_train_X_y(
                       y    = data_train['Demand'],
                       exog = data_train[exog_features],
                   )

display(X_train.head(3))
lag_1 lag_2 lag_3 lag_4 lag_5 lag_6 lag_7 roll_mean_24 Temperature day_of_week month
Time
2012-01-24 280188.298774 239810.374218 207949.859910 225035.325476 240187.677944 247722.494256 292458.685446 222658.202570 26.611458 1 1
2012-01-25 287474.816646 280188.298774 239810.374218 207949.859910 225035.325476 240187.677944 247722.494256 231197.497184 19.759375 2 1
2012-01-26 239083.684380 287474.816646 280188.298774 239810.374218 207949.859910 225035.325476 240187.677944 231668.556646 20.038542 3 1

✎ Note

Aunque los datos comienzan el 2011-12-31, la matriz de entrenamiento empieza el 2012-01-24. Esto se debe a que el forecaster incluye una media móvil de 24 días (roll_mean_24), por lo que su tamaño de ventana es 24: las primeras 24 observaciones de la serie se necesitan para calcular los predictores de la primera fila de entrenamiento, por lo que aparecen como predictores pero no como valores de la variable respuesta. Por ello, X_train e y_train contienen 24 filas menos que la serie de entrenamiento original.

A continuación, se calculan los valores SHAP con la librería shap. Al llamar al explainer con los datos de entrenamiento se obtiene un objeto Explanation que almacena los valores SHAP. Si el conjunto de datos es grande, se recomienda utilizar solo una muestra aleatoria.

# Crear un objeto explainer de SHAP (para modelos basados en árboles)
# ==============================================================================
explainer = shap.TreeExplainer(forecaster.estimator)

# Muestreo del 50% de los datos para acelerar el cálculo
rng = np.random.default_rng(seed=785412)
sample = rng.choice(X_train.index, size=int(len(X_train)*0.5), replace=False)
X_train_sample = X_train.loc[sample, :]
y_train_sample = y_train.loc[sample]
explanation = explainer(X=X_train_sample, y=y_train_sample)
shap_values = explanation.values

✎ Note

La librería SHAP tiene varios explainers, cada uno diseñado para un tipo de modelo diferente. El explainer shap.TreeExplainer se utiliza para modelos basados en árboles, como el LGBMRegressor utilizado en este ejemplo. Para obtener más información, consulte la documentación de SHAP.

Una vez calculados los valores SHAP, se pueden generar varios gráficos para visualizar los resultados.

SHAP Summary Plot

El SHAP summary plot muestra la contribución de cada variable a la predicción del modelo en para varias observaciones. Muestra cuánto contribuye cada variable a alejar la predicción del modelo de un valor base (a menudo la predicción media del modelo). Al examinar un SHAP summary plot, se pueden obtener información sobre qué variables tienen un impacto más significativo en las predicciones, si influyen positiva o negativamente en el resultado y cómo contribuyen los diferentes valores de las variables a predicciones específicas.

# Shap summary plot (top 10)
# ==============================================================================
shap.initjs()
shap.summary_plot(shap_values, X_train_sample, max_display=10, show=False)
fig, ax = plt.gcf(), plt.gca()
ax.set_title('SHAP summary plot')
ax.tick_params(labelsize=8)
fig.set_size_inches(6, 3)

En este gráfico, cada punto representa una observación de la muestra de entrenamiento. Su posición en el eje horizontal es su valor SHAP (impacto en la predicción) y su color indica si el valor del predictor es alto (rosa) o bajo (azul) en esa observación. Se observan varios patrones:

  • Valores altos de lag_1 (demanda del día anterior) empujan la predicción hacia arriba y valores bajos la empujan hacia abajo: la demanda es muy persistente de un día para otro.

  • Valores altos de day_of_week (fin de semana) reducen la demanda predicha, en línea con el menor consumo eléctrico de sábados y domingos.

  • Temperature muestra valores SHAP muy positivos en sus valores más altos (demanda de refrigeración), mientras que los valores intermedios tienen un impacto negativo.

# Shap summary plot (bar)
# ==============================================================================
shap.summary_plot(shap_values, X_train_sample, plot_type='bar', plot_size=(6, 3))

El gráfico de barras resume el valor SHAP absoluto medio de cada predictor: lag_1, day_of_week y Temperature dominan la salida del modelo. Merece la pena comparar este ranking con el devuelto por get_feature_importances(): day_of_week es el último según el número de divisiones, pero el segundo según SHAP. Esto significa que el modelo utiliza este predictor en relativamente pocas divisiones, pero esas divisiones modifican considerablemente las predicciones. Cuando ambos rankings difieren, los valores SHAP (o la ganancia de las divisiones) suelen ser una medida más fiable de la influencia real de cada predictor.

Gráfico de dependencia SHAP

Los gráficos de dependencia SHAP son visualizaciones utilizadas para entender la relación entre una variable y la salida del modelo. Para ello muestran cómo el valor de una única variable afecta a las predicciones realizadas por el modelo teniendo en cuenta las interacciones con otras variables. Estos gráficos son especialmente útiles para examinar cómo una determinada variable afecta a las predicciones del modelo en todo su rango de valores.

# Gráfico de dependencia para la variable Temperature
# ==============================================================================
fig, ax = plt.subplots(figsize=(6, 3))
scatter = shap.plots.scatter(explanation[:, "Temperature"], show=False, ax=ax)
ax.set_title("Temperature dependence plot")
ax.set_ylabel("SHAP value for the 'Temperature' feature");

El gráfico de dependencia revela una clara relación en forma de U: la demanda aumenta con temperaturas bajas (calefacción) y, de forma más acusada, con temperaturas altas (aire acondicionado), con su mínimo en el rango templado de unos 15-20 grados Celsius, donde la contribución de Temperature a la predicción es negativa. Capturar este tipo de relaciones no lineales es una de las principales ventajas de los modelos basados en árboles frente a los modelos lineales.

SHAP: explicación de predicciones individuales

Los valores SHAP no solo permiten interpretar el comportamiento general del modelo (Interpretabilidad Global), sino que también sirven para analizar predicciones individuales (Interpretabilidad Local). Esto resulta especialmente útil cuando se desea entender por qué el modelo realizó una predicción específica para un caso concreto.

Para llevar a cabo este análisis, es necesario acceder a los valores de los predictores (lags y variables exógenas) en el momento de la predicción. Esto se puede lograr utilizando el método create_predict_X o activando el argumento return_predictors=True en la función backtesting_forecaster.

SHAP values para los resultados de predict()

Supongamos que el modelo de pronóstico se utiliza para predecir los próximos 30 valores de la serie, y se desea explicar una predicción específica correspondiente a la fecha '2014-12-28'.

# Forecasting de los próximos 30 días
# ==============================================================================
set_dark_theme()
predictions = forecaster.predict(steps=30, exog=data_test[exog_features])
fig, ax = plt.subplots(figsize=(6, 2.5))
data_test['Demand'].plot(ax=ax, label='Test')
predictions.plot(ax=ax, label='Predictions', linestyle='--')
ax.set_xlabel(None)
ax.legend();

El método create_predict_X se utiliza para crear la matriz de entrada que el método predict usa internamente. Esta matriz se emplea posteriormente para generar los valores SHAP correspondientes a los valores predichos.

# Crear la matriz de entrada utilizada para predecir los próximos 30 días
# ==============================================================================
X_predict = forecaster.create_predict_X(steps=30, exog=data_test[exog_features])
X_predict.head(3)
lag_1 lag_2 lag_3 lag_4 lag_5 lag_6 lag_7 roll_mean_24 Temperature day_of_week month
2014-12-02 237812.592388 234970.336660 189653.758108 202017.012448 214602.854760 218321.456402 214318.765210 211369.709659 19.833333 1 12
2014-12-03 230878.900870 237812.592388 234970.336660 189653.758108 202017.012448 214602.854760 218321.456402 212777.981610 19.616667 2 12
2014-12-04 230782.656189 230878.900870 237812.592388 234970.336660 189653.758108 202017.012448 214602.854760 214485.198829 21.702083 3 12
# Valores SHAP para las predicciones
# ==============================================================================
explanation_predict = explainer(X_predict)
# Waterfall plot para una única predicción
# ==============================================================================
predicted_date = '2014-12-28'
iloc_predicted_date = X_predict.index.get_loc(predicted_date)
shap.plots.waterfall(explanation_predict[iloc_predicted_date], show=False)
fig = plt.gcf()
ax = fig.axes[0]
fig.set_size_inches(6, 3.5)
ax.tick_params(labelsize=10)
plt.show()

El gráfico waterfall (cascada) muestra cómo los diferentes predictores influenciaron la predicción del modelo hacia arriba (en rojo) o hacia abajo (en azul), en relación con la predicción promedio del modelo.

  • lag_1 tuvo el mayor impacto negativo, reduciendo la predicción en más de 22,000 unidades.

  • Temperature contribuyó de forma positiva, aumentando la predicción en aproximadamente 7,685 unidades.

  • Otros predictores como day_of_week, month y varios valores de lag también influyeron en la predicción, aunque en menor medida.

La predicción del modelo (f(x)) fue de 200,849.86, mientras que el valor esperado (E[f(x)]), el promedio de las salidas del modelo sobre los datos de entrenamiento utilizados como referencia, es de 224,358.59. Esto significa que los valores específicos de entrada para esta predicción llevaron al modelo a prever un valor inferior al promedio, debido principalmente al fuerte impacto negativo de lag_1.

Las mismas conclusiones se pueden obtener utilizando la función shap.force_plot.

# Force plot para una única predicción
# ==============================================================================
shap.force_plot(
    base_value  = explainer.expected_value,
    shap_values = explanation_predict.values[iloc_predicted_date],
    features    = X_predict.iloc[iloc_predicted_date, :]
)
Visualization omitted, Javascript library not loaded!
Have you run `initjs()` in this notebook? If this notebook was from another user you must also trust this notebook (File -> Trust notebook). If you are viewing this notebook on github the Javascript has been stripped for security. If you are using JupyterLab this error is because a JupyterLab extension has not yet been written.
# Force plot para las 30 predicciones
# ==============================================================================
shap.force_plot(
    base_value  = explainer.expected_value,
    shap_values = explanation_predict.values,
    features    = X_predict
)
Visualization omitted, Javascript library not loaded!
Have you run `initjs()` in this notebook? If this notebook was from another user you must also trust this notebook (File -> Trust notebook). If you are viewing this notebook on github the Javascript has been stripped for security. If you are using JupyterLab this error is because a JupyterLab extension has not yet been written.

El force plot muestra la misma información que el gráfico waterfall, pero condensada en una barra horizontal: los predictores que empujan la predicción por encima del valor base aparecen en rojo y los que la empujan por debajo, en azul. En la versión que combina las 30 predicciones, cada corte vertical corresponde a una fecha (los gráficos individuales se rotan 90 grados y se apilan uno junto a otro). Esto facilita detectar periodos en los que los mismos predictores dirigen sistemáticamente las predicciones, como el patrón semanal introducido por day_of_week. El gráfico es interactivo: al pasar el cursor por cada región se muestra el predictor y su contribución.

SHAP values para los resultados de backtesting_forecaster()

El análisis de predicciones individuales usando valores SHAP también puede aplicarse a las predicciones realizadas durante un proceso de backtesting. Para ello, se debe establecer el argumento return_predictors=True en la función backtesting_forecaster. Esto devuelve un DataFrame con el valor predicho (pred), la partición a la que pertenece (fold) y los valores de los lags y las variables exógenas utilizados para cada predicción.

En este escenario, se emplea un proceso de backtesting para entrenar el modelo utilizando datos hasta '2014-12-01 23:59:00'. Luego, el modelo genera predicciones en folds de 24 días. Posteriormente, se calculan los valores SHAP para la predicción correspondiente a la fecha '2014-12-16'.

# Backtesting devolviendo los predictores
# ==============================================================================
cv = TimeSeriesFold(
         steps              = 24,
         initial_train_size = len(data.loc[:'2014-12-01 23:59:00'])
     )
_, predictions = backtesting_forecaster(
                        forecaster        = forecaster,
                        y                 = data['Demand'],
                        exog              = data[exog_features],
                        cv                = cv,
                        metric            = 'mean_absolute_error',
                        return_predictors = True,
                )
predictions.head(3)
fold pred lag_1 lag_2 lag_3 lag_4 lag_5 lag_6 lag_7 roll_mean_24 Temperature day_of_week month
2014-12-02 0 230878.900870 237812.592388 234970.336660 189653.758108 202017.012448 214602.854760 218321.456402 214318.765210 211369.709659 19.833333 1 12
2014-12-03 0 230782.656189 230878.900870 237812.592388 234970.336660 189653.758108 202017.012448 214602.854760 218321.456402 212777.981610 19.616667 2 12
2014-12-04 0 237992.220195 230782.656189 230878.900870 237812.592388 234970.336660 189653.758108 202017.012448 214602.854760 214485.198829 21.702083 3 12
# Waterfall para una predicción concreta generada en el backtesting
# ==============================================================================
predictions = predictions.astype(data[exog_features].dtypes)  # Asegurar mismos tipos
iloc_predicted_date = predictions.index.get_loc('2014-12-16')
explanation_backtesting = explainer(predictions.iloc[:, 2:])
shap.plots.waterfall(explanation_backtesting[iloc_predicted_date], show=False)
fig = plt.gcf()
ax = fig.axes[0]
fig.set_size_inches(6, 3.5)
ax.tick_params(labelsize=8)
plt.show()

Scikit-learn gráficos de dependencia parcial

Scikit-learn permite crear gráficos de dependencia parcial utilizando PartialDependenceDisplay.from_estimator. Esta función visualiza el efecto de una o dos variables en el resultado predicho, marginalizando el efecto de todas las demás características. Estos gráficos proporcionan información sobre cómo influyen las variables seleccionadas en las predicciones del modelo y pueden ayudar a identificar relaciones no lineales o interacciones entre variables.

Además de la curva promedio, el argumento kind='both' utilizado en la siguiente celda dibuja también las curvas ICE (Individual Conditional Expectation): una línea fina por observación que muestra cómo cambia su predicción al variar el valor del predictor, manteniendo fijo el resto. La curva de dependencia parcial es el promedio de todas las curvas ICE. Si las curvas ICE son aproximadamente paralelas, el predictor afecta a todas las observaciones de forma similar; si se cruzan o divergen, es señal de interacciones con otros predictores.

Una descripción más detallada sobre gráficos de dependencia parcial se puede encontrar en la Guía de Usuario de scikit-learn.

# Scikit-learn gráfico de dependencia parcial
# ==============================================================================
fig, ax = plt.subplots(figsize=(8, 3))
PartialDependenceDisplay.from_estimator(
    estimator = forecaster.estimator,
    X         = X_train,
    features  = ["Temperature", "lag_1"],
    kind      = 'both',
    ax        = ax,
)
ax.set_title("Partial Dependence Plot")
fig.tight_layout()
plt.show()

Información de sesión

import session_info
session_info.show(html=False)
-----
lightgbm            4.7.0
matplotlib          3.10.9
numpy               2.4.6
pandas              2.3.3
session_info        v1.0.1
shap                0.52.0
skforecast          0.25.0
sklearn             1.7.2
-----
IPython             9.15.0
jupyter_client      8.9.1
jupyter_core        5.9.1
-----
Python 3.13.14 | packaged by conda-forge | (main, Jun 12 2026, 09:44:26) [MSC v.1944 64 bit (AMD64)]
Windows-11-10.0.26200-SP0
-----
Session information updated at 2026-09-24 13:22

Instrucciones para citar

¿Cómo citar este documento?

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

Modelos de forecasting interpretables 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://www.cienciadedatos.net/documentos/py57-modelos-forecasting-interpretables.html

¿Cómo citar skforecast?

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

Zenodo:

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

APA:

Amat Rodrigo, J., & Escobar Ortiz, J. (2026). skforecast (Version 0.25.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.25.0}, month = {09}, year = {2026}, 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.