openstef 3.4.11__py3-none-any.whl → 3.4.13__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.
- openstef/data_classes/prediction_job.py +0 -1
- openstef/enums.py +0 -1
- openstef/feature_engineering/apply_features.py +0 -6
- openstef/feature_engineering/feature_applicator.py +1 -5
- openstef/model/model_creator.py +0 -27
- openstef/model/objective.py +3 -50
- openstef/model/objective_creator.py +0 -2
- openstef/pipeline/optimize_hyperparameters.py +1 -13
- openstef/pipeline/train_create_forecast_backtest.py +1 -1
- openstef/pipeline/train_model.py +1 -5
- {openstef-3.4.11.dist-info → openstef-3.4.13.dist-info}/METADATA +18 -18
- {openstef-3.4.11.dist-info → openstef-3.4.13.dist-info}/RECORD +15 -17
- {openstef-3.4.11.dist-info → openstef-3.4.13.dist-info}/WHEEL +1 -1
- openstef/feature_engineering/historic_features.py +0 -40
- openstef/model/regressors/proloaf.py +0 -281
- {openstef-3.4.11.dist-info → openstef-3.4.13.dist-info}/LICENSE +0 -0
- {openstef-3.4.11.dist-info → openstef-3.4.13.dist-info}/top_level.txt +0 -0
openstef/enums.py
CHANGED
@@ -14,9 +14,6 @@ Examples of features that are added:
|
|
14
14
|
import pandas as pd
|
15
15
|
|
16
16
|
from openstef.data_classes.prediction_job import PredictionJobDataClass
|
17
|
-
from openstef.feature_engineering.historic_features import (
|
18
|
-
add_historic_load_as_a_feature,
|
19
|
-
)
|
20
17
|
from openstef.feature_engineering.holiday_features import (
|
21
18
|
generate_holiday_feature_functions,
|
22
19
|
)
|
@@ -69,9 +66,6 @@ def apply_features(
|
|
69
66
|
np.random.uniform(0.7,1.7, 200)))
|
70
67
|
|
71
68
|
"""
|
72
|
-
# Add if needed the proloaf feature (historic_load)
|
73
|
-
data = add_historic_load_as_a_feature(data, pj)
|
74
|
-
|
75
69
|
# Get lag feature functions
|
76
70
|
feature_functions = generate_lag_feature_functions(feature_names, horizon)
|
77
71
|
|
@@ -149,11 +149,7 @@ class TrainFeatureApplicator(AbstractFeatureApplicator):
|
|
149
149
|
|
150
150
|
# NOTE this is required since apply_features could add additional features
|
151
151
|
if self.feature_names is not None:
|
152
|
-
|
153
|
-
if pj.get("model") == "proloaf":
|
154
|
-
features = self.feature_names + ["historic_load"] + ["horizon"]
|
155
|
-
else:
|
156
|
-
features = self.feature_names + ["horizon"]
|
152
|
+
features = self.feature_names + ["horizon"]
|
157
153
|
result = remove_non_requested_feature_columns(result, features)
|
158
154
|
|
159
155
|
# Sort all features except for the (first) load and (last) horizon columns
|
openstef/model/model_creator.py
CHANGED
@@ -15,11 +15,6 @@ from openstef.model.regressors.xgb_quantile import XGBQuantileOpenstfRegressor
|
|
15
15
|
from openstef.model.regressors.arima import ARIMAOpenstfRegressor
|
16
16
|
|
17
17
|
logger = structlog.get_logger(__name__)
|
18
|
-
try:
|
19
|
-
from openstef.model.regressors.proloaf import OpenstfProloafRegressor
|
20
|
-
except ImportError:
|
21
|
-
logger.info("Proloaf not available, setting constructor to None")
|
22
|
-
OpenstfProloafRegressor = None
|
23
18
|
|
24
19
|
valid_model_kwargs = {
|
25
20
|
MLModelType.XGB: [
|
@@ -84,27 +79,6 @@ valid_model_kwargs = {
|
|
84
79
|
"max_depth",
|
85
80
|
"early_stopping_rounds",
|
86
81
|
],
|
87
|
-
MLModelType.ProLoaf: [
|
88
|
-
"relu_leak",
|
89
|
-
"encoder_features",
|
90
|
-
"decoder_features",
|
91
|
-
"core_layers",
|
92
|
-
"rel_linear_hidden_size",
|
93
|
-
"rel_core_hidden_size",
|
94
|
-
"dropout_fc",
|
95
|
-
"dropout_core",
|
96
|
-
"training_metric",
|
97
|
-
"metric_options",
|
98
|
-
"optimizer_name",
|
99
|
-
"early_stopping_patience",
|
100
|
-
"early_stopping_margin",
|
101
|
-
"learning_rate",
|
102
|
-
"max_epochs",
|
103
|
-
"device",
|
104
|
-
"batch_size",
|
105
|
-
"history_horizon",
|
106
|
-
"horizon_minutes",
|
107
|
-
],
|
108
82
|
MLModelType.LINEAR: [
|
109
83
|
"missing_values",
|
110
84
|
"imputation_strategy",
|
@@ -127,7 +101,6 @@ class ModelCreator:
|
|
127
101
|
MLModelType.XGB: XGBOpenstfRegressor,
|
128
102
|
MLModelType.LGB: LGBMOpenstfRegressor,
|
129
103
|
MLModelType.XGB_QUANTILE: XGBQuantileOpenstfRegressor,
|
130
|
-
MLModelType.ProLoaf: OpenstfProloafRegressor,
|
131
104
|
MLModelType.LINEAR: LinearOpenstfRegressor,
|
132
105
|
MLModelType.ARIMA: ARIMAOpenstfRegressor,
|
133
106
|
}
|
openstef/model/objective.py
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: MPL-2.0
|
4
4
|
import copy
|
5
|
-
from datetime import datetime
|
5
|
+
from datetime import datetime, timezone
|
6
6
|
from typing import Any, Callable, Optional
|
7
7
|
|
8
8
|
import optuna
|
@@ -59,7 +59,7 @@ class RegressorObjective:
|
|
59
59
|
self.validation_data = None
|
60
60
|
self.test_data = None
|
61
61
|
self.model = model
|
62
|
-
self.start_time = datetime.
|
62
|
+
self.start_time = datetime.now(timezone.utc)
|
63
63
|
self.test_fraction = test_fraction
|
64
64
|
self.validation_fraction = validation_fraction
|
65
65
|
self.eval_metric = eval_metric
|
@@ -94,7 +94,7 @@ class RegressorObjective:
|
|
94
94
|
split_args = self.split_args
|
95
95
|
if split_args is None:
|
96
96
|
split_args = {
|
97
|
-
"stratification_min_max":
|
97
|
+
"stratification_min_max": True,
|
98
98
|
"back_test": True,
|
99
99
|
}
|
100
100
|
(
|
@@ -349,53 +349,6 @@ class XGBQuantileRegressorObjective(RegressorObjective):
|
|
349
349
|
)
|
350
350
|
|
351
351
|
|
352
|
-
class ProLoafRegressorObjective(RegressorObjective):
|
353
|
-
def __init__(self, *args, **kwargs):
|
354
|
-
super().__init__(*args, **kwargs)
|
355
|
-
self.model_type = MLModelType.ProLoaf
|
356
|
-
|
357
|
-
def get_params(self, trial: optuna.trial.FrozenTrial) -> dict:
|
358
|
-
"""Get parameters for ProLoaf Regressor Objective with objective specific parameters.
|
359
|
-
|
360
|
-
Args: trial
|
361
|
-
|
362
|
-
Returns:
|
363
|
-
Dictionary with hyperparameter name as key and hyperparamer value as value.
|
364
|
-
|
365
|
-
"""
|
366
|
-
# Filtered default parameters
|
367
|
-
model_params = super().get_params(trial)
|
368
|
-
|
369
|
-
# ProLoaf specific parameters
|
370
|
-
params = {
|
371
|
-
# TODO: look into optimizing this pipeline for proloaf
|
372
|
-
# "relu_leak": trial.suggest_float("relu_leak", 0.1, 1.0),
|
373
|
-
# "core_layers": trial.suggest_int("core_layers", 1, 3),
|
374
|
-
# "rel_linear_hidden_size": trial.suggest_float(
|
375
|
-
# "rel_linear_hidden_size", 0.1, 1
|
376
|
-
# ),
|
377
|
-
# "rel_core_hidden_size": trial.suggest_float("rel_core_hidden_size", 0.1, 1),
|
378
|
-
# "dropout_fc": trial.suggest_float("dropout_fc", 0.1, 0.9),
|
379
|
-
# "dropout_core": trial.suggest_float("dropout_core", 0.1, 0.9),
|
380
|
-
# "early_stopping_patience": trial.suggest_int(
|
381
|
-
# "early_stopping_patience", 5, 10
|
382
|
-
# ),
|
383
|
-
# "early_stopping_margin": trial.suggest_float(
|
384
|
-
# "early_stopping_margin", 0.1, 0.9
|
385
|
-
# ),
|
386
|
-
"max_epochs": trial.suggest_int(
|
387
|
-
"max_epochs", 1, 1
|
388
|
-
), # TODO: change after having availability to gpu resource
|
389
|
-
"batch_size": trial.suggest_int("batch_size", 1, 24),
|
390
|
-
}
|
391
|
-
return {**model_params, **params}
|
392
|
-
|
393
|
-
def get_pruning_callback(self, trial: optuna.trial.FrozenTrial):
|
394
|
-
return optuna.integration.PyTorchLightningPruningCallback(
|
395
|
-
trial, monitor="val_loss"
|
396
|
-
)
|
397
|
-
|
398
|
-
|
399
352
|
class LinearRegressorObjective(RegressorObjective):
|
400
353
|
def __init__(self, *args, **kwargs):
|
401
354
|
super().__init__(*args, **kwargs)
|
@@ -8,7 +8,6 @@ from openstef.enums import MLModelType
|
|
8
8
|
from openstef.model.objective import (
|
9
9
|
LGBRegressorObjective,
|
10
10
|
LinearRegressorObjective,
|
11
|
-
ProLoafRegressorObjective,
|
12
11
|
RegressorObjective,
|
13
12
|
XGBQuantileRegressorObjective,
|
14
13
|
XGBRegressorObjective,
|
@@ -25,7 +24,6 @@ class ObjectiveCreator:
|
|
25
24
|
MLModelType.XGB: XGBRegressorObjective,
|
26
25
|
MLModelType.LGB: LGBRegressorObjective,
|
27
26
|
MLModelType.XGB_QUANTILE: XGBQuantileRegressorObjective,
|
28
|
-
MLModelType.ProLoaf: ProLoafRegressorObjective,
|
29
27
|
MLModelType.LINEAR: LinearRegressorObjective,
|
30
28
|
MLModelType.ARIMA: ARIMARegressorObjective,
|
31
29
|
}
|
@@ -175,18 +175,6 @@ def optimize_hyperparameters_pipeline_core(
|
|
175
175
|
horizons=horizons, feature_names=feature_names, feature_modules=feature_modules
|
176
176
|
).add_features(validated_data, pj=pj)
|
177
177
|
|
178
|
-
# Adds additional proloaf features to the input data, historic_load (equal to the load, first column)
|
179
|
-
if pj["model"] == "proloaf" and "historic_load" not in list(
|
180
|
-
validated_data_with_features.columns
|
181
|
-
):
|
182
|
-
validated_data_with_features[
|
183
|
-
"historic_load"
|
184
|
-
] = validated_data_with_features.iloc[:, 0]
|
185
|
-
# Make sure horizons is last column
|
186
|
-
temp_cols = validated_data_with_features.columns.tolist()
|
187
|
-
new_cols = temp_cols[:-2] + [temp_cols[-1]] + [temp_cols[-2]]
|
188
|
-
validated_data_with_features = validated_data_with_features[new_cols]
|
189
|
-
|
190
178
|
# Create objective (NOTE: this is a callable class)
|
191
179
|
objective = ObjectiveCreator.create_objective(model_type=pj["model"])
|
192
180
|
|
@@ -268,7 +256,7 @@ def optuna_optimization(
|
|
268
256
|
if pj.train_split_func is None:
|
269
257
|
split_func = split_data_train_validation_test
|
270
258
|
split_args = {
|
271
|
-
"stratification_min_max":
|
259
|
+
"stratification_min_max": True,
|
272
260
|
"back_test": True,
|
273
261
|
}
|
274
262
|
else:
|
@@ -59,7 +59,7 @@ def train_model_and_forecast_back_test(
|
|
59
59
|
"""
|
60
60
|
if pj.backtest_split_func is None:
|
61
61
|
backtest_split_func = backtest_split_default
|
62
|
-
backtest_split_args = {"stratification_min_max":
|
62
|
+
backtest_split_args = {"stratification_min_max": True}
|
63
63
|
else:
|
64
64
|
backtest_split_func, backtest_split_args = pj.backtest_split_func.load(
|
65
65
|
required_arguments=["data", "n_folds"]
|
openstef/pipeline/train_model.py
CHANGED
@@ -348,10 +348,6 @@ def train_pipeline_step_compute_features(
|
|
348
348
|
ValueError: when the horizon is a string and the corresponding column in not in the input data
|
349
349
|
|
350
350
|
"""
|
351
|
-
if pj["model"] == "proloaf":
|
352
|
-
# proloaf is only able to train with one horizon
|
353
|
-
horizons = [horizons[0]]
|
354
|
-
|
355
351
|
if input_data.empty:
|
356
352
|
raise InputDataInsufficientError("Input dataframe is empty")
|
357
353
|
elif "load" not in input_data.columns:
|
@@ -523,7 +519,7 @@ def train_pipeline_step_split_data(
|
|
523
519
|
if pj.train_split_func is None:
|
524
520
|
split_func = split_data_train_validation_test
|
525
521
|
split_args = {
|
526
|
-
"stratification_min_max":
|
522
|
+
"stratification_min_max": True,
|
527
523
|
"back_test": backtest,
|
528
524
|
}
|
529
525
|
else:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: openstef
|
3
|
-
Version: 3.4.
|
3
|
+
Version: 3.4.13
|
4
4
|
Summary: Open short term energy forecaster
|
5
5
|
Home-page: https://github.com/OpenSTEF/openstef
|
6
6
|
Author: Alliander N.V
|
@@ -22,6 +22,7 @@ Requires-Dist: matplotlib ~=3.7
|
|
22
22
|
Requires-Dist: mlflow ~=2.3
|
23
23
|
Requires-Dist: networkx ~=3.1
|
24
24
|
Requires-Dist: optuna ~=3.1
|
25
|
+
Requires-Dist: optuna-integration ~=3.6
|
25
26
|
Requires-Dist: pandas ~=2.2.0
|
26
27
|
Requires-Dist: plotly ~=5.18
|
27
28
|
Requires-Dist: pvlib ==0.9.4
|
@@ -30,12 +31,8 @@ Requires-Dist: pymsteams ~=0.2.2
|
|
30
31
|
Requires-Dist: scikit-learn ~=1.3
|
31
32
|
Requires-Dist: scipy ~=1.10
|
32
33
|
Requires-Dist: statsmodels ~=0.13.5
|
33
|
-
Requires-Dist: structlog
|
34
|
+
Requires-Dist: structlog <25,>=23.1
|
34
35
|
Requires-Dist: xgboost ~=2.0
|
35
|
-
Provides-Extra: proloaf
|
36
|
-
Requires-Dist: proloaf ==0.2.0 ; extra == 'proloaf'
|
37
|
-
Requires-Dist: torch ==1.10.0 ; extra == 'proloaf'
|
38
|
-
Requires-Dist: pytorch-lightning ==1.5.1 ; extra == 'proloaf'
|
39
36
|
|
40
37
|
<!--
|
41
38
|
SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com>
|
@@ -57,20 +54,27 @@ SPDX-License-Identifier: MPL-2.0
|
|
57
54
|
[](https://sonarcloud.io/dashboard?id=OpenSTEF_openstef)
|
58
55
|
[](https://sonarcloud.io/dashboard?id=OpenSTEF_openstef)
|
59
56
|
[](https://bestpractices.coreinfrastructure.org/projects/5585)
|
57
|
+
[](https://pepy.tech/project/openstef)
|
58
|
+
[](https://pepy.tech/project/openstef)
|
60
59
|
|
61
60
|
# OpenSTEF
|
62
61
|
OpenSTEF is a Python package designed for generating short-term forecasts in the energy sector. The repository includes all the essential components required for machine learning pipelines that facilitate the forecasting process. To utilize the package, users are required to furnish their own data storage and retrieval interface.
|
63
62
|
|
64
63
|
# Table of contents
|
64
|
+
- [OpenSTEF](#openstef)
|
65
|
+
- [Table of contents](#table-of-contents)
|
65
66
|
- [External information sources](#external-information-sources)
|
66
|
-
- [Installation](
|
67
|
-
- [
|
68
|
-
- [
|
69
|
-
- [
|
70
|
-
- [
|
71
|
-
- [
|
72
|
-
- [
|
73
|
-
- [
|
67
|
+
- [Installation](#installation)
|
68
|
+
- [Install the openstef package](#install-the-openstef-package)
|
69
|
+
- [Remark regarding installation within a **conda environment on Windows**:](#remark-regarding-installation-within-a-conda-environment-on-windows)
|
70
|
+
- [Usage](#usage)
|
71
|
+
- [Reference Implementation](#reference-implementation)
|
72
|
+
- [Openstef-dbc - Database connector for openstef](#openstef-dbc---database-connector-for-openstef)
|
73
|
+
- [Example notebooks](#example-notebooks)
|
74
|
+
- [License](#license)
|
75
|
+
- [Licenses third-party libraries](#licenses-third-party-libraries)
|
76
|
+
- [Contributing](#contributing)
|
77
|
+
- [Contact](#contact)
|
74
78
|
|
75
79
|
# External information sources
|
76
80
|
- [Documentation website](https://openstef.github.io/openstef/index.html);
|
@@ -89,10 +93,6 @@ OpenSTEF is a Python package designed for generating short-term forecasts in the
|
|
89
93
|
pip install openstef
|
90
94
|
```
|
91
95
|
|
92
|
-
_**Optional**_: if you would like to use the proloaf model with OpenSTEF install the proloaf dependencies by running:
|
93
|
-
```shell
|
94
|
-
pip install openstef[proloaf]
|
95
|
-
```
|
96
96
|
### Remark regarding installation within a **conda environment on Windows**:
|
97
97
|
|
98
98
|
A version of the pywin32 package will be installed as a secondary dependency along with the installation of the openstef package. Since conda relies on an old version of pywin32, the new installation can break conda's functionality. The following command can solve this issue:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
openstef/__init__.py,sha256=93UM6m0LLQhO69-mSqLuUy73jgs4W7Iuxfo3Lm8c98g,419
|
2
2
|
openstef/__main__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
3
|
-
openstef/enums.py,sha256=
|
3
|
+
openstef/enums.py,sha256=4NxcBobpn1Z6J_qHaIsJCarZ2BGZph_S_1PcwCDjg5o,729
|
4
4
|
openstef/exceptions.py,sha256=fVqjyrVMBiSGxcoZ3JfTcgZjIur1cPennZpfwqgc9qY,1992
|
5
5
|
openstef/data/dutch_holidays_2020-2022.csv,sha256=pS-CjE0igYXd-2dG-MlqyvR2fgYgXkbNmgCKyTjmwxs,23704
|
6
6
|
openstef/data/dutch_holidays_2020-2022.csv.license,sha256=AxxHusqwIXU5RHl5ZMU65LyXmgtbj6QlcnFaOEN4kEE,145
|
@@ -27,15 +27,14 @@ openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_target_scaler.z.license,sha25
|
|
27
27
|
openstef/data_classes/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
28
28
|
openstef/data_classes/data_prep.py,sha256=3SLvHDXlL-fBw8IFGBP_pKXTfWjQsKjgVxDyYlgic1o,3417
|
29
29
|
openstef/data_classes/model_specifications.py,sha256=Uod1W3QzhRqVLb6zvXwxh9wRL3EHCzSvX0oDNd28cFk,1197
|
30
|
-
openstef/data_classes/prediction_job.py,sha256=
|
30
|
+
openstef/data_classes/prediction_job.py,sha256=N2iD1B3LlnBAhvQaLJxIKe6K_0iWpTG0Qt6gHq5Vn6o,4789
|
31
31
|
openstef/data_classes/split_function.py,sha256=ljQIQQu1t1Y_CVWGAy25jrM6wG9odIVVQVimrT1n-1s,3358
|
32
32
|
openstef/feature_engineering/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
33
|
-
openstef/feature_engineering/apply_features.py,sha256
|
33
|
+
openstef/feature_engineering/apply_features.py,sha256=-3fyisOVj9ckIkRe2iYfWutbXSX8iqBkcvt8AYr-gmE,3906
|
34
34
|
openstef/feature_engineering/data_preparation.py,sha256=vFdCdXrX7RWWa4uj1D8rVkHymacbfhvwoLiEnUk-v6g,5399
|
35
35
|
openstef/feature_engineering/feature_adder.py,sha256=aSqDl_gUrB3H2TD3cNvU5JniY_KOb4u4a2A6J7zB2BQ,6835
|
36
|
-
openstef/feature_engineering/feature_applicator.py,sha256=
|
36
|
+
openstef/feature_engineering/feature_applicator.py,sha256=DR7jayrEMlra4BFL1Ps5WV2fxbkQ6VaOTa5RIKM-YNk,7447
|
37
37
|
openstef/feature_engineering/general.py,sha256=igAPyejYN5d09-a_c53C79a0A4cHjvMCa47KC4IfgCo,4072
|
38
|
-
openstef/feature_engineering/historic_features.py,sha256=aDxoS42ndUmLmwqpII8rZ_-L86NFer-Gw_fGf0TAobU,1215
|
39
38
|
openstef/feature_engineering/holiday_features.py,sha256=3Ff4Lkm26h8wJVoBplUewt4HfsvOUS9zj0x0MxewIm8,7842
|
40
39
|
openstef/feature_engineering/lag_features.py,sha256=Dr6qS8UhdgEHPZZSe-w6ibtjl_lcbcQohhqdZN9fqEU,5652
|
41
40
|
openstef/feature_engineering/weather_features.py,sha256=wy3KFXUIIwSydFJZpiejsJMwURtDpv9l0HBHu-uLAGQ,15561
|
@@ -47,9 +46,9 @@ openstef/model/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,16
|
|
47
46
|
openstef/model/basecase.py,sha256=caI6Q-8y0ymlxGK9Js_H3Vh0q6ruNHlGD5RG0_kE5M0,2878
|
48
47
|
openstef/model/confidence_interval_applicator.py,sha256=7E1_JFLZ4-hyEhleacMvp5szdmYZS4tpKAjfhGvXXvg,8602
|
49
48
|
openstef/model/fallback.py,sha256=VV9ehgnoMZtWzqKk9H1t8wnERFh5CyC4TvDIuRP_ZDI,2861
|
50
|
-
openstef/model/model_creator.py,sha256=
|
51
|
-
openstef/model/objective.py,sha256=
|
52
|
-
openstef/model/objective_creator.py,sha256=
|
49
|
+
openstef/model/model_creator.py,sha256=uDLn5fte8nGmxMOGA2xvTkeyslaA4kATuu-w1QOI4FI,4790
|
50
|
+
openstef/model/objective.py,sha256=eqNBYGfhEVGegOm0PbizowuFImKblRqHgxkp9lgaKQc,13500
|
51
|
+
openstef/model/objective_creator.py,sha256=QxHolw60aSvqSKO6VO-uDslwg3VC_T4BZ2cm-sy7E3U,1970
|
53
52
|
openstef/model/serializer.py,sha256=Q7pKkA-K1bszER_tkOWhvwTQsj6-qZoX5zaXIemRKGs,16934
|
54
53
|
openstef/model/standard_deviation_generator.py,sha256=Od9bzXi2TLb1v8Nz-VhBMZHSopWH6ssaDe8gYLlqO1I,2911
|
55
54
|
openstef/model/metamodels/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
@@ -61,7 +60,6 @@ openstef/model/regressors/custom_regressor.py,sha256=Hsmxahc9nfSWD0aEZ6cm4pxW2no
|
|
61
60
|
openstef/model/regressors/dazls.py,sha256=cCYFewJEv3Fn01wdZpaKNSiYmEwzuED7PQrrWzwyTEg,8084
|
62
61
|
openstef/model/regressors/lgbm.py,sha256=zCdn1euEdSFxYJzH8XqQFFnb6R4JVUnmineKjX_Gy-g,800
|
63
62
|
openstef/model/regressors/linear.py,sha256=uOvZMLGZH_9nXfmS5honCMfyVeyGXP1Cza9A_BdXlVw,3665
|
64
|
-
openstef/model/regressors/proloaf.py,sha256=HjyfEQRiFMFzyfYSrFL3yPhduhL1igGr1FTO6d0ET7I,9081
|
65
63
|
openstef/model/regressors/regressor.py,sha256=uJcx59AyCPE9f_yPcAQ59h2ZS7eNsDpIHJrladKvHIw,3461
|
66
64
|
openstef/model/regressors/xgb.py,sha256=HggA1U10srzdysjV560BMMX66kfaxCKAnOZB3JyyT_Y,808
|
67
65
|
openstef/model/regressors/xgb_quantile.py,sha256=Oenhe0cMLAEXlinHZF588zNTjwR-hB7NB0anQZPwPKU,7710
|
@@ -74,9 +72,9 @@ openstef/pipeline/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU
|
|
74
72
|
openstef/pipeline/create_basecase_forecast.py,sha256=7jig8lt-e3xwIWDSk-bMwUC45y2mwKe9-zDZYHiiQMY,4324
|
75
73
|
openstef/pipeline/create_component_forecast.py,sha256=ksX5r7H5IrMrfPVuRK0OWOtsdns1Rrn1L9ZG0Si0TI4,6255
|
76
74
|
openstef/pipeline/create_forecast.py,sha256=El9xXKN8DeIADy_76-V22wBY8AMSa4KEfYuW00jw85k,5083
|
77
|
-
openstef/pipeline/optimize_hyperparameters.py,sha256=
|
78
|
-
openstef/pipeline/train_create_forecast_backtest.py,sha256=
|
79
|
-
openstef/pipeline/train_model.py,sha256=
|
75
|
+
openstef/pipeline/optimize_hyperparameters.py,sha256=QlM_TN2sVelfrYFqZfy-gkRJMlt4j3fr65HvcEGhdac,10272
|
76
|
+
openstef/pipeline/train_create_forecast_backtest.py,sha256=QkkpccW4BW0TC5uq22_juTcp8uvPZ4Qk-ewdnlYpNTE,5492
|
77
|
+
openstef/pipeline/train_model.py,sha256=ELIHkGjzvIdV4V7IMiy8tw7A_wc1QJ7eXY_rPXOgytU,18533
|
80
78
|
openstef/pipeline/utils.py,sha256=fkc-oNirJ-JiyuOAL08RFrnPYPwudWal_N-BO6Cw980,2086
|
81
79
|
openstef/postprocessing/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
82
80
|
openstef/postprocessing/postprocessing.py,sha256=nehd0tDpkdIaWFJggQ-fDizIKdfmqJ3IOGfk0sDnrzk,8409
|
@@ -99,8 +97,8 @@ openstef/tasks/utils/predictionjobloop.py,sha256=Ysy3zF5lzPMz_asYDKeF5m0qgVT3tCt
|
|
99
97
|
openstef/tasks/utils/taskcontext.py,sha256=yI6TntOkZcW8JiNVuw4uJIigEBL0_iIrkPklF4ZeCX4,5401
|
100
98
|
openstef/validation/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
|
101
99
|
openstef/validation/validation.py,sha256=SaI-Mff9UOHQPnQ2jodXzZAVZilc-2AXZsPpSjDRqAg,10346
|
102
|
-
openstef-3.4.
|
103
|
-
openstef-3.4.
|
104
|
-
openstef-3.4.
|
105
|
-
openstef-3.4.
|
106
|
-
openstef-3.4.
|
100
|
+
openstef-3.4.13.dist-info/LICENSE,sha256=7Pm2fWFFHHUG5lDHed1vl5CjzxObIXQglnYsEdtjo_k,14907
|
101
|
+
openstef-3.4.13.dist-info/METADATA,sha256=l5HsBWQbm_94pKxUsJxpOW6QAUBGw2Dd-z3_sdDxDWM,8124
|
102
|
+
openstef-3.4.13.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
103
|
+
openstef-3.4.13.dist-info/top_level.txt,sha256=kD0H4PqrQoncZ957FvqwfBxa89kTrun4Z_RAPs_HhLs,9
|
104
|
+
openstef-3.4.13.dist-info/RECORD,,
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# SPDX-FileCopyrightText: 2017-2023 Alliander N.V. <korte.termijn.prognoses@alliander.com> # noqa E501>
|
2
|
-
#
|
3
|
-
# SPDX-License-Identifier: MPL-2.0
|
4
|
-
|
5
|
-
"""This module contains historic load related functions used for feature engineering."""
|
6
|
-
|
7
|
-
import pandas as pd
|
8
|
-
import structlog
|
9
|
-
|
10
|
-
from openstef.data_classes.prediction_job import PredictionJobDataClass
|
11
|
-
|
12
|
-
|
13
|
-
def add_historic_load_as_a_feature(
|
14
|
-
data: pd.DataFrame,
|
15
|
-
pj: PredictionJobDataClass = None,
|
16
|
-
) -> pd.DataFrame:
|
17
|
-
"""Adds additional proloaf features to the input data, historic_load (equal to the load).
|
18
|
-
|
19
|
-
Args:
|
20
|
-
data: Dataframe to which the wind features have to be added
|
21
|
-
pj: Prediction job.
|
22
|
-
|
23
|
-
Returns:
|
24
|
-
DataFrame that is the same as input dataframe with extra columns for the added proloaf features
|
25
|
-
|
26
|
-
"""
|
27
|
-
logger = structlog.get_logger(__name__)
|
28
|
-
|
29
|
-
if pj is None:
|
30
|
-
pj = {}
|
31
|
-
|
32
|
-
if pj.get("model") == "proloaf":
|
33
|
-
data["historic_load"] = data["load"]
|
34
|
-
logger.warning(
|
35
|
-
"The historic_load is added to the data, this is a copy of the load. Adding"
|
36
|
-
" this feature is in most of the cases not a good idea, it is designed for"
|
37
|
-
" the proloaf model."
|
38
|
-
)
|
39
|
-
|
40
|
-
return data
|
@@ -1,281 +0,0 @@
|
|
1
|
-
# SPDX-FileCopyrightText: 2017-2023 Alliander N.V. <korte.termijn.prognoses@alliander.com> # noqa E501>
|
2
|
-
#
|
3
|
-
# SPDX-License-Identifier: MPL-2.0
|
4
|
-
from typing import Any, Union
|
5
|
-
|
6
|
-
import numpy as np
|
7
|
-
import pandas as pd
|
8
|
-
|
9
|
-
# These imports will require the proloaf optional dependencies to be installed
|
10
|
-
import proloaf.datahandler as dh
|
11
|
-
import torch
|
12
|
-
from proloaf.modelhandler import ModelWrapper
|
13
|
-
|
14
|
-
from openstef.model.regressors.regressor import OpenstfRegressor
|
15
|
-
|
16
|
-
# TODO: implement the hyperparameter optimalisation via optuna
|
17
|
-
# TODO: set the default for hyperparameters in the init of OpenstfProloafRegressor
|
18
|
-
# TODO: implement function for defining encoder and decoder features
|
19
|
-
|
20
|
-
|
21
|
-
def divide_scaling_groups(x: pd.DataFrame) -> tuple[list[str], list[str], list[str]]:
|
22
|
-
"""Divides the column names over different type of scaling groups.
|
23
|
-
|
24
|
-
Args:
|
25
|
-
x: Dataframe from which columns have to be divided
|
26
|
-
|
27
|
-
Returns:
|
28
|
-
List of all the grouped features for scaling (three groups)
|
29
|
-
|
30
|
-
"""
|
31
|
-
minmax_scale_features = []
|
32
|
-
oh_scale_features = []
|
33
|
-
no_scale_features = []
|
34
|
-
|
35
|
-
for column in x.columns:
|
36
|
-
if (x[column].min() <= -1) or (x[column].max() >= 1):
|
37
|
-
minmax_scale_features.append(column)
|
38
|
-
elif x[column].dtype == "bool":
|
39
|
-
oh_scale_features.append(column)
|
40
|
-
else:
|
41
|
-
no_scale_features.append(column)
|
42
|
-
|
43
|
-
return minmax_scale_features, oh_scale_features, no_scale_features
|
44
|
-
|
45
|
-
|
46
|
-
def apply_scaling(
|
47
|
-
scaler_features: tuple[list[str], list[str], list[str]],
|
48
|
-
data: pd.DataFrame,
|
49
|
-
scalers=None,
|
50
|
-
):
|
51
|
-
"""Applies different scaling methods to a certain dataframe (minmax, one hot, or no scaling).
|
52
|
-
|
53
|
-
Args:
|
54
|
-
scaler_features: Three different lists with features for each scaling
|
55
|
-
x: Dataframe from which columns have to be divided
|
56
|
-
scalers: scalers resulting from the previous scaling
|
57
|
-
|
58
|
-
Returns:
|
59
|
-
Dataframe with all the scaled features
|
60
|
-
|
61
|
-
"""
|
62
|
-
selected_features, scalers = dh.scale_all(
|
63
|
-
data,
|
64
|
-
scalers=scalers,
|
65
|
-
feature_groups=[
|
66
|
-
{
|
67
|
-
"name": "main",
|
68
|
-
"scaler": ["minmax", -1.0, 1.0],
|
69
|
-
"features": scaler_features[0],
|
70
|
-
},
|
71
|
-
{"name": "aux", "scaler": None, "features": scaler_features[2]},
|
72
|
-
],
|
73
|
-
)
|
74
|
-
|
75
|
-
# One hot encoding certain features
|
76
|
-
onehot_feature_groups = [
|
77
|
-
{
|
78
|
-
"name": "main",
|
79
|
-
"scaler": [
|
80
|
-
"onehot",
|
81
|
-
],
|
82
|
-
"features": scaler_features[1],
|
83
|
-
}
|
84
|
-
]
|
85
|
-
for group in onehot_feature_groups:
|
86
|
-
df_onehot = data.filter(group["features"])
|
87
|
-
result_oh_scale = np.transpose(np.array(df_onehot.iloc[:, :], dtype=np.int))
|
88
|
-
df_onehot.iloc[:, :] = result_oh_scale.T
|
89
|
-
|
90
|
-
if not df_onehot.columns.empty:
|
91
|
-
selected_features = pd.concat([selected_features, df_onehot], axis=1)
|
92
|
-
data = selected_features.iloc[:, :].replace(np.nan, 0)
|
93
|
-
|
94
|
-
return data, scalers
|
95
|
-
|
96
|
-
|
97
|
-
class OpenstfProloafRegressor(OpenstfRegressor, ModelWrapper):
|
98
|
-
def __init__(
|
99
|
-
self,
|
100
|
-
name: str = "model",
|
101
|
-
core_net: str = "torch.nn.LSTM",
|
102
|
-
relu_leak: float = 0.1,
|
103
|
-
encoder_features: list[str] = [
|
104
|
-
"historic_load",
|
105
|
-
], # make sure historic load is present, TODO: implement so you can use None
|
106
|
-
decoder_features: list[str] = [
|
107
|
-
"air_density"
|
108
|
-
], # TODO: implement so you can use None
|
109
|
-
core_layers: int = 1,
|
110
|
-
rel_linear_hidden_size: float = 1.0,
|
111
|
-
rel_core_hidden_size: float = 1.0,
|
112
|
-
dropout_fc: float = 0.4,
|
113
|
-
dropout_core: float = 0.3,
|
114
|
-
training_metric: str = "nllgauss",
|
115
|
-
metric_options: dict[str, Any] = {},
|
116
|
-
optimizer_name: str = "adam",
|
117
|
-
early_stopping_patience: int = 7,
|
118
|
-
early_stopping_margin: float = 0,
|
119
|
-
learning_rate: float = 1e-3,
|
120
|
-
max_epochs: int = 100,
|
121
|
-
device: Union[str, int] = "cpu", # "cuda" or "cpu"
|
122
|
-
batch_size: int = 6,
|
123
|
-
history_horizon: int = 24,
|
124
|
-
horizon_minutes: int = 2880, # 2 days in minutes,
|
125
|
-
):
|
126
|
-
self.device = device
|
127
|
-
self.batch_size = batch_size
|
128
|
-
self.history_horizon = history_horizon
|
129
|
-
self.forecast_horizon = int(horizon_minutes / 60)
|
130
|
-
ModelWrapper.__init__(
|
131
|
-
self,
|
132
|
-
name=name,
|
133
|
-
core_net=core_net,
|
134
|
-
relu_leak=relu_leak,
|
135
|
-
encoder_features=encoder_features,
|
136
|
-
decoder_features=decoder_features,
|
137
|
-
core_layers=core_layers,
|
138
|
-
rel_linear_hidden_size=rel_linear_hidden_size,
|
139
|
-
rel_core_hidden_size=rel_core_hidden_size,
|
140
|
-
dropout_fc=dropout_fc,
|
141
|
-
dropout_core=dropout_core,
|
142
|
-
training_metric=training_metric,
|
143
|
-
metric_options=metric_options,
|
144
|
-
optimizer_name=optimizer_name,
|
145
|
-
early_stopping_patience=early_stopping_patience,
|
146
|
-
early_stopping_margin=early_stopping_margin,
|
147
|
-
learning_rate=learning_rate,
|
148
|
-
max_epochs=max_epochs,
|
149
|
-
)
|
150
|
-
self.to(device)
|
151
|
-
|
152
|
-
@property
|
153
|
-
def feature_names(self):
|
154
|
-
return (
|
155
|
-
["load"] + self.encoder_features + self.decoder_features
|
156
|
-
) # TODO: gehele range, of een enkele feature
|
157
|
-
|
158
|
-
@property
|
159
|
-
def can_predict_quantiles(self):
|
160
|
-
return False
|
161
|
-
|
162
|
-
def predict(self, x: pd.DataFrame) -> np.ndarray:
|
163
|
-
x = x[list(self.feature_names)[1:]]
|
164
|
-
# Apply scaling and interpolation for NaN values
|
165
|
-
x = dh.fill_if_missing(x, periodicity=24)
|
166
|
-
x, _ = apply_scaling(
|
167
|
-
[
|
168
|
-
self.minmax_scale_features,
|
169
|
-
self.oh_scale_features,
|
170
|
-
self.no_scale_features,
|
171
|
-
],
|
172
|
-
x,
|
173
|
-
self.scalers,
|
174
|
-
)
|
175
|
-
|
176
|
-
inputs_enc = torch.tensor(
|
177
|
-
x[self.encoder_features].to_numpy(), dtype=torch.float
|
178
|
-
).unsqueeze(dim=0)
|
179
|
-
inputs_dec = torch.tensor(
|
180
|
-
x[self.decoder_features].to_numpy(), dtype=torch.float
|
181
|
-
).unsqueeze(dim=0)
|
182
|
-
prediction = (
|
183
|
-
ModelWrapper.predict(self, inputs_enc, inputs_dec)[:, :, 0]
|
184
|
-
.squeeze()
|
185
|
-
.detach()
|
186
|
-
.numpy()
|
187
|
-
)
|
188
|
-
|
189
|
-
return prediction
|
190
|
-
|
191
|
-
def fit(
|
192
|
-
self,
|
193
|
-
x: pd.DataFrame,
|
194
|
-
y: pd.DataFrame,
|
195
|
-
eval_set: tuple = None,
|
196
|
-
early_stopping_rounds: int = None,
|
197
|
-
verbose: bool = False,
|
198
|
-
**kwargs,
|
199
|
-
) -> ModelWrapper:
|
200
|
-
x = x[list(self.feature_names)[1:]]
|
201
|
-
# Apply scaling and interpolation for NaN values
|
202
|
-
x = dh.fill_if_missing(x, periodicity=24)
|
203
|
-
(
|
204
|
-
self.minmax_scale_features,
|
205
|
-
self.oh_scale_features,
|
206
|
-
self.no_scale_features,
|
207
|
-
) = divide_scaling_groups(x)
|
208
|
-
x, self.scalers = apply_scaling(
|
209
|
-
[
|
210
|
-
self.minmax_scale_features,
|
211
|
-
self.oh_scale_features,
|
212
|
-
self.no_scale_features,
|
213
|
-
],
|
214
|
-
x,
|
215
|
-
self.scalers,
|
216
|
-
)
|
217
|
-
y = y.to_frame()
|
218
|
-
self.target_id = [y.columns[0]]
|
219
|
-
|
220
|
-
df_train = pd.concat([x, y], axis="columns", verify_integrity=True)
|
221
|
-
|
222
|
-
print(f"{self.encoder_features = }")
|
223
|
-
print(f"{self.decoder_features = }")
|
224
|
-
|
225
|
-
train_dl, _, _ = dh.transform(
|
226
|
-
df=df_train,
|
227
|
-
encoder_features=self.encoder_features,
|
228
|
-
decoder_features=self.decoder_features,
|
229
|
-
batch_size=self.batch_size,
|
230
|
-
history_horizon=self.history_horizon,
|
231
|
-
forecast_horizon=self.forecast_horizon,
|
232
|
-
target_id=self.target_id,
|
233
|
-
train_split=1.0,
|
234
|
-
validation_split=1.0,
|
235
|
-
device=self.device,
|
236
|
-
)
|
237
|
-
|
238
|
-
val_x, val_y = eval_set[1][0], eval_set[1][1]
|
239
|
-
val_x = dh.fill_if_missing(val_x, periodicity=24)
|
240
|
-
val_x, _ = apply_scaling(
|
241
|
-
[
|
242
|
-
self.minmax_scale_features,
|
243
|
-
self.oh_scale_features,
|
244
|
-
self.no_scale_features,
|
245
|
-
],
|
246
|
-
val_x,
|
247
|
-
self.scalers,
|
248
|
-
)
|
249
|
-
|
250
|
-
df_val = pd.concat([val_x, val_y], axis="columns", verify_integrity=True)
|
251
|
-
_, validation_dl, _ = dh.transform(
|
252
|
-
df=df_val,
|
253
|
-
encoder_features=self.encoder_features,
|
254
|
-
decoder_features=self.decoder_features,
|
255
|
-
batch_size=self.batch_size,
|
256
|
-
history_horizon=self.history_horizon,
|
257
|
-
forecast_horizon=self.forecast_horizon,
|
258
|
-
target_id=self.target_id,
|
259
|
-
train_split=0.0,
|
260
|
-
validation_split=1.0,
|
261
|
-
device=self.device,
|
262
|
-
)
|
263
|
-
self.to(self.device)
|
264
|
-
self.init_model()
|
265
|
-
self.is_fitted_ = True
|
266
|
-
|
267
|
-
return self.run_training(train_dl, validation_dl)
|
268
|
-
|
269
|
-
def get_params(self, deep=True):
|
270
|
-
model_params = self.get_model_config()
|
271
|
-
training_params = self.get_training_config()
|
272
|
-
return {**model_params, **training_params}
|
273
|
-
|
274
|
-
def set_params(self, **params):
|
275
|
-
self.update(**params)
|
276
|
-
return self
|
277
|
-
|
278
|
-
|
279
|
-
if __name__ == "__main__":
|
280
|
-
test = OpenstfProloafRegressor()
|
281
|
-
print(test)
|
File without changes
|
File without changes
|