oracle-ads 2.11.6__py3-none-any.whl → 2.11.8__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 (64) hide show
  1. ads/aqua/__init__.py +24 -14
  2. ads/aqua/base.py +0 -2
  3. ads/aqua/cli.py +50 -2
  4. ads/aqua/decorator.py +8 -0
  5. ads/aqua/deployment.py +37 -34
  6. ads/aqua/evaluation.py +106 -49
  7. ads/aqua/extension/base_handler.py +18 -10
  8. ads/aqua/extension/common_handler.py +21 -2
  9. ads/aqua/extension/deployment_handler.py +1 -4
  10. ads/aqua/extension/evaluation_handler.py +1 -2
  11. ads/aqua/extension/finetune_handler.py +0 -1
  12. ads/aqua/extension/ui_handler.py +1 -12
  13. ads/aqua/extension/utils.py +4 -4
  14. ads/aqua/finetune.py +24 -11
  15. ads/aqua/model.py +2 -4
  16. ads/aqua/utils.py +39 -23
  17. ads/catalog/model.py +3 -3
  18. ads/catalog/notebook.py +3 -3
  19. ads/catalog/project.py +2 -2
  20. ads/catalog/summary.py +2 -4
  21. ads/cli.py +21 -2
  22. ads/common/serializer.py +5 -4
  23. ads/common/utils.py +6 -2
  24. ads/config.py +1 -0
  25. ads/data_labeling/metadata.py +2 -2
  26. ads/dataset/dataset.py +3 -5
  27. ads/dataset/factory.py +2 -3
  28. ads/dataset/label_encoder.py +1 -1
  29. ads/dataset/sampled_dataset.py +3 -5
  30. ads/jobs/ads_job.py +26 -2
  31. ads/jobs/builders/infrastructure/dsc_job.py +20 -7
  32. ads/llm/serializers/runnable_parallel.py +7 -1
  33. ads/model/model_artifact_boilerplate/artifact_introspection_test/model_artifact_validate.py +1 -1
  34. ads/opctl/operator/lowcode/anomaly/README.md +1 -1
  35. ads/opctl/operator/lowcode/anomaly/environment.yaml +1 -1
  36. ads/opctl/operator/lowcode/anomaly/model/anomaly_dataset.py +8 -15
  37. ads/opctl/operator/lowcode/anomaly/model/automlx.py +16 -10
  38. ads/opctl/operator/lowcode/anomaly/model/autots.py +9 -10
  39. ads/opctl/operator/lowcode/anomaly/model/base_model.py +36 -39
  40. ads/opctl/operator/lowcode/anomaly/model/tods.py +4 -4
  41. ads/opctl/operator/lowcode/anomaly/operator_config.py +18 -1
  42. ads/opctl/operator/lowcode/anomaly/schema.yaml +16 -4
  43. ads/opctl/operator/lowcode/common/data.py +16 -2
  44. ads/opctl/operator/lowcode/common/transformations.py +48 -14
  45. ads/opctl/operator/lowcode/forecast/README.md +1 -1
  46. ads/opctl/operator/lowcode/forecast/environment.yaml +5 -4
  47. ads/opctl/operator/lowcode/forecast/model/arima.py +36 -29
  48. ads/opctl/operator/lowcode/forecast/model/automlx.py +91 -90
  49. ads/opctl/operator/lowcode/forecast/model/autots.py +200 -166
  50. ads/opctl/operator/lowcode/forecast/model/base_model.py +144 -140
  51. ads/opctl/operator/lowcode/forecast/model/neuralprophet.py +86 -80
  52. ads/opctl/operator/lowcode/forecast/model/prophet.py +68 -63
  53. ads/opctl/operator/lowcode/forecast/operator_config.py +18 -2
  54. ads/opctl/operator/lowcode/forecast/schema.yaml +20 -4
  55. ads/opctl/operator/lowcode/forecast/utils.py +8 -4
  56. ads/opctl/operator/lowcode/pii/README.md +1 -1
  57. ads/opctl/operator/lowcode/pii/environment.yaml +1 -1
  58. ads/opctl/operator/lowcode/pii/model/report.py +71 -70
  59. ads/pipeline/ads_pipeline_step.py +11 -12
  60. {oracle_ads-2.11.6.dist-info → oracle_ads-2.11.8.dist-info}/METADATA +8 -7
  61. {oracle_ads-2.11.6.dist-info → oracle_ads-2.11.8.dist-info}/RECORD +64 -64
  62. {oracle_ads-2.11.6.dist-info → oracle_ads-2.11.8.dist-info}/LICENSE.txt +0 -0
  63. {oracle_ads-2.11.6.dist-info → oracle_ads-2.11.8.dist-info}/WHEEL +0 -0
  64. {oracle_ads-2.11.6.dist-info → oracle_ads-2.11.8.dist-info}/entry_points.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding: utf-8 -*--
3
3
 
4
- # Copyright (c) 2023 Oracle and/or its affiliates.
4
+ # Copyright (c) 2023, 2024 Oracle and/or its affiliates.
5
5
  # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
6
6
 
7
7
  import copy
@@ -54,145 +54,161 @@ class AutoTSOperatorModel(ForecastOperatorBaseModel):
54
54
  target_column=self.original_target_column,
55
55
  dt_column=self.spec.datetime_column.name,
56
56
  )
57
- model = self.loaded_models if self.loaded_models is not None else None
58
- if model is None:
59
- # Initialize the AutoTS model with specified parameters
60
- model = AutoTS(
61
- forecast_length=self.spec.horizon,
62
- frequency=self.spec.model_kwargs.get(
63
- "frequency", "infer"
64
- ), # TODO: Use datasets.get_datetime_frequency ?
65
- prediction_interval=self.spec.confidence_interval_width,
66
- max_generations=self.spec.model_kwargs.get(
67
- "max_generations", AUTOTS_MAX_GENERATION
68
- ),
69
- no_negatives=self.spec.model_kwargs.get("no_negatives", False),
70
- constraint=self.spec.model_kwargs.get("constraint", None),
71
- ensemble=self.spec.model_kwargs.get("ensemble", "auto"),
72
- initial_template=self.spec.model_kwargs.get(
73
- "initial_template", "General+Random"
74
- ),
75
- random_seed=self.spec.model_kwargs.get("random_seed", 2022),
76
- holiday_country=self.spec.model_kwargs.get("holiday_country", "US"),
77
- subset=self.spec.model_kwargs.get("subset", None),
78
- aggfunc=self.spec.model_kwargs.get("aggfunc", "first"),
79
- na_tolerance=self.spec.model_kwargs.get("na_tolerance", 1),
80
- drop_most_recent=self.spec.model_kwargs.get("drop_most_recent", 0),
81
- drop_data_older_than_periods=self.spec.model_kwargs.get(
82
- "drop_data_older_than_periods", None
83
- ),
84
- model_list=self.spec.model_kwargs.get("model_list", "fast_parallel"),
85
- transformer_list=self.spec.model_kwargs.get("transformer_list", "auto"),
86
- transformer_max_depth=self.spec.model_kwargs.get(
87
- "transformer_max_depth", 6
88
- ),
89
- models_mode=self.spec.model_kwargs.get("models_mode", "random"),
90
- num_validations=self.spec.model_kwargs.get("num_validations", "auto"),
91
- models_to_validate=self.spec.model_kwargs.get(
92
- "models_to_validate", AUTOTS_MODELS_TO_VALIDATE
93
- ),
94
- max_per_model_class=self.spec.model_kwargs.get(
95
- "max_per_model_class", None
96
- ),
97
- validation_method=self.spec.model_kwargs.get(
98
- "validation_method", "backwards"
99
- ),
100
- min_allowed_train_percent=self.spec.model_kwargs.get(
101
- "min_allowed_train_percent", 0.5
102
- ),
103
- remove_leading_zeroes=self.spec.model_kwargs.get(
104
- "remove_leading_zeroes", False
105
- ),
106
- prefill_na=self.spec.model_kwargs.get("prefill_na", None),
107
- introduce_na=self.spec.model_kwargs.get("introduce_na", None),
108
- preclean=self.spec.model_kwargs.get("preclean", None),
109
- model_interrupt=self.spec.model_kwargs.get("model_interrupt", True),
110
- generation_timeout=self.spec.model_kwargs.get(
111
- "generation_timeout", None
112
- ),
113
- current_model_file=self.spec.model_kwargs.get(
114
- "current_model_file", None
115
- ),
116
- verbose=-1 if logger.level > 40 else 1,
117
- n_jobs=self.spec.model_kwargs.get("n_jobs", -1),
118
- )
119
-
120
- full_data_indexed = self.datasets.get_data_multi_indexed()
121
-
122
- dates = full_data_indexed.index.get_level_values(0).unique().tolist()
123
- train_idx = dates[: -self.spec.horizon]
124
-
125
- df_train = full_data_indexed[
126
- full_data_indexed.index.get_level_values(0).isin(train_idx)
127
- ][[self.original_target_column]].reset_index()
128
-
129
- # Future regressors need to be in wide format - (num_unique_dates x (num_unique_series x num_unique_cols))
130
- additional_regressors = list(
131
- set(full_data_indexed.columns) - {self.original_target_column}
132
- )
133
- if len(additional_regressors) > 1:
134
- future_regressor = full_data_indexed.reset_index().pivot(
135
- index=self.spec.datetime_column.name,
136
- columns=ForecastOutputColumns.SERIES,
137
- values=additional_regressors,
138
- )
139
- future_reg = future_regressor[: -self.spec.horizon]
140
- regr_fcst = future_regressor[-self.spec.horizon :]
141
- else:
142
- future_reg = None
143
- regr_fcst = None
144
-
145
- if self.loaded_models is None:
146
- model = model.fit(
147
- df_train,
148
- future_regressor=future_reg,
149
- date_col=self.spec.datetime_column.name,
150
- value_col=self.original_target_column,
151
- id_col=ForecastOutputColumns.SERIES,
152
- )
153
- # Store the trained model and generate forecasts
154
- self.models = copy.deepcopy(model)
155
- else:
156
- self.models = self.loaded_models
157
-
158
- self.outputs = model.predict(future_regressor=regr_fcst)
159
- logger.debug("===========Forecast Generated===========")
160
-
161
- hist_df = model.back_forecast().forecast
162
-
163
- params = vars(model).copy()
164
- for param in [
165
- "ens_copy",
166
- "df_wide_numeric",
167
- "future_regressor_train",
168
- "initial_results",
169
- "score_per_series",
170
- "validation_results",
171
- "validation_train_indexes",
172
- "validation_test_indexes",
173
- "validation_indexes",
174
- "best_model",
175
- ]:
176
- if param in params:
177
- params.pop(param)
178
-
179
- for s_id in self.datasets.list_series_ids():
180
- self.forecast_output.init_series_output(
181
- series_id=s_id, data_at_series=self.datasets.get_data_at_series(s_id)
182
- )
183
-
184
- self.forecast_output.populate_series_output(
185
- series_id=s_id,
186
- fit_val=hist_df[s_id].values,
187
- forecast_val=self.outputs.forecast[s_id].values,
188
- upper_bound=self.outputs.upper_forecast[s_id].values,
189
- lower_bound=self.outputs.lower_forecast[s_id].values,
57
+ try:
58
+ model = self.loaded_models if self.loaded_models is not None else None
59
+ if model is None:
60
+ # Initialize the AutoTS model with specified parameters
61
+ model = AutoTS(
62
+ forecast_length=self.spec.horizon,
63
+ frequency=self.spec.model_kwargs.get(
64
+ "frequency", "infer"
65
+ ), # TODO: Use datasets.get_datetime_frequency ?
66
+ prediction_interval=self.spec.confidence_interval_width,
67
+ max_generations=self.spec.model_kwargs.get(
68
+ "max_generations", AUTOTS_MAX_GENERATION
69
+ ),
70
+ no_negatives=self.spec.model_kwargs.get("no_negatives", False),
71
+ constraint=self.spec.model_kwargs.get("constraint", None),
72
+ ensemble=self.spec.model_kwargs.get("ensemble", "auto"),
73
+ initial_template=self.spec.model_kwargs.get(
74
+ "initial_template", "General+Random"
75
+ ),
76
+ random_seed=self.spec.model_kwargs.get("random_seed", 2022),
77
+ holiday_country=self.spec.model_kwargs.get("holiday_country", "US"),
78
+ subset=self.spec.model_kwargs.get("subset", None),
79
+ aggfunc=self.spec.model_kwargs.get("aggfunc", "first"),
80
+ na_tolerance=self.spec.model_kwargs.get("na_tolerance", 1),
81
+ drop_most_recent=self.spec.model_kwargs.get("drop_most_recent", 0),
82
+ drop_data_older_than_periods=self.spec.model_kwargs.get(
83
+ "drop_data_older_than_periods", None
84
+ ),
85
+ model_list=self.spec.model_kwargs.get(
86
+ "model_list", "fast_parallel"
87
+ ),
88
+ transformer_list=self.spec.model_kwargs.get(
89
+ "transformer_list", "auto"
90
+ ),
91
+ transformer_max_depth=self.spec.model_kwargs.get(
92
+ "transformer_max_depth", 6
93
+ ),
94
+ models_mode=self.spec.model_kwargs.get("models_mode", "random"),
95
+ num_validations=self.spec.model_kwargs.get(
96
+ "num_validations", "auto"
97
+ ),
98
+ models_to_validate=self.spec.model_kwargs.get(
99
+ "models_to_validate", AUTOTS_MODELS_TO_VALIDATE
100
+ ),
101
+ max_per_model_class=self.spec.model_kwargs.get(
102
+ "max_per_model_class", None
103
+ ),
104
+ validation_method=self.spec.model_kwargs.get(
105
+ "validation_method", "backwards"
106
+ ),
107
+ min_allowed_train_percent=self.spec.model_kwargs.get(
108
+ "min_allowed_train_percent", 0.5
109
+ ),
110
+ remove_leading_zeroes=self.spec.model_kwargs.get(
111
+ "remove_leading_zeroes", False
112
+ ),
113
+ prefill_na=self.spec.model_kwargs.get("prefill_na", None),
114
+ introduce_na=self.spec.model_kwargs.get("introduce_na", None),
115
+ preclean=self.spec.model_kwargs.get("preclean", None),
116
+ model_interrupt=self.spec.model_kwargs.get("model_interrupt", True),
117
+ generation_timeout=self.spec.model_kwargs.get(
118
+ "generation_timeout", None
119
+ ),
120
+ current_model_file=self.spec.model_kwargs.get(
121
+ "current_model_file", None
122
+ ),
123
+ verbose=-1 if logger.level > 40 else 1,
124
+ n_jobs=self.spec.model_kwargs.get("n_jobs", -1),
125
+ )
126
+
127
+ full_data_indexed = self.datasets.get_data_multi_indexed()
128
+
129
+ dates = full_data_indexed.index.get_level_values(0).unique().tolist()
130
+ train_idx = dates[: -self.spec.horizon]
131
+
132
+ df_train = full_data_indexed[
133
+ full_data_indexed.index.get_level_values(0).isin(train_idx)
134
+ ][[self.original_target_column]].reset_index()
135
+
136
+ # Future regressors need to be in wide format - (num_unique_dates x (num_unique_series x num_unique_cols))
137
+ additional_regressors = list(
138
+ set(full_data_indexed.columns) - {self.original_target_column}
190
139
  )
191
-
192
- self.model_parameters[s_id] = {
193
- "framework": SupportedModels.AutoTS,
194
- **params,
195
- }
140
+ if len(additional_regressors) > 1:
141
+ future_regressor = full_data_indexed.reset_index().pivot(
142
+ index=self.spec.datetime_column.name,
143
+ columns=ForecastOutputColumns.SERIES,
144
+ values=additional_regressors,
145
+ )
146
+ future_reg = future_regressor[: -self.spec.horizon]
147
+ regr_fcst = future_regressor[-self.spec.horizon :]
148
+ else:
149
+ future_reg = None
150
+ regr_fcst = None
151
+
152
+ for s_id in self.datasets.list_series_ids():
153
+ self.forecast_output.init_series_output(
154
+ series_id=s_id,
155
+ data_at_series=self.datasets.get_data_at_series(s_id),
156
+ )
157
+
158
+ if self.loaded_models is None:
159
+ model = model.fit(
160
+ df_train,
161
+ future_regressor=future_reg,
162
+ date_col=self.spec.datetime_column.name,
163
+ value_col=self.original_target_column,
164
+ id_col=ForecastOutputColumns.SERIES,
165
+ )
166
+ # Store the trained model and generate forecasts
167
+ self.models = copy.deepcopy(model)
168
+ else:
169
+ self.models = self.loaded_models
170
+
171
+ self.outputs = model.predict(future_regressor=regr_fcst)
172
+ logger.debug("===========Forecast Generated===========")
173
+
174
+ hist_df = model.back_forecast().forecast
175
+
176
+ params = vars(model).copy()
177
+ for param in [
178
+ "ens_copy",
179
+ "df_wide_numeric",
180
+ "future_regressor_train",
181
+ "initial_results",
182
+ "score_per_series",
183
+ "validation_results",
184
+ "validation_train_indexes",
185
+ "validation_test_indexes",
186
+ "validation_indexes",
187
+ "best_model",
188
+ ]:
189
+ if param in params:
190
+ params.pop(param)
191
+
192
+ for s_id in self.datasets.list_series_ids():
193
+ self.forecast_output.populate_series_output(
194
+ series_id=s_id,
195
+ fit_val=hist_df[s_id].values,
196
+ forecast_val=self.outputs.forecast[s_id].values,
197
+ upper_bound=self.outputs.upper_forecast[s_id].values,
198
+ lower_bound=self.outputs.lower_forecast[s_id].values,
199
+ )
200
+
201
+ self.model_parameters[s_id] = {
202
+ "framework": SupportedModels.AutoTS,
203
+ **params,
204
+ }
205
+
206
+ except Exception as e:
207
+ for s_id in self.datasets.list_series_ids():
208
+ self.errors_dict[s_id] = {
209
+ "model_name": self.spec.model,
210
+ "error": str(e),
211
+ }
196
212
 
197
213
  logger.debug("===========Done===========")
198
214
 
@@ -204,7 +220,7 @@ class AutoTSOperatorModel(ForecastOperatorBaseModel):
204
220
 
205
221
  Returns:
206
222
  tuple: A tuple containing the following elements:
207
- - model_description (dp.Text): A text object containing the description of the AutoTS model.
223
+ - model_description (rc.Text): A text object containing the description of the AutoTS model.
208
224
  - other_sections (list): A list of sections to be included in the report.
209
225
  - forecast_col_name (str): The name of the forecast column.
210
226
  - train_metrics (bool): A boolean indicating whether to include train metrics.
@@ -212,36 +228,48 @@ class AutoTSOperatorModel(ForecastOperatorBaseModel):
212
228
  - ds_forecast_col (pd.Index): A pandas Index containing the forecast column values.
213
229
  - ci_col_names (list): A list of column names for confidence intervals.
214
230
  """
215
- import datapane as dp
231
+ import report_creator as rc
216
232
 
217
- # Section 1: Forecast Overview
218
- sec1_text = dp.Text(
219
- "## Forecast Overview \n"
220
- "These plots show your forecast in the context of historical data."
221
- )
222
- sec_1 = _select_plot_list(
223
- lambda s_id: self.outputs.plot(self.models.df_wide_numeric, series=s_id),
224
- self.datasets.list_series_ids(),
225
- )
233
+ all_sections = []
234
+ if self.models:
235
+ # Section 1: Forecast Overview
226
236
 
227
- # Section 2: AutoTS Model Parameters
228
- sec2_text = dp.Text(f"## AutoTS Model Parameters")
229
- try:
230
- sec2 = dp.Code(
231
- code=yaml.dump(list(self.models.best_model.T.to_dict().values())[0]),
232
- language="yaml",
237
+ sec_1_plots = _select_plot_list(
238
+ lambda s_id: self.outputs.plot(
239
+ self.models.df_wide_numeric, series=s_id
240
+ ),
241
+ self.datasets.list_series_ids(),
242
+ )
243
+ section_1 = rc.Block(
244
+ rc.Heading("Forecast Overview", level=2),
245
+ rc.Text(
246
+ "These plots show your forecast in the context of historical data."
247
+ ),
248
+ sec_1_plots,
233
249
  )
234
250
 
235
- except KeyError as ke:
236
- logger.warn(f"Issue generating Model Parameters Table Section. Skipping")
237
- sec2 = dp.Text(f"Error generating model parameters.")
238
- all_sections = [sec1_text, sec_1, sec2_text, sec2]
251
+ # Section 2: AutoTS Model Parameters
252
+ sec2_text = rc.Heading("AutoTS Model Parameters", level=2)
253
+ try:
254
+ sec2 = rc.Yaml(
255
+ yaml.dump(list(self.models.best_model.T.to_dict().values())[0]),
256
+ )
257
+
258
+ except KeyError as ke:
259
+ logger.warn(
260
+ f"Issue generating Model Parameters Table Section. Skipping"
261
+ )
262
+ sec2 = rc.Text("Error generating model parameters.")
263
+
264
+ section_2 = rc.Block(sec2_text, sec2)
265
+
266
+ all_sections = [sec_1_plots, section_2]
239
267
 
240
268
  if self.spec.generate_explanations:
241
269
  logger.warn(f"Explanations not yet supported for the AutoTS Module")
242
270
 
243
271
  # Model Description
244
- model_description = dp.Text(
272
+ model_description = rc.Text(
245
273
  "AutoTS is a time series package for Python designed for rapidly deploying high-accuracy forecasts at scale. "
246
274
  "In 2023, AutoTS has won in the M6 forecasting competition, "
247
275
  "delivering the highest performance investment decisions across 12 months of stock market forecasting."
@@ -266,9 +294,15 @@ class AutoTSOperatorModel(ForecastOperatorBaseModel):
266
294
  r2 -4.60E-06
267
295
  Explained Variance 0.002177087
268
296
  """
269
- mapes = pd.DataFrame(self.models.best_model_per_series_mape()).T
270
- scores = pd.DataFrame(
271
- self.models.best_model_per_series_score(), columns=["AutoTS Score"]
272
- ).T
273
- df = pd.concat([mapes, scores])
297
+ df = pd.DataFrame()
298
+ try:
299
+ mapes = pd.DataFrame(self.models.best_model_per_series_mape()).T
300
+ scores = pd.DataFrame(
301
+ self.models.best_model_per_series_score(), columns=["AutoTS Score"]
302
+ ).T
303
+ df = pd.concat([mapes, scores])
304
+ except Exception as e:
305
+ logger.debug(f"Failed to generate training metrics")
306
+ logger.debug(f"Received Error Statement: {e}")
307
+
274
308
  return df