oracle-ads 2.10.0__py3-none-any.whl → 2.11.0__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.
- ads/aqua/__init__.py +12 -0
- ads/aqua/base.py +324 -0
- ads/aqua/cli.py +19 -0
- ads/aqua/config/deployment_config_defaults.json +9 -0
- ads/aqua/config/resource_limit_names.json +7 -0
- ads/aqua/constants.py +45 -0
- ads/aqua/data.py +40 -0
- ads/aqua/decorator.py +101 -0
- ads/aqua/deployment.py +643 -0
- ads/aqua/dummy_data/icon.txt +1 -0
- ads/aqua/dummy_data/oci_model_deployments.json +56 -0
- ads/aqua/dummy_data/oci_models.json +1 -0
- ads/aqua/dummy_data/readme.md +26 -0
- ads/aqua/evaluation.py +1751 -0
- ads/aqua/exception.py +82 -0
- ads/aqua/extension/__init__.py +40 -0
- ads/aqua/extension/base_handler.py +138 -0
- ads/aqua/extension/common_handler.py +21 -0
- ads/aqua/extension/deployment_handler.py +202 -0
- ads/aqua/extension/evaluation_handler.py +135 -0
- ads/aqua/extension/finetune_handler.py +66 -0
- ads/aqua/extension/model_handler.py +59 -0
- ads/aqua/extension/ui_handler.py +201 -0
- ads/aqua/extension/utils.py +23 -0
- ads/aqua/finetune.py +579 -0
- ads/aqua/job.py +29 -0
- ads/aqua/model.py +819 -0
- ads/aqua/training/__init__.py +4 -0
- ads/aqua/training/exceptions.py +459 -0
- ads/aqua/ui.py +453 -0
- ads/aqua/utils.py +715 -0
- ads/cli.py +37 -6
- ads/common/auth.py +7 -0
- ads/common/decorator/__init__.py +7 -3
- ads/common/decorator/require_nonempty_arg.py +65 -0
- ads/common/object_storage_details.py +166 -7
- ads/common/oci_client.py +18 -1
- ads/common/oci_logging.py +2 -2
- ads/common/oci_mixin.py +4 -5
- ads/common/serializer.py +34 -5
- ads/common/utils.py +75 -10
- ads/config.py +40 -1
- ads/dataset/correlation_plot.py +10 -12
- ads/jobs/ads_job.py +43 -25
- ads/jobs/builders/infrastructure/base.py +4 -2
- ads/jobs/builders/infrastructure/dsc_job.py +49 -39
- ads/jobs/builders/runtimes/base.py +71 -1
- ads/jobs/builders/runtimes/container_runtime.py +4 -4
- ads/jobs/builders/runtimes/pytorch_runtime.py +10 -63
- ads/jobs/templates/driver_pytorch.py +27 -10
- ads/model/artifact_downloader.py +84 -14
- ads/model/artifact_uploader.py +25 -23
- ads/model/datascience_model.py +388 -38
- ads/model/deployment/model_deployment.py +10 -2
- ads/model/generic_model.py +8 -0
- ads/model/model_file_description_schema.json +68 -0
- ads/model/model_metadata.py +1 -1
- ads/model/service/oci_datascience_model.py +34 -5
- ads/opctl/config/merger.py +2 -2
- ads/opctl/operator/__init__.py +3 -1
- ads/opctl/operator/cli.py +7 -1
- ads/opctl/operator/cmd.py +3 -3
- ads/opctl/operator/common/errors.py +2 -1
- ads/opctl/operator/common/operator_config.py +22 -3
- ads/opctl/operator/common/utils.py +16 -0
- ads/opctl/operator/lowcode/anomaly/MLoperator +15 -0
- ads/opctl/operator/lowcode/anomaly/README.md +209 -0
- ads/opctl/operator/lowcode/anomaly/__init__.py +5 -0
- ads/opctl/operator/lowcode/anomaly/__main__.py +104 -0
- ads/opctl/operator/lowcode/anomaly/cmd.py +35 -0
- ads/opctl/operator/lowcode/anomaly/const.py +88 -0
- ads/opctl/operator/lowcode/anomaly/environment.yaml +12 -0
- ads/opctl/operator/lowcode/anomaly/model/__init__.py +5 -0
- ads/opctl/operator/lowcode/anomaly/model/anomaly_dataset.py +147 -0
- ads/opctl/operator/lowcode/anomaly/model/automlx.py +89 -0
- ads/opctl/operator/lowcode/anomaly/model/autots.py +103 -0
- ads/opctl/operator/lowcode/anomaly/model/base_model.py +354 -0
- ads/opctl/operator/lowcode/anomaly/model/factory.py +67 -0
- ads/opctl/operator/lowcode/anomaly/model/tods.py +119 -0
- ads/opctl/operator/lowcode/anomaly/operator_config.py +105 -0
- ads/opctl/operator/lowcode/anomaly/schema.yaml +359 -0
- ads/opctl/operator/lowcode/anomaly/utils.py +81 -0
- ads/opctl/operator/lowcode/common/__init__.py +5 -0
- ads/opctl/operator/lowcode/common/const.py +10 -0
- ads/opctl/operator/lowcode/common/data.py +96 -0
- ads/opctl/operator/lowcode/common/errors.py +41 -0
- ads/opctl/operator/lowcode/common/transformations.py +191 -0
- ads/opctl/operator/lowcode/common/utils.py +250 -0
- ads/opctl/operator/lowcode/forecast/README.md +3 -2
- ads/opctl/operator/lowcode/forecast/__main__.py +18 -2
- ads/opctl/operator/lowcode/forecast/cmd.py +8 -7
- ads/opctl/operator/lowcode/forecast/const.py +17 -1
- ads/opctl/operator/lowcode/forecast/environment.yaml +3 -2
- ads/opctl/operator/lowcode/forecast/model/arima.py +106 -117
- ads/opctl/operator/lowcode/forecast/model/automlx.py +204 -180
- ads/opctl/operator/lowcode/forecast/model/autots.py +144 -253
- ads/opctl/operator/lowcode/forecast/model/base_model.py +326 -259
- ads/opctl/operator/lowcode/forecast/model/forecast_datasets.py +325 -176
- ads/opctl/operator/lowcode/forecast/model/neuralprophet.py +293 -237
- ads/opctl/operator/lowcode/forecast/model/prophet.py +191 -208
- ads/opctl/operator/lowcode/forecast/operator_config.py +24 -33
- ads/opctl/operator/lowcode/forecast/schema.yaml +116 -29
- ads/opctl/operator/lowcode/forecast/utils.py +186 -356
- ads/opctl/operator/lowcode/pii/model/guardrails.py +18 -15
- ads/opctl/operator/lowcode/pii/model/report.py +7 -7
- ads/opctl/operator/lowcode/pii/operator_config.py +1 -8
- ads/opctl/operator/lowcode/pii/utils.py +0 -82
- ads/opctl/operator/runtime/runtime.py +3 -2
- ads/telemetry/base.py +62 -0
- ads/telemetry/client.py +105 -0
- ads/telemetry/telemetry.py +6 -3
- {oracle_ads-2.10.0.dist-info → oracle_ads-2.11.0.dist-info}/METADATA +44 -7
- {oracle_ads-2.10.0.dist-info → oracle_ads-2.11.0.dist-info}/RECORD +116 -59
- ads/opctl/operator/lowcode/forecast/model/transformations.py +0 -125
- {oracle_ads-2.10.0.dist-info → oracle_ads-2.11.0.dist-info}/LICENSE.txt +0 -0
- {oracle_ads-2.10.0.dist-info → oracle_ads-2.11.0.dist-info}/WHEEL +0 -0
- {oracle_ads-2.10.0.dist-info → oracle_ads-2.11.0.dist-info}/entry_points.txt +0 -0
@@ -7,15 +7,17 @@
|
|
7
7
|
import pandas as pd
|
8
8
|
import numpy as np
|
9
9
|
import pmdarima as pm
|
10
|
+
from joblib import Parallel, delayed
|
10
11
|
|
11
12
|
from ads.opctl import logger
|
12
13
|
|
13
|
-
from
|
14
|
+
from ads.opctl.operator.lowcode.forecast.utils import _label_encode_dataframe
|
15
|
+
from ads.opctl.operator.lowcode.common.utils import seconds_to_datetime
|
14
16
|
from .base_model import ForecastOperatorBaseModel
|
15
17
|
from ..operator_config import ForecastOperatorConfig
|
16
18
|
import traceback
|
17
19
|
from .forecast_datasets import ForecastDatasets, ForecastOutput
|
18
|
-
from ..const import ForecastOutputColumns
|
20
|
+
from ..const import ForecastOutputColumns, SupportedModels
|
19
21
|
|
20
22
|
|
21
23
|
class ArimaOperatorModel(ForecastOperatorBaseModel):
|
@@ -25,13 +27,10 @@ class ArimaOperatorModel(ForecastOperatorBaseModel):
|
|
25
27
|
super().__init__(config, datasets=datasets)
|
26
28
|
self.global_explanation = {}
|
27
29
|
self.local_explanation = {}
|
28
|
-
self.train_metrics = True
|
29
30
|
self.formatted_global_explanation = None
|
30
31
|
self.formatted_local_explanation = None
|
31
32
|
|
32
|
-
def
|
33
|
-
full_data_dict = self.datasets.full_data_dict
|
34
|
-
|
33
|
+
def set_kwargs(self):
|
35
34
|
# Extract the Confidence Interval Width and convert to arima's equivalent - alpha
|
36
35
|
if self.spec.confidence_interval_width is None:
|
37
36
|
self.spec.confidence_interval_width = 1 - self.spec.model_kwargs.get(
|
@@ -41,74 +40,57 @@ class ArimaOperatorModel(ForecastOperatorBaseModel):
|
|
41
40
|
model_kwargs["alpha"] = 1 - self.spec.confidence_interval_width
|
42
41
|
if "error_action" not in model_kwargs.keys():
|
43
42
|
model_kwargs["error_action"] = "ignore"
|
43
|
+
return model_kwargs
|
44
44
|
|
45
|
-
|
46
|
-
self.
|
47
|
-
|
48
|
-
|
45
|
+
def preprocess(self, data, series_id): # TODO: re-use self.le for explanations
|
46
|
+
self.le[series_id], df_encoded = _label_encode_dataframe(
|
47
|
+
data,
|
48
|
+
no_encode={self.spec.datetime_column.name, self.original_target_column},
|
49
49
|
)
|
50
|
+
return df_encoded.set_index(self.spec.datetime_column.name)
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
fitted_values = dict()
|
54
|
-
actual_values = dict()
|
55
|
-
dt_columns = dict()
|
56
|
-
|
57
|
-
for i, (target, df) in enumerate(full_data_dict.items()):
|
58
|
-
# format the dataframe for this target. Dropping NA on target[df] will remove all future data
|
59
|
-
le, df_encoded = utils._label_encode_dataframe(
|
60
|
-
df, no_encode={self.spec.datetime_column.name, target}
|
61
|
-
)
|
52
|
+
def _train_model(self, i, s_id, df, model_kwargs):
|
53
|
+
"""Trains the ARIMA model for a given series of the dataset.
|
62
54
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
55
|
+
Parameters
|
56
|
+
----------
|
57
|
+
i: int
|
58
|
+
The index of the series
|
59
|
+
s_id: str
|
60
|
+
The name of the series
|
61
|
+
df: pd.DataFrame
|
62
|
+
The dataframe containing the target data
|
63
|
+
"""
|
64
|
+
try:
|
65
|
+
target = self.original_target_column
|
66
|
+
self.forecast_output.init_series_output(series_id=s_id, data_at_series=df)
|
69
67
|
|
70
|
-
#
|
71
|
-
|
72
|
-
|
73
|
-
self.spec.datetime_column.name,
|
74
|
-
}
|
75
|
-
logger.debug(
|
76
|
-
f"Additional Regressors Detected {list(additional_regressors)}"
|
77
|
-
)
|
68
|
+
# format the dataframe for this target. Dropping NA on target[df] will remove all future data
|
69
|
+
data = self.preprocess(df, s_id)
|
70
|
+
data_i = self.drop_horizon(data)
|
78
71
|
|
79
72
|
# Split data into X and y for arima tune method
|
80
73
|
y = data_i[target]
|
81
|
-
X_in = None
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
model = pm.auto_arima(y=y, X=X_in, **self.spec.model_kwargs)
|
87
|
-
|
88
|
-
fitted_values[target] = model.predict_in_sample(X=X_in)
|
89
|
-
actual_values[target] = y
|
90
|
-
actual_values[target].index = pd.to_datetime(y.index)
|
91
|
-
|
92
|
-
# Build future dataframe
|
93
|
-
start_date = y.index.values[-1]
|
94
|
-
n_periods = self.spec.horizon
|
95
|
-
if len(additional_regressors):
|
96
|
-
X = df_clean[df_clean[target].isnull()].drop(target, axis=1)
|
74
|
+
X_in = data_i.drop(target, axis=1) if len(data_i.columns) > 1 else None
|
75
|
+
X_pred = self.get_horizon(data).drop(target, axis=1)
|
76
|
+
|
77
|
+
if self.loaded_models is not None:
|
78
|
+
model = self.loaded_models[s_id]
|
97
79
|
else:
|
98
|
-
|
99
|
-
|
100
|
-
|
80
|
+
# Build and fit model
|
81
|
+
model = pm.auto_arima(y=y, X=X_in, **model_kwargs)
|
82
|
+
|
83
|
+
fitted_values = model.predict_in_sample(X=X_in).values
|
101
84
|
|
102
85
|
# Predict and format forecast
|
103
86
|
yhat, conf_int = model.predict(
|
104
|
-
n_periods=
|
105
|
-
X=
|
87
|
+
n_periods=self.spec.horizon,
|
88
|
+
X=X_pred,
|
106
89
|
return_conf_int=True,
|
107
90
|
alpha=model_kwargs["alpha"],
|
108
91
|
)
|
109
92
|
yhat_clean = pd.DataFrame(yhat, index=yhat.index, columns=["yhat"])
|
110
93
|
|
111
|
-
dt_columns[target] = df_encoded[self.spec.datetime_column.name]
|
112
94
|
conf_int_clean = pd.DataFrame(
|
113
95
|
conf_int, index=yhat.index, columns=["yhat_lower", "yhat_upper"]
|
114
96
|
)
|
@@ -116,43 +98,47 @@ class ArimaOperatorModel(ForecastOperatorBaseModel):
|
|
116
98
|
logger.debug(f"-----------------Model {i}----------------------")
|
117
99
|
logger.debug(forecast[["yhat", "yhat_lower", "yhat_upper"]].tail())
|
118
100
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
self.models = models
|
127
|
-
|
128
|
-
logger.debug("===========Done===========")
|
129
|
-
|
130
|
-
# Merge the outputs from each model into 1 df with all outputs by target and category
|
131
|
-
col = self.original_target_column
|
132
|
-
output_col = pd.DataFrame()
|
133
|
-
yhat_upper_name = ForecastOutputColumns.UPPER_BOUND
|
134
|
-
yhat_lower_name = ForecastOutputColumns.LOWER_BOUND
|
135
|
-
for cat in self.categories:
|
136
|
-
output_i = pd.DataFrame()
|
137
|
-
output_i["Date"] = dt_columns[f"{col}_{cat}"]
|
138
|
-
output_i["Series"] = cat
|
139
|
-
output_i = output_i.set_index("Date")
|
140
|
-
|
141
|
-
output_i["input_value"] = actual_values[f"{col}_{cat}"]
|
142
|
-
output_i["fitted_value"] = fitted_values[f"{col}_{cat}"]
|
143
|
-
output_i["forecast_value"] = outputs[f"{col}_{cat}"]["yhat"]
|
144
|
-
output_i[yhat_upper_name] = outputs[f"{col}_{cat}"]["yhat_upper"]
|
145
|
-
output_i[yhat_lower_name] = outputs[f"{col}_{cat}"]["yhat_lower"]
|
146
|
-
|
147
|
-
output_i = output_i.reset_index(drop=False)
|
148
|
-
output_col = pd.concat([output_col, output_i])
|
149
|
-
self.forecast_output.add_category(
|
150
|
-
category=cat, target_category_column=f"{col}_{cat}", forecast=output_i
|
101
|
+
self.forecast_output.populate_series_output(
|
102
|
+
series_id=s_id,
|
103
|
+
fit_val=fitted_values,
|
104
|
+
forecast_val=self.get_horizon(forecast["yhat"]).values,
|
105
|
+
upper_bound=self.get_horizon(forecast["yhat_upper"]).values,
|
106
|
+
lower_bound=self.get_horizon(forecast["yhat_lower"]).values,
|
151
107
|
)
|
152
108
|
|
153
|
-
|
109
|
+
self.models[s_id] = model
|
110
|
+
|
111
|
+
params = vars(model).copy()
|
112
|
+
for param in ["arima_res_", "endog_index_"]:
|
113
|
+
if param in params:
|
114
|
+
params.pop(param)
|
115
|
+
self.model_parameters[s_id] = {
|
116
|
+
"framework": SupportedModels.Arima,
|
117
|
+
**params,
|
118
|
+
}
|
154
119
|
|
155
|
-
|
120
|
+
logger.debug("===========Done===========")
|
121
|
+
except Exception as e:
|
122
|
+
self.errors_dict[s_id] = {"model_name": self.spec.model, "error": str(e)}
|
123
|
+
|
124
|
+
def _build_model(self) -> pd.DataFrame:
|
125
|
+
full_data_dict = self.datasets.get_data_by_series()
|
126
|
+
self.models = dict()
|
127
|
+
self.additional_regressors = self.datasets.get_additional_data_column_names()
|
128
|
+
model_kwargs = self.set_kwargs()
|
129
|
+
self.forecast_output = ForecastOutput(
|
130
|
+
confidence_interval_width=self.spec.confidence_interval_width,
|
131
|
+
horizon=self.spec.horizon,
|
132
|
+
target_column=self.original_target_column,
|
133
|
+
dt_column=self.spec.datetime_column.name,
|
134
|
+
)
|
135
|
+
|
136
|
+
Parallel(n_jobs=-1, require="sharedmem")(
|
137
|
+
delayed(self._train_model)(i, s_id, df, model_kwargs.copy())
|
138
|
+
for (i, (s_id, df)) in enumerate(full_data_dict.items())
|
139
|
+
)
|
140
|
+
|
141
|
+
return self.forecast_output.get_forecast_long()
|
156
142
|
|
157
143
|
def _generate_report(self):
|
158
144
|
"""The method that needs to be implemented on the particular model level."""
|
@@ -160,8 +146,11 @@ class ArimaOperatorModel(ForecastOperatorBaseModel):
|
|
160
146
|
|
161
147
|
sec5_text = dp.Text(f"## ARIMA Model Parameters")
|
162
148
|
blocks = [
|
163
|
-
dp.HTML(
|
164
|
-
|
149
|
+
dp.HTML(
|
150
|
+
m.summary().as_html(),
|
151
|
+
label=s_id,
|
152
|
+
)
|
153
|
+
for i, (s_id, m) in enumerate(self.models.items())
|
165
154
|
]
|
166
155
|
sec5 = dp.Select(blocks=blocks) if len(blocks) > 1 else blocks[0]
|
167
156
|
all_sections = [sec5_text, sec5]
|
@@ -169,11 +158,7 @@ class ArimaOperatorModel(ForecastOperatorBaseModel):
|
|
169
158
|
if self.spec.generate_explanations:
|
170
159
|
try:
|
171
160
|
# If the key is present, call the "explain_model" method
|
172
|
-
self.explain_model(
|
173
|
-
datetime_col_name=self.spec.datetime_column.name,
|
174
|
-
explain_predict_fn=self._custom_predict_arima,
|
175
|
-
)
|
176
|
-
|
161
|
+
self.explain_model()
|
177
162
|
# Create a markdown text block for the global explanation section
|
178
163
|
global_explanation_text = dp.Text(
|
179
164
|
f"## Global Explanation of Models \n "
|
@@ -186,6 +171,12 @@ class ArimaOperatorModel(ForecastOperatorBaseModel):
|
|
186
171
|
self.formatted_global_explanation = (
|
187
172
|
global_explanation_df / global_explanation_df.sum(axis=0) * 100
|
188
173
|
)
|
174
|
+
self.formatted_global_explanation = (
|
175
|
+
self.formatted_global_explanation.rename(
|
176
|
+
{self.spec.datetime_column.name: ForecastOutputColumns.DATE},
|
177
|
+
axis=1,
|
178
|
+
)
|
179
|
+
)
|
189
180
|
|
190
181
|
# Create a markdown section for the global explainability
|
191
182
|
global_explanation_section = dp.Blocks(
|
@@ -238,23 +229,21 @@ class ArimaOperatorModel(ForecastOperatorBaseModel):
|
|
238
229
|
other_sections,
|
239
230
|
)
|
240
231
|
|
241
|
-
def
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
# Use the ARIMA model to predict the values
|
258
|
-
predictions = self.models[series_index].predict(X=data, n_periods=len(data))
|
232
|
+
def get_explain_predict_fn(self, series_id):
|
233
|
+
def _custom_predict(
|
234
|
+
data,
|
235
|
+
model=self.models[series_id],
|
236
|
+
dt_column_name=self.datasets._datetime_column_name,
|
237
|
+
target_col=self.original_target_column,
|
238
|
+
):
|
239
|
+
"""
|
240
|
+
data: ForecastDatasets.get_data_at_series(s_id)
|
241
|
+
"""
|
242
|
+
data = data.drop([target_col], axis=1)
|
243
|
+
data[dt_column_name] = seconds_to_datetime(
|
244
|
+
data[dt_column_name], dt_format=self.spec.datetime_column.format
|
245
|
+
)
|
246
|
+
data = self.preprocess(data, series_id)
|
247
|
+
return model.predict(X=data, n_periods=len(data))
|
259
248
|
|
260
|
-
return
|
249
|
+
return _custom_predict
|