Nixtla / mlforecast

Scalable machine 🤖 learning for time series forecasting.
https://nixtlaverse.nixtla.io/mlforecast
Apache License 2.0
789 stars 74 forks source link

SHAP with exogenous features #342

Closed kkckk1110 closed 1 month ago

kkckk1110 commented 1 month ago

What happened + What you expected to happen

Hello! I hope to use shap to interpret my model, but I came across the following issue.

File ~/miniforge3/lib/python3.9/site-packages/mlforecast/forecast.py:689, in MLForecast.predict(self, h, before_predict_callback, after_predict_callback, new_df, level, Xdf, ids) 686 else: 687 ts = self.ts --> 689 forecasts = ts.predict( 690 models=self.models, 691 horizon=h, 692 before_predict_callback=before_predict_callback, 693 after_predict_callback=after_predict_callback, 694 X_df=X_df, 695 ids=ids, 696 ) 697 if level is not None: 698 if self._cs_df is None:

File ~/miniforge3/lib/python3.9/site-packages/mlforecast/core.py:733, in TimeSeries.predict(self, models, horizon, before_predict_callback, after_predict_callback, X_df, ids) 731 try: 732 if getattr(self, "max_horizon", None) is None: --> 733 preds = self._predict_recursive( 734 models=models, 735 horizon=horizon, 736 before_predict_callback=before_predict_callback, 737 after_predict_callback=after_predict_callback, 738 X_df=X_df, 739 ) 740 else: 741 preds = self._predict_multi( 742 models=models, 743 horizon=horizon, 744 before_predict_callback=before_predict_callback, 745 X_df=X_df, 746 )

File ~/miniforge3/lib/python3.9/site-packages/mlforecast/core.py:606, in TimeSeries._predict_recursive(self, models, horizon, before_predict_callback, after_predict_callback, X_df) 604 for i, (name, model) in enumerate(models.items()): 605 self._predictsetup() --> 606 for in range(horizon): 607 new_x = self._get_features_for_next_step(X_df) 608 if before_predict_callback is not None:

TypeError: 'DataFrame' object cannot be interpreted as an integer

Versions / Dependencies

MACOS

Reproduction script

model = MLForecast(models=models,freq='MS',lags=[1,12]) model.fit(train, id_col='unique_id', time_col='ds', target_col='sales', static_features=[],fitted=True)

import shap X = train.drop(columns=['unique_id', 'ds', 'sales']) X100 = shap.utils.sample(X, 100) explainer = shap.Explainer(model.predict, X100) shap_values = explainer(X, max_evals=600)

Issue Severity

High: It blocks me from completing my task.

jmoralez commented 1 month ago

Have you read this guide?

kkckk1110 commented 1 month ago

Yes, and the codes are exactly following the guide

jmoralez commented 1 month ago

That passes the linear regression model to the explainer, you're passing the MLForecast object.

kkckk1110 commented 1 month ago

Many thanks to your kind replies!