oracle-ads 2.13.2__py3-none-any.whl → 2.13.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. ads/aqua/app.py +2 -1
  2. ads/aqua/evaluation/evaluation.py +11 -10
  3. ads/aqua/finetuning/finetuning.py +2 -3
  4. ads/opctl/operator/lowcode/anomaly/model/base_model.py +3 -3
  5. ads/opctl/operator/lowcode/anomaly/model/randomcutforest.py +1 -1
  6. ads/opctl/operator/lowcode/anomaly/utils.py +1 -1
  7. ads/opctl/operator/lowcode/common/transformations.py +5 -1
  8. ads/opctl/operator/lowcode/common/utils.py +7 -2
  9. ads/opctl/operator/lowcode/forecast/model/arima.py +15 -10
  10. ads/opctl/operator/lowcode/forecast/model/automlx.py +31 -9
  11. ads/opctl/operator/lowcode/forecast/model/autots.py +7 -5
  12. ads/opctl/operator/lowcode/forecast/model/base_model.py +127 -101
  13. ads/opctl/operator/lowcode/forecast/model/forecast_datasets.py +14 -6
  14. ads/opctl/operator/lowcode/forecast/model/ml_forecast.py +2 -2
  15. ads/opctl/operator/lowcode/forecast/model/neuralprophet.py +46 -32
  16. ads/opctl/operator/lowcode/forecast/model/prophet.py +82 -29
  17. ads/opctl/operator/lowcode/forecast/model_evaluator.py +136 -54
  18. ads/opctl/operator/lowcode/forecast/operator_config.py +29 -3
  19. ads/opctl/operator/lowcode/forecast/whatifserve/deployment_manager.py +103 -58
  20. {oracle_ads-2.13.2.dist-info → oracle_ads-2.13.3.dist-info}/METADATA +1 -1
  21. {oracle_ads-2.13.2.dist-info → oracle_ads-2.13.3.dist-info}/RECORD +24 -24
  22. {oracle_ads-2.13.2.dist-info → oracle_ads-2.13.3.dist-info}/WHEEL +0 -0
  23. {oracle_ads-2.13.2.dist-info → oracle_ads-2.13.3.dist-info}/entry_points.txt +0 -0
  24. {oracle_ads-2.13.2.dist-info → oracle_ads-2.13.3.dist-info}/licenses/LICENSE.txt +0 -0
@@ -28,8 +28,8 @@ from ads.opctl.operator.lowcode.common.utils import (
28
28
  merged_category_column_name,
29
29
  seconds_to_datetime,
30
30
  write_data,
31
+ write_json,
31
32
  )
32
- from ads.opctl.operator.lowcode.forecast.model.forecast_datasets import TestData
33
33
  from ads.opctl.operator.lowcode.forecast.utils import (
34
34
  _build_metrics_df,
35
35
  _build_metrics_per_horizon,
@@ -46,6 +46,7 @@ from ..const import (
46
46
  AUTO_SELECT,
47
47
  BACKTEST_REPORT_NAME,
48
48
  SUMMARY_METRICS_HORIZON_LIMIT,
49
+ ForecastOutputColumns,
49
50
  SpeedAccuracyMode,
50
51
  SupportedMetrics,
51
52
  SupportedModels,
@@ -132,11 +133,10 @@ class ForecastOperatorBaseModel(ABC):
132
133
 
133
134
  if self.datasets.test_data is not None:
134
135
  try:
135
- (
136
- self.test_eval_metrics,
137
- summary_metrics
138
- ) = self._test_evaluate_metrics(
139
- elapsed_time=elapsed_time,
136
+ (self.test_eval_metrics, summary_metrics) = (
137
+ self._test_evaluate_metrics(
138
+ elapsed_time=elapsed_time,
139
+ )
140
140
  )
141
141
  if not self.target_cat_col:
142
142
  self.test_eval_metrics.rename(
@@ -145,7 +145,7 @@ class ForecastOperatorBaseModel(ABC):
145
145
  inplace=True,
146
146
  )
147
147
  except Exception:
148
- logger.warn("Unable to generate Test Metrics.")
148
+ logger.warning("Unable to generate Test Metrics.")
149
149
  logger.debug(f"Full Traceback: {traceback.format_exc()}")
150
150
  report_sections = []
151
151
 
@@ -155,9 +155,8 @@ class ForecastOperatorBaseModel(ABC):
155
155
  model_description,
156
156
  other_sections,
157
157
  ) = self._generate_report()
158
-
159
158
  header_section = rc.Block(
160
- rc.Heading("Forecast Report", level=1),
159
+ rc.Heading(self.spec.report_title, level=1),
161
160
  rc.Text(
162
161
  f"You selected the {self.spec.model} model.\nBased on your dataset, you could have also selected any of the models: {SupportedModels.keys()}."
163
162
  ),
@@ -369,7 +368,7 @@ class ForecastOperatorBaseModel(ABC):
369
368
  -self.spec.horizon :
370
369
  ]
371
370
  except KeyError as ke:
372
- logger.warn(
371
+ logger.warning(
373
372
  f"Error Generating Metrics: Unable to find {s_id} in the test data. Error: {ke.args}"
374
373
  )
375
374
  y_pred = self.forecast_output.get_forecast(s_id)["forecast_value"].values[
@@ -478,10 +477,11 @@ class ForecastOperatorBaseModel(ABC):
478
477
  unique_output_dir = self.spec.output_directory.url
479
478
  results = ForecastResults()
480
479
 
481
- if ObjectStorageDetails.is_oci_path(unique_output_dir):
482
- storage_options = default_signer()
483
- else:
484
- storage_options = {}
480
+ storage_options = (
481
+ default_signer()
482
+ if ObjectStorageDetails.is_oci_path(unique_output_dir)
483
+ else {}
484
+ )
485
485
 
486
486
  # report-creator html report
487
487
  if self.spec.generate_report:
@@ -512,12 +512,13 @@ class ForecastOperatorBaseModel(ABC):
512
512
  if self.target_cat_col
513
513
  else result_df.drop(DataColumns.Series, axis=1)
514
514
  )
515
- write_data(
516
- data=result_df,
517
- filename=os.path.join(unique_output_dir, self.spec.forecast_filename),
518
- format="csv",
519
- storage_options=storage_options,
520
- )
515
+ if self.spec.generate_forecast_file:
516
+ write_data(
517
+ data=result_df,
518
+ filename=os.path.join(unique_output_dir, self.spec.forecast_filename),
519
+ format="csv",
520
+ storage_options=storage_options,
521
+ )
521
522
  results.set_forecast(result_df)
522
523
 
523
524
  # metrics csv report
@@ -531,18 +532,19 @@ class ForecastOperatorBaseModel(ABC):
531
532
  metrics_df_formatted = metrics_df.reset_index().rename(
532
533
  {"index": "metrics", "Series 1": metrics_col_name}, axis=1
533
534
  )
534
- write_data(
535
- data=metrics_df_formatted,
536
- filename=os.path.join(
537
- unique_output_dir, self.spec.metrics_filename
538
- ),
539
- format="csv",
540
- storage_options=storage_options,
541
- index=False,
542
- )
535
+ if self.spec.generate_metrics_file:
536
+ write_data(
537
+ data=metrics_df_formatted,
538
+ filename=os.path.join(
539
+ unique_output_dir, self.spec.metrics_filename
540
+ ),
541
+ format="csv",
542
+ storage_options=storage_options,
543
+ index=False,
544
+ )
543
545
  results.set_metrics(metrics_df_formatted)
544
546
  else:
545
- logger.warn(
547
+ logger.warning(
546
548
  f"Attempted to generate the {self.spec.metrics_filename} file with the training metrics, however the training metrics could not be properly generated."
547
549
  )
548
550
 
@@ -552,56 +554,59 @@ class ForecastOperatorBaseModel(ABC):
552
554
  test_metrics_df_formatted = test_metrics_df.reset_index().rename(
553
555
  {"index": "metrics", "Series 1": metrics_col_name}, axis=1
554
556
  )
555
- write_data(
556
- data=test_metrics_df_formatted,
557
- filename=os.path.join(
558
- unique_output_dir, self.spec.test_metrics_filename
559
- ),
560
- format="csv",
561
- storage_options=storage_options,
562
- index=False,
563
- )
557
+ if self.spec.generate_metrics_file:
558
+ write_data(
559
+ data=test_metrics_df_formatted,
560
+ filename=os.path.join(
561
+ unique_output_dir, self.spec.test_metrics_filename
562
+ ),
563
+ format="csv",
564
+ storage_options=storage_options,
565
+ index=False,
566
+ )
564
567
  results.set_test_metrics(test_metrics_df_formatted)
565
568
  else:
566
- logger.warn(
569
+ logger.warning(
567
570
  f"Attempted to generate the {self.spec.test_metrics_filename} file with the test metrics, however the test metrics could not be properly generated."
568
571
  )
569
572
  # explanations csv reports
570
573
  if self.spec.generate_explanations:
571
574
  try:
572
575
  if not self.formatted_global_explanation.empty:
573
- write_data(
574
- data=self.formatted_global_explanation,
575
- filename=os.path.join(
576
- unique_output_dir, self.spec.global_explanation_filename
577
- ),
578
- format="csv",
579
- storage_options=storage_options,
580
- index=True,
581
- )
576
+ if self.spec.generate_explanation_files:
577
+ write_data(
578
+ data=self.formatted_global_explanation,
579
+ filename=os.path.join(
580
+ unique_output_dir, self.spec.global_explanation_filename
581
+ ),
582
+ format="csv",
583
+ storage_options=storage_options,
584
+ index=True,
585
+ )
582
586
  results.set_global_explanations(self.formatted_global_explanation)
583
587
  else:
584
- logger.warn(
588
+ logger.warning(
585
589
  f"Attempted to generate global explanations for the {self.spec.global_explanation_filename} file, but an issue occured in formatting the explanations."
586
590
  )
587
591
 
588
592
  if not self.formatted_local_explanation.empty:
589
- write_data(
590
- data=self.formatted_local_explanation,
591
- filename=os.path.join(
592
- unique_output_dir, self.spec.local_explanation_filename
593
- ),
594
- format="csv",
595
- storage_options=storage_options,
596
- index=True,
597
- )
593
+ if self.spec.generate_explanation_files:
594
+ write_data(
595
+ data=self.formatted_local_explanation,
596
+ filename=os.path.join(
597
+ unique_output_dir, self.spec.local_explanation_filename
598
+ ),
599
+ format="csv",
600
+ storage_options=storage_options,
601
+ index=True,
602
+ )
598
603
  results.set_local_explanations(self.formatted_local_explanation)
599
604
  else:
600
- logger.warn(
605
+ logger.warning(
601
606
  f"Attempted to generate local explanations for the {self.spec.local_explanation_filename} file, but an issue occured in formatting the explanations."
602
607
  )
603
608
  except AttributeError as e:
604
- logger.warn(
609
+ logger.warning(
605
610
  "Unable to generate explanations for this model type or for this dataset."
606
611
  )
607
612
  logger.debug(f"Got error: {e.args}")
@@ -631,15 +636,12 @@ class ForecastOperatorBaseModel(ABC):
631
636
  f"The outputs have been successfully generated and placed into the directory: {unique_output_dir}."
632
637
  )
633
638
  if self.errors_dict:
634
- write_data(
635
- data=pd.DataFrame.from_dict(self.errors_dict),
639
+ write_json(
640
+ json_dict=self.errors_dict,
636
641
  filename=os.path.join(
637
642
  unique_output_dir, self.spec.errors_dict_filename
638
643
  ),
639
- format="json",
640
644
  storage_options=storage_options,
641
- index=True,
642
- indent=4,
643
645
  )
644
646
  results.set_errors_dict(self.errors_dict)
645
647
  else:
@@ -742,45 +744,62 @@ class ForecastOperatorBaseModel(ABC):
742
744
  include_horizon=False
743
745
  ).items():
744
746
  if s_id in self.models:
745
- explain_predict_fn = self.get_explain_predict_fn(series_id=s_id)
746
- data_trimmed = data_i.tail(
747
- max(int(len(data_i) * ratio), 5)
748
- ).reset_index(drop=True)
749
- data_trimmed[datetime_col_name] = data_trimmed[datetime_col_name].apply(
750
- lambda x: x.timestamp()
751
- )
752
-
753
- # Explainer fails when boolean columns are passed
754
-
755
- _, data_trimmed_encoded = _label_encode_dataframe(
756
- data_trimmed,
757
- no_encode={datetime_col_name, self.original_target_column},
758
- )
759
-
760
- kernel_explnr = PermutationExplainer(
761
- model=explain_predict_fn, masker=data_trimmed_encoded
762
- )
763
- kernel_explnr_vals = kernel_explnr.shap_values(data_trimmed_encoded)
764
- exp_end_time = time.time()
765
- global_ex_time = global_ex_time + exp_end_time - exp_start_time
766
- self.local_explainer(
767
- kernel_explnr, series_id=s_id, datetime_col_name=datetime_col_name
768
- )
769
- local_ex_time = local_ex_time + time.time() - exp_end_time
747
+ try:
748
+ explain_predict_fn = self.get_explain_predict_fn(series_id=s_id)
749
+ data_trimmed = data_i.tail(
750
+ max(int(len(data_i) * ratio), 5)
751
+ ).reset_index(drop=True)
752
+ data_trimmed[datetime_col_name] = data_trimmed[
753
+ datetime_col_name
754
+ ].apply(lambda x: x.timestamp())
755
+
756
+ # Explainer fails when boolean columns are passed
757
+
758
+ _, data_trimmed_encoded = _label_encode_dataframe(
759
+ data_trimmed,
760
+ no_encode={datetime_col_name, self.original_target_column},
761
+ )
770
762
 
771
- if not len(kernel_explnr_vals):
772
- logger.warn(
773
- "No explanations generated. Ensure that additional data has been provided."
763
+ kernel_explnr = PermutationExplainer(
764
+ model=explain_predict_fn, masker=data_trimmed_encoded
774
765
  )
775
- else:
776
- self.global_explanation[s_id] = dict(
777
- zip(
778
- data_trimmed.columns[1:],
779
- np.average(np.absolute(kernel_explnr_vals[:, 1:]), axis=0),
780
- )
766
+ kernel_explnr_vals = kernel_explnr.shap_values(data_trimmed_encoded)
767
+ exp_end_time = time.time()
768
+ global_ex_time = global_ex_time + exp_end_time - exp_start_time
769
+ self.local_explainer(
770
+ kernel_explnr,
771
+ series_id=s_id,
772
+ datetime_col_name=datetime_col_name,
781
773
  )
774
+ local_ex_time = local_ex_time + time.time() - exp_end_time
775
+
776
+ if not len(kernel_explnr_vals):
777
+ logger.warning(
778
+ "No explanations generated. Ensure that additional data has been provided."
779
+ )
780
+ else:
781
+ self.global_explanation[s_id] = dict(
782
+ zip(
783
+ data_trimmed.columns[1:],
784
+ np.average(
785
+ np.absolute(kernel_explnr_vals[:, 1:]), axis=0
786
+ ),
787
+ )
788
+ )
789
+ except Exception as e:
790
+ if s_id in self.errors_dict:
791
+ self.errors_dict[s_id]["explainer_error"] = str(e)
792
+ self.errors_dict[s_id]["explainer_error_trace"] = (
793
+ traceback.format_exc()
794
+ )
795
+ else:
796
+ self.errors_dict[s_id] = {
797
+ "model_name": self.spec.model,
798
+ "explainer_error": str(e),
799
+ "explainer_error_trace": traceback.format_exc(),
800
+ }
782
801
  else:
783
- logger.warn(
802
+ logger.warning(
784
803
  f"Skipping explanations for {s_id}, as forecast was not generated."
785
804
  )
786
805
 
@@ -815,6 +834,13 @@ class ForecastOperatorBaseModel(ABC):
815
834
  local_kernel_explnr_df = pd.DataFrame(
816
835
  local_kernel_explnr_vals, columns=data.columns
817
836
  )
837
+
838
+ # Add date column to local explanation DataFrame
839
+ local_kernel_explnr_df[ForecastOutputColumns.DATE] = (
840
+ self.datasets.get_horizon_at_series(
841
+ s_id=series_id
842
+ )[self.spec.datetime_column.name].reset_index(drop=True)
843
+ )
818
844
  self.local_explanation[series_id] = local_kernel_explnr_df
819
845
 
820
846
  def get_explain_predict_fn(self, series_id, fcst_col_name="yhat"):
@@ -23,14 +23,14 @@ from ..operator_config import ForecastOperatorConfig
23
23
 
24
24
 
25
25
  class HistoricalData(AbstractData):
26
- def __init__(self, spec, historical_data = None):
26
+ def __init__(self, spec, historical_data=None):
27
27
  super().__init__(spec=spec, name="historical_data", data=historical_data)
28
28
 
29
29
  def _ingest_data(self, spec):
30
30
  try:
31
31
  self.freq = get_frequency_of_datetime(self.data.index.get_level_values(0))
32
32
  except TypeError as e:
33
- logger.warn(
33
+ logger.warning(
34
34
  f"Error determining frequency: {e.args}. Setting Frequency to None"
35
35
  )
36
36
  logger.debug(f"Full traceback: {e}")
@@ -106,7 +106,7 @@ class AdditionalData(AbstractData):
106
106
  _spec = spec
107
107
  self.additional_regressors = list(self.data.columns)
108
108
  if not self.additional_regressors:
109
- logger.warn(
109
+ logger.warning(
110
110
  f"No additional variables found in the additional_data. Only columns found: {self.data.columns}. Skipping for now."
111
111
  )
112
112
  # Check that datetime column matches historical datetime column
@@ -121,7 +121,13 @@ class TestData(AbstractData):
121
121
 
122
122
 
123
123
  class ForecastDatasets:
124
- def __init__(self, config: ForecastOperatorConfig, historical_data=None, additional_data=None, test_data=None):
124
+ def __init__(
125
+ self,
126
+ config: ForecastOperatorConfig,
127
+ historical_data=None,
128
+ additional_data=None,
129
+ test_data=None,
130
+ ):
125
131
  """Instantiates the DataIO instance.
126
132
 
127
133
  Properties
@@ -136,7 +142,9 @@ class ForecastDatasets:
136
142
  self._target_col = config.spec.target_column
137
143
  if historical_data is not None:
138
144
  self.historical_data = HistoricalData(config.spec, historical_data)
139
- self.additional_data = AdditionalData(config.spec, self.historical_data, additional_data)
145
+ self.additional_data = AdditionalData(
146
+ config.spec, self.historical_data, additional_data
147
+ )
140
148
  else:
141
149
  self._load_data(config.spec)
142
150
  self.test_data = TestData(config.spec, test_data)
@@ -147,7 +155,7 @@ class ForecastDatasets:
147
155
  self.additional_data = AdditionalData(spec, self.historical_data)
148
156
 
149
157
  if spec.generate_explanations and spec.additional_data is None:
150
- logger.warn(
158
+ logger.warning(
151
159
  "Unable to generate explanations as there is no additional data passed in. Either set generate_explanations to False, or pass in additional data."
152
160
  )
153
161
  spec.generate_explanations = False
@@ -168,8 +168,8 @@ class MLForecastOperatorModel(ForecastOperatorBaseModel):
168
168
  "error": str(e),
169
169
  "error_trace": traceback.format_exc(),
170
170
  }
171
- logger.warn(f"Encountered Error: {e}. Skipping.")
172
- logger.warn(traceback.format_exc())
171
+ logger.warning(f"Encountered Error: {e}. Skipping.")
172
+ logger.warning(traceback.format_exc())
173
173
  raise e
174
174
 
175
175
  def _build_model(self) -> pd.DataFrame:
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python
2
2
 
3
- # Copyright (c) 2023, 2024 Oracle and/or its affiliates.
3
+ # Copyright (c) 2023, 2025 Oracle and/or its affiliates.
4
4
  # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
5
5
 
6
6
  import logging
@@ -40,7 +40,7 @@ from .forecast_datasets import ForecastDatasets, ForecastOutput
40
40
  # "rmse": MeanSquaredError,
41
41
  # }
42
42
  # if selected_metric not in metric_translation.keys():
43
- # logger.warn(
43
+ # logger.warning(
44
44
  # f"Could not find the metric: {selected_metric} in torchmetrics. Defaulting to MAE and RMSE"
45
45
  # )
46
46
  # return {"MAE": MeanAbsoluteError(), "RMSE": MeanSquaredError()}
@@ -149,28 +149,42 @@ class NeuralProphetOperatorModel(ForecastOperatorBaseModel):
149
149
  logger.debug(f"-----------------Model {i}----------------------")
150
150
  logger.debug(forecast.tail())
151
151
 
152
- # TODO; could also extract trend and seasonality?
153
- cols_to_read = filter(
154
- lambda x: x.startswith("future_regressor"), forecast.columns
155
- )
156
- self.explanations_info[s_id] = forecast[cols_to_read]
157
- self.explanations_info[s_id]["Date"] = forecast["ds"]
158
- self.explanations_info[s_id] = self.explanations_info[s_id].set_index(
159
- "Date"
160
- )
161
-
162
152
  self.outputs[s_id] = forecast
153
+ upper_bound_col_name = f"yhat1 {model_kwargs['quantiles'][1]*100}%"
154
+ lower_bound_col_name = f"yhat1 {model_kwargs['quantiles'][0]*100}%"
163
155
  self.forecast_output.populate_series_output(
164
156
  series_id=s_id,
165
157
  fit_val=self.drop_horizon(forecast["yhat1"]).values,
166
158
  forecast_val=self.get_horizon(forecast["yhat1"]).values,
167
- upper_bound=self.get_horizon(
168
- forecast[f"yhat1 {model_kwargs['quantiles'][1]*100}%"]
169
- ).values,
170
- lower_bound=self.get_horizon(
171
- forecast[f"yhat1 {model_kwargs['quantiles'][0]*100}%"]
172
- ).values,
159
+ upper_bound=self.get_horizon(forecast[upper_bound_col_name]).values,
160
+ lower_bound=self.get_horizon(forecast[lower_bound_col_name]).values,
161
+ )
162
+ core_columns = set(forecast.columns) - set(
163
+ [
164
+ "y",
165
+ "yhat1",
166
+ upper_bound_col_name,
167
+ lower_bound_col_name,
168
+ "future_regressors_additive",
169
+ "future_regressors_multiplicative",
170
+ ]
171
+ )
172
+ exog_variables = set(
173
+ filter(lambda x: x.startswith("future_regressor_"), list(core_columns))
173
174
  )
175
+ combine_terms = list(core_columns - exog_variables - set(["ds"]))
176
+ temp_df = (
177
+ forecast[list(core_columns)]
178
+ .rename({"ds": "Date"}, axis=1)
179
+ .set_index("Date")
180
+ )
181
+ if combine_terms:
182
+ temp_df[self.spec.target_column] = temp_df[combine_terms].sum(axis=1)
183
+ temp_df = temp_df.drop(combine_terms, axis=1)
184
+ else:
185
+ temp_df[self.spec.target_column] = 0
186
+ # Todo: check for columns that were dropped, and set them to 0
187
+ self.explanations_info[s_id] = temp_df
174
188
 
175
189
  self.trainers[s_id] = model.trainer
176
190
  self.models[s_id] = {}
@@ -207,7 +221,7 @@ class NeuralProphetOperatorModel(ForecastOperatorBaseModel):
207
221
  "error": str(e),
208
222
  "error_trace": traceback.format_exc(),
209
223
  }
210
- logger.warn(traceback.format_exc())
224
+ logger.warning(traceback.format_exc())
211
225
  raise e
212
226
 
213
227
  def _build_model(self) -> pd.DataFrame:
@@ -215,7 +229,6 @@ class NeuralProphetOperatorModel(ForecastOperatorBaseModel):
215
229
  self.models = {}
216
230
  self.trainers = {}
217
231
  self.outputs = {}
218
- self.errors_dict = {}
219
232
  self.explanations_info = {}
220
233
  self.accepted_regressors = {}
221
234
  self.additional_regressors = self.datasets.get_additional_data_column_names()
@@ -363,7 +376,9 @@ class NeuralProphetOperatorModel(ForecastOperatorBaseModel):
363
376
  pd.Series(
364
377
  m.state_dict(),
365
378
  index=m.state_dict().keys(),
366
- name=s_id if self.target_cat_col else self.original_target_column,
379
+ name=s_id
380
+ if self.target_cat_col
381
+ else self.original_target_column,
367
382
  )
368
383
  )
369
384
  all_model_states = pd.concat(model_states, axis=1)
@@ -377,11 +392,15 @@ class NeuralProphetOperatorModel(ForecastOperatorBaseModel):
377
392
  self.explain_model()
378
393
 
379
394
  if not self.target_cat_col:
380
- self.formatted_global_explanation = self.formatted_global_explanation.rename(
381
- {"Series 1": self.original_target_column},
382
- axis=1,
395
+ self.formatted_global_explanation = (
396
+ self.formatted_global_explanation.rename(
397
+ {"Series 1": self.original_target_column},
398
+ axis=1,
399
+ )
400
+ )
401
+ self.formatted_local_explanation.drop(
402
+ "Series", axis=1, inplace=True
383
403
  )
384
- self.formatted_local_explanation.drop("Series", axis=1, inplace=True)
385
404
 
386
405
  # Create a markdown section for the global explainability
387
406
  global_explanation_section = rc.Block(
@@ -412,7 +431,7 @@ class NeuralProphetOperatorModel(ForecastOperatorBaseModel):
412
431
  ]
413
432
  except Exception as e:
414
433
  # Do not fail the whole run due to explanations failure
415
- logger.warn(f"Failed to generate Explanations with error: {e}.")
434
+ logger.warning(f"Failed to generate Explanations with error: {e}.")
416
435
  logger.debug(f"Full Traceback: {traceback.format_exc()}")
417
436
 
418
437
  model_description = rc.Text(
@@ -453,9 +472,7 @@ class NeuralProphetOperatorModel(ForecastOperatorBaseModel):
453
472
  for s_id, expl_df in self.explanations_info.items():
454
473
  expl_df = expl_df.rename(rename_cols, axis=1)
455
474
  # Local Expl
456
- self.local_explanation[s_id] = self.get_horizon(expl_df).drop(
457
- ["future_regressors_additive"], axis=1
458
- )
475
+ self.local_explanation[s_id] = self.get_horizon(expl_df)
459
476
  self.local_explanation[s_id]["Series"] = s_id
460
477
  self.local_explanation[s_id].index.rename(self.dt_column_name, inplace=True)
461
478
  # Global Expl
@@ -463,9 +480,6 @@ class NeuralProphetOperatorModel(ForecastOperatorBaseModel):
463
480
  g_expl.name = s_id
464
481
  global_expl.append(g_expl)
465
482
  self.global_explanation = pd.concat(global_expl, axis=1)
466
- self.global_explanation = self.global_explanation.drop(
467
- index=["future_regressors_additive"], axis=0
468
- )
469
483
  self.formatted_global_explanation = (
470
484
  self.global_explanation / self.global_explanation.sum(axis=0) * 100
471
485
  )