openstef 3.4.23__py3-none-any.whl → 3.4.25__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 (32) hide show
  1. openstef/data_classes/prediction_job.py +1 -0
  2. openstef/enums.py +1 -0
  3. openstef/metrics/metrics.py +51 -0
  4. openstef/model/model_creator.py +14 -0
  5. openstef/model/objective.py +30 -0
  6. openstef/model/objective_creator.py +3 -0
  7. openstef/model/regressors/dazls.py +28 -107
  8. openstef/model/regressors/xgb_multioutput_quantile.py +261 -0
  9. openstef/pipeline/create_component_forecast.py +2 -19
  10. {openstef-3.4.23.dist-info → openstef-3.4.25.dist-info}/METADATA +2 -2
  11. {openstef-3.4.23.dist-info → openstef-3.4.25.dist-info}/RECORD +14 -31
  12. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_adaptation_model.z +0 -0
  13. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_adaptation_model.z.license +0 -3
  14. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_adaptation_model_features.z +0 -0
  15. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_adaptation_model_features.z.license +0 -3
  16. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_adaptation_model_scaler.z +0 -0
  17. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_adaptation_model_scaler.z.license +0 -3
  18. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_domain_model.z +0 -0
  19. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_domain_model.z.license +0 -3
  20. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_domain_model_features.z +0 -2
  21. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_domain_model_features.z.license +0 -3
  22. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_domain_model_scaler.z +0 -0
  23. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_domain_model_scaler.z.license +0 -3
  24. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_model_card.md +0 -14
  25. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_model_card.md.license +0 -3
  26. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_target.z +0 -0
  27. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_target.z.license +0 -3
  28. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_target_scaler.z +0 -0
  29. openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_target_scaler.z.license +0 -3
  30. {openstef-3.4.23.dist-info → openstef-3.4.25.dist-info}/LICENSE +0 -0
  31. {openstef-3.4.23.dist-info → openstef-3.4.25.dist-info}/WHEEL +0 -0
  32. {openstef-3.4.23.dist-info → openstef-3.4.25.dist-info}/top_level.txt +0 -0
@@ -26,6 +26,7 @@ class PredictionJobDataClass(BaseModel):
26
26
  - ``"lgb"``
27
27
  - ``"linear"``
28
28
  - ``"linear_quantile"``
29
+ - ``"xgb_multioutput_quantile"``
29
30
 
30
31
  If unsure what to pick, choose ``"xgb"``.
31
32
 
openstef/enums.py CHANGED
@@ -8,6 +8,7 @@ from enum import Enum
8
8
  class MLModelType(Enum):
9
9
  XGB = "xgb"
10
10
  XGB_QUANTILE = "xgb_quantile"
11
+ XGB_MULTIOUTPUT_QUANTILE = "xgb_multioutput_quantile"
11
12
  LGB = "lgb"
12
13
  LINEAR = "linear"
13
14
  LINEAR_QUANTILE = "linear_quantile"
@@ -431,3 +431,54 @@ def xgb_quantile_obj(
431
431
  hess = np.ones_like(preds)
432
432
 
433
433
  return grad, hess
434
+
435
+
436
+ def arctan_loss(y_true, y_pred, taus, s=0.1):
437
+ """Compute the arctan pinball loss.
438
+
439
+ Note that XGBoost outputs the predictions in a slightly peculiar manner.
440
+ Suppose we have 100 data points and we predict 10 quantiles. The predictions
441
+ will be an array of size (1000 x 1). We first resize this to a (100x10) array
442
+ where each row corresponds to the 10 predicted quantile for a single data
443
+ point. We then use a for-loop (over the 10 columns) to calculate the gradients
444
+ and second derivatives. Legibility was chosen over efficiency. This part
445
+ can be made more efficient.
446
+
447
+ Args:
448
+ y_true: An array containing the true observations.
449
+ y_pred: An array containing the predicted quantiles.
450
+ taus: A list containing the true desired coverage of the quantiles.
451
+ s: A smoothing parameter.
452
+
453
+ Returns:
454
+ grad: An array containing the (negative) gradients with respect to y_pred.
455
+ hess: An array containing the second derivative with respect to y_pred.
456
+
457
+ """
458
+ size = len(y_true)
459
+ n_dim = len(taus) # The number of columns
460
+ n_rows = size // n_dim
461
+
462
+ # Resize the predictions and targets.
463
+ # Each column corresponds to a quantile, each row to a data point.
464
+ y_pred = np.reshape(y_pred, (n_rows, n_dim))
465
+ y_true = np.reshape(y_true, (n_rows, n_dim))
466
+
467
+ # Calculate the differences
468
+ u = y_true - y_pred
469
+
470
+ # Calculate the gradient and second derivatives
471
+ grad = np.zeros_like(y_pred)
472
+ hess = np.zeros_like(y_pred)
473
+ z = u / s
474
+ for i, tau in enumerate(taus):
475
+ x = 1 + z[:, i] ** 2
476
+ grad[:, i] = (
477
+ tau - 0.5 + 1 / np.pi * np.arctan(z[:, i]) + z[:, i] / (np.pi) * x**-1
478
+ )
479
+ hess[:, i] = 2 / (np.pi * s) * x ** (-2)
480
+
481
+ # Reshape back to the original shape.
482
+ grad = grad.reshape(size)
483
+ hess = hess.reshape(size)
484
+ return -grad / n_dim, hess / n_dim
@@ -15,6 +15,9 @@ from openstef.model.regressors.linear_quantile import LinearQuantileOpenstfRegre
15
15
  from openstef.model.regressors.regressor import OpenstfRegressor
16
16
  from openstef.model.regressors.xgb import XGBOpenstfRegressor
17
17
  from openstef.model.regressors.xgb_quantile import XGBQuantileOpenstfRegressor
18
+ from openstef.model.regressors.xgb_multioutput_quantile import (
19
+ XGBMultiOutputQuantileOpenstfRegressor,
20
+ )
18
21
  from openstef.settings import Settings
19
22
 
20
23
  structlog.configure(
@@ -87,6 +90,16 @@ valid_model_kwargs = {
87
90
  "max_depth",
88
91
  "early_stopping_rounds",
89
92
  ],
93
+ MLModelType.XGB_MULTIOUTPUT_QUANTILE: [
94
+ "quantiles",
95
+ "gamma",
96
+ "colsample_bytree",
97
+ "subsample",
98
+ "min_child_weight",
99
+ "max_depth",
100
+ "early_stopping_rounds",
101
+ "arctan_smoothing",
102
+ ],
90
103
  MLModelType.LINEAR: [
91
104
  "missing_values",
92
105
  "imputation_strategy",
@@ -117,6 +130,7 @@ class ModelCreator:
117
130
  MLModelType.XGB: XGBOpenstfRegressor,
118
131
  MLModelType.LGB: LGBMOpenstfRegressor,
119
132
  MLModelType.XGB_QUANTILE: XGBQuantileOpenstfRegressor,
133
+ MLModelType.XGB_MULTIOUTPUT_QUANTILE: XGBMultiOutputQuantileOpenstfRegressor,
120
134
  MLModelType.LINEAR: LinearOpenstfRegressor,
121
135
  MLModelType.LINEAR_QUANTILE: LinearQuantileOpenstfRegressor,
122
136
  MLModelType.ARIMA: ARIMAOpenstfRegressor,
@@ -349,6 +349,36 @@ class XGBQuantileRegressorObjective(RegressorObjective):
349
349
  )
350
350
 
351
351
 
352
+ class XGBMultioutputQuantileRegressorObjective(RegressorObjective):
353
+ def __init__(self, *args, **kwargs):
354
+ super().__init__(*args, **kwargs)
355
+ self.model_type = MLModelType.XGB_QUANTILE
356
+
357
+ def get_params(self, trial: optuna.trial.FrozenTrial) -> dict:
358
+ """Get parameters for XGB Multioutput Quantile 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
+ # XGB specific parameters
370
+ params = {
371
+ "gamma": trial.suggest_float("gamma", 1e-8, 1.0),
372
+ "arctan_smoothing": trial.suggest_float("arctan_smoothing", 0.025, 0.15),
373
+ }
374
+ return {**model_params, **params}
375
+
376
+ def get_pruning_callback(self, trial: optuna.trial.FrozenTrial):
377
+ return optuna.integration.XGBoostPruningCallback(
378
+ trial, observation_key=f"validation_1-{self.eval_metric}"
379
+ )
380
+
381
+
352
382
  class LinearRegressorObjective(RegressorObjective):
353
383
  def __init__(self, *args, **kwargs):
354
384
  super().__init__(*args, **kwargs)
@@ -12,6 +12,7 @@ from openstef.model.objective import (
12
12
  RegressorObjective,
13
13
  XGBQuantileRegressorObjective,
14
14
  XGBRegressorObjective,
15
+ XGBMultioutputQuantileRegressorObjective,
15
16
  )
16
17
  from openstef.model.regressors.custom_regressor import (
17
18
  create_custom_objective,
@@ -24,7 +25,9 @@ class ObjectiveCreator:
24
25
  MLModelType.XGB: XGBRegressorObjective,
25
26
  MLModelType.LGB: LGBRegressorObjective,
26
27
  MLModelType.XGB_QUANTILE: XGBQuantileRegressorObjective,
28
+ MLModelType.XGB_MULTIOUTPUT_QUANTILE: XGBMultioutputQuantileRegressorObjective,
27
29
  MLModelType.LINEAR: LinearRegressorObjective,
30
+ MLModelType.LINEAR_QUANTILE: LinearRegressorObjective,
28
31
  MLModelType.ARIMA: ARIMARegressorObjective,
29
32
  }
30
33
 
@@ -4,65 +4,41 @@
4
4
  """This module defines the DAZL model."""
5
5
  import numpy as np
6
6
  from sklearn.base import BaseEstimator
7
+ from sklearn.compose import TransformedTargetRegressor
8
+ from sklearn.linear_model import LinearRegression
7
9
  from sklearn.metrics import mean_squared_error, r2_score
8
- from sklearn.neighbors import KNeighborsRegressor
10
+ from sklearn.pipeline import Pipeline
9
11
  from sklearn.preprocessing import MinMaxScaler
10
- from sklearn.utils import shuffle
11
12
 
12
13
 
13
14
  class Dazls(BaseEstimator):
14
15
  """DAZLS model.
15
16
 
16
- The model carries out wind and solar power prediction for unseen target substations using training data from
17
- other substations with known components.
18
- This model has two sub-models:
19
-
20
- - domain model : a model taking a set of 'input' features of a substation and make an 'initial' prediction.
21
- Input features can be features such as: weather, geospatial, total load, etc.
22
- These features are always directly related to the components' size in some way.
23
-
24
-
25
- - adaptation model : a model taking a set of 'meta' features of a substation and refines the domain model's
26
- prediction. Next to the features, it is trained on the domain model's predictions.
27
- 'Meta' features are features related to the uncertainty of the data, and include:
28
- variance of the total load, standard deviation of the total load, etc.
29
-
30
- Any data-driven model can be plugged and used as the base for the domain and the adaptation model.
31
-
32
- CAUTION : 'Meta' features should be kept out of the domain model, and vice versa input features should be
33
- kept out the adaptation model.
34
-
35
- For a full reference, see:
36
- Teng, S.Y., van Nooten, C. C., van Doorn, J.M., Ottenbros, A., Huijbregts, M., Jansen, J.J.
37
- Improving Near Real-Time Predictions of Renewable Electricity Production at Substation Level (Submitted)
38
-
39
- Args:
40
- - BaseEstimator (object) : a base model that can be used to carry out predictions.
17
+ The model carries out wind and solar power prediction for unseen target substations using training data from other
18
+ substations with known components.
41
19
 
42
20
  """
43
21
 
22
+ model_: Pipeline
23
+
44
24
  def __init__(self):
45
25
  """Initialize DAZL model."""
46
26
  self.__name__ = "DAZLS"
47
- self.domain_model_scaler = MinMaxScaler(clip=True)
48
- self.adaptation_model_scaler = MinMaxScaler(clip=True)
49
- self.target_scaler = MinMaxScaler(clip=True)
50
- self.domain_model = KNeighborsRegressor(n_neighbors=20, weights="uniform")
51
- self.adaptation_model = KNeighborsRegressor(n_neighbors=20, weights="uniform")
27
+
28
+ regressor = TransformedTargetRegressor(
29
+ regressor=LinearRegression(),
30
+ transformer=MinMaxScaler(clip=True),
31
+ )
32
+
33
+ self.model_ = Pipeline(
34
+ [("scaler", MinMaxScaler(clip=True)), ("regressor", regressor)]
35
+ )
52
36
 
53
37
  # The input columns for the domain and adaptation models (with description)
54
- self.domain_model_input_columns = [
38
+ self.baseline_input_columns = [
55
39
  "radiation", # Weather parameter
56
40
  "windspeed_100m", # Weather parameter
57
- "total_substation", # Substation's measured total load
58
- "lat", # Latitude
59
- "lon", # Longitude
60
- "hour", # Hour of the day
61
- "minute", # Minute of the hour
62
- ]
63
- self.adaptation_model_input_columns = [
64
- "var_total", # Variance of the total load
65
- "sem_total", # Standard Error of the Mean of the total load
41
+ "total_load",
66
42
  ]
67
43
  self.target_columns = ["total_wind_part", "total_solar_part"]
68
44
 
@@ -76,34 +52,15 @@ class Dazls(BaseEstimator):
76
52
  Args:
77
53
  features: inputs for domain and adaptation model (domain_model_input, adaptation_model_input)
78
54
  target: the expected output (y_train)
79
-
80
55
  """
81
- x, x2, y = (
82
- features.loc[:, self.domain_model_input_columns],
83
- features.loc[:, self.adaptation_model_input_columns],
56
+ x, y = (
57
+ features.loc[:, self.baseline_input_columns],
84
58
  target.loc[:, self.target_columns],
85
59
  )
86
- domain_model_input, adaptation_model_input, y_train = shuffle(
87
- x, x2, y, random_state=999
88
- ) # just shuffling
89
-
90
- self.domain_model_scaler.fit(domain_model_input)
91
- self.adaptation_model_scaler.fit(adaptation_model_input)
92
- self.target_scaler.fit(y_train)
93
- domain_model_input = self.domain_model_scaler.transform(domain_model_input)
94
- adaptation_model_input = self.adaptation_model_scaler.transform(
95
- adaptation_model_input
96
- )
97
- y_train = self.target_scaler.transform(y_train)
98
60
 
99
- self.domain_model.fit(domain_model_input, y_train)
100
- domain_model_pred = self.domain_model.predict(domain_model_input)
101
- adaptation_model_input = np.concatenate(
102
- (adaptation_model_input, domain_model_pred), axis=1
103
- )
104
- self.adaptation_model.fit(adaptation_model_input, y_train)
61
+ self.model_.fit(x, y)
105
62
 
106
- def predict(self, x: np.array, return_sub_preds: bool = False):
63
+ def predict(self, x: np.array):
107
64
  """Make a prediction.
108
65
 
109
66
  For the prediction we use the test data x. We use domain_model_input_columns and
@@ -119,41 +76,10 @@ class Dazls(BaseEstimator):
119
76
 
120
77
  Returns:
121
78
  prediction: The output prediction after both models.
122
-
123
79
  """
124
- domain_model_test_data, adaptation_model_test_data = (
125
- x.loc[:, self.domain_model_input_columns],
126
- x.loc[:, self.adaptation_model_input_columns],
127
- )
128
- # Rescale test data for both models (if required)
129
- domain_model_test_data_scaled = self.domain_model_scaler.transform(
130
- domain_model_test_data
131
- )
132
- adaptation_model_test_data_scaled = self.adaptation_model_scaler.transform(
133
- adaptation_model_test_data
134
- )
135
- # Use the scaled data to make domain_model_prediction
136
- domain_model_test_data_pred = self.domain_model.predict(
137
- domain_model_test_data_scaled
138
- )
139
- # Use the domain_model_prediction to make adaptation_model_prediction
140
- adaptation_model_test_data_pred = self.adaptation_model.predict(
141
- np.concatenate(
142
- [adaptation_model_test_data_scaled, domain_model_test_data_pred], axis=1
143
- )
144
- )
145
- # Rescale adaptation_model_prediction (if required)
146
- prediction = self.target_scaler.inverse_transform(
147
- adaptation_model_test_data_pred
148
- )
80
+ model_test_data = x.loc[:, self.baseline_input_columns]
149
81
 
150
- if return_sub_preds:
151
- prediction_domain = self.target_scaler.inverse_transform(
152
- domain_model_test_data_pred
153
- )
154
- return prediction, prediction_domain
155
- else:
156
- return prediction
82
+ return self.model_.predict(model_test_data)
157
83
 
158
84
  def score(self, truth, prediction):
159
85
  """Evaluation of the prediction's output.
@@ -164,7 +90,6 @@ class Dazls(BaseEstimator):
164
90
 
165
91
  Returns:
166
92
  RMSE and R2 scores
167
-
168
93
  """
169
94
  rmse = (mean_squared_error(truth, prediction)) ** 0.5
170
95
  r2_score_value = r2_score(truth, prediction)
@@ -175,17 +100,13 @@ class Dazls(BaseEstimator):
175
100
 
176
101
  Returns:
177
102
  Summary represented by a string
178
-
179
103
  """
180
104
  summary_str = (
181
105
  f"{self.__name__} model summary:\n\n"
182
- f"Domain Model: {self.domain_model} \n"
183
- f"\tInput columns: {self.domain_model_input_columns} \n"
184
- f"\tScaler: {self.domain_model_scaler} \n\n"
185
- f"Adaptation Model: {self.adaptation_model} \n"
186
- f"\tInput columns: {self.adaptation_model_input_columns} \n"
187
- f"\tScaler: {self.adaptation_model_scaler} \n\n"
188
- f"Target columns: {self.target_columns}"
106
+ f"Model: {self.model_} \n"
107
+ f"\tInput columns: {self.baseline_input_columns} \n"
108
+ f"\tScaler: {self.model_['scaler']} \n\n"
109
+ f"\tRegressor: {self.model_['regressor']} \n\n"
189
110
  )
190
111
 
191
112
  return summary_str
@@ -0,0 +1,261 @@
1
+ # SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com> # noqa E501>
2
+ #
3
+ # SPDX-License-Identifier: MPL-2.0
4
+ from functools import partial
5
+ from typing import Dict, Optional, Sequence, Tuple, Union
6
+
7
+ import numpy as np
8
+ import pandas as pd
9
+ import sklearn.base
10
+ import xgboost as xgb
11
+ from sklearn.compose import TransformedTargetRegressor
12
+ from sklearn.preprocessing import StandardScaler
13
+ from sklearn.utils.validation import check_array, check_is_fitted, check_X_y
14
+ from xgboost import Booster
15
+
16
+ import openstef.metrics.metrics as metrics
17
+ from openstef.model.regressors.regressor import OpenstfRegressor
18
+
19
+ DEFAULT_QUANTILES: tuple[float, ...] = (0.9, 0.5, 0.1)
20
+
21
+
22
+ class XGBMultiOutputQuantileOpenstfRegressor(OpenstfRegressor):
23
+ r"""Model that provides multioutput quantile regression with XGBoost by default using the arctan loss function.
24
+
25
+ Arctan loss:
26
+ Refence: https://github.com/LaurensSluyterman/XGBoost_quantile_regression/tree/master
27
+ The key idea is to use a smooth approximation of the pinball loss, the arctan
28
+ pinball loss, that has a relatively large second derivative.
29
+
30
+ The approximation is given by:
31
+ $$L^{(\text{arctan})}_{\tau, s}(u) = (\tau - 0.5 + \frac{\arctan (u/s)}{\pi})u + \frac{s}{\pi}$$. # noqa E501
32
+
33
+ Some important settings:
34
+
35
+ * The parameter in the loss function determines the amount of smoothing. A
36
+ smaller values gives a closer approximation but also a much smaller second
37
+ derivative. A larger value gives more conservative quantiles when
38
+ is larger than 0.5, the quantile becomes larger and vice versa.
39
+ Values between 0.05 and 0.1 appear to work well. It may be a good idea to
40
+ optimize this parameter.
41
+ * Set min-child-weight to zero. The second derivatives can be a lot smaller
42
+ than 1 and this parameter may prevent any splits.
43
+ * Use a relatively small max-delta-step. We used a default of 0.5.
44
+ This prevents excessive steps that could happen due to the relatively
45
+ small second derivative.
46
+ * For the same reason, use a slightly lower learning rate of 0.05.
47
+
48
+ """
49
+
50
+ estimator_: TransformedTargetRegressor
51
+ quantile_indices_: Dict[float, int]
52
+
53
+ @staticmethod
54
+ def _get_importance_names():
55
+ return {
56
+ "gain_importance_name": "total_gain",
57
+ "weight_importance_name": "weight",
58
+ }
59
+
60
+ def __init__(
61
+ self,
62
+ quantiles: tuple[float, ...] = DEFAULT_QUANTILES,
63
+ gamma: float = 0.0,
64
+ colsample_bytree: float = 1.0,
65
+ subsample: float = 1.0,
66
+ min_child_weight: int = 0,
67
+ max_depth: int = 6,
68
+ learning_rate: float = 0.22,
69
+ alpha: float = 0.0,
70
+ max_delta_step: int = 0.5,
71
+ arctan_smoothing: float = 0.055,
72
+ early_stopping_rounds: Optional[int] = None,
73
+ ):
74
+ """Initialize XGBMultiQuantileRegressor.
75
+
76
+ Model that provides quantile regression with XGBoost.
77
+ For each desired quantile an XGBoost model is trained,
78
+ these can later be used to predict quantiles.
79
+
80
+ Args:
81
+ quantiles: Tuple with desired quantiles, quantile 0.5 is required.
82
+ For example: (0.1, 0.5, 0.9)
83
+ gamma: Gamma.
84
+ colsample_bytree: Colsample by tree.
85
+ subsample: Subsample.
86
+ min_child_weight: Minimum child weight.
87
+ max_depth: Maximum depth.
88
+ learning_rate: Learning rate.
89
+ alpha: Alpha.
90
+ max_delta_step: Maximum delta step.
91
+ arctan_smoothing: smoothing parameter of the arctan loss function.
92
+ early_stopping_rounds: Number of rounds to stop training if no improvement
93
+ is made.
94
+
95
+ Raises:
96
+ ValueError in case quantile 0.5 is not in the requested quantiles.
97
+
98
+ """
99
+ super().__init__()
100
+ if 0.5 not in quantiles:
101
+ raise ValueError(
102
+ "Cannot train quantile model as 0.5 is not in requested quantiles!"
103
+ )
104
+
105
+ self.quantiles = quantiles
106
+
107
+ # Set attributes for hyper parameters
108
+ self.subsample = subsample
109
+ self.min_child_weight = min_child_weight
110
+ self.max_depth = max_depth
111
+ self.gamma = gamma
112
+ self.alpha = alpha
113
+ self.max_delta_step = max_delta_step
114
+ self.colsample_bytree = colsample_bytree
115
+ self.learning_rate = learning_rate
116
+ self.early_stopping_rounds = early_stopping_rounds
117
+ self.arctan_smoothing = arctan_smoothing
118
+
119
+ # Get fitting parameters - only those required for xgbooster's
120
+ xgb_regressor_params = {
121
+ key: value
122
+ for key, value in self.get_params().items()
123
+ if key in xgb.XGBRegressor().get_params().keys()
124
+ }
125
+
126
+ # Define the model
127
+ objective = partial(
128
+ metrics.arctan_loss, taus=self.quantiles, s=arctan_smoothing
129
+ )
130
+ xgb_model: xgb.XGBRegressor = xgb.XGBRegressor(
131
+ objective=objective,
132
+ base_score=0,
133
+ multi_strategy="one_output_per_tree",
134
+ **xgb_regressor_params,
135
+ )
136
+ self.estimator_ = TransformedTargetRegressor(
137
+ regressor=xgb_model, transformer=StandardScaler()
138
+ )
139
+
140
+ # Set quantile indices to remap multioutput predictions
141
+ self.quantile_indices_ = {
142
+ quantile: i for i, quantile in enumerate(self.quantiles)
143
+ }
144
+
145
+ def fit(
146
+ self,
147
+ x: np.array,
148
+ y: np.array,
149
+ eval_set: Optional[Sequence[Tuple[np.array, np.array]]] = None,
150
+ verbose: Optional[Union[bool, int]] = 0,
151
+ **kwargs
152
+ ) -> OpenstfRegressor:
153
+ """Fits xgb quantile model.
154
+
155
+ Args:
156
+ x: Feature matrix.
157
+ y: Labels.
158
+ eval_set: Evaluation set to monitor training performance.
159
+ verbose: Verbosity level (disabled by default).
160
+
161
+ Returns:
162
+ Fitted XGBQuantile model.
163
+
164
+ """
165
+ if isinstance(y, pd.Series):
166
+ y = y.to_numpy()
167
+
168
+ if not isinstance(x, pd.DataFrame):
169
+ x = pd.DataFrame(np.asarray(x))
170
+
171
+ # Check/validate input
172
+ check_X_y(x, y, force_all_finite="allow-nan")
173
+
174
+ # Prepare inputs
175
+ y_multioutput = replicate_for_multioutput(y, len(self.quantiles))
176
+
177
+ # Define watchlist if eval_set is defined
178
+ eval_set_multioutput = []
179
+ if eval_set:
180
+ for x_eval, y_eval in eval_set:
181
+ if isinstance(y_eval, pd.Series):
182
+ y_eval = y_eval.to_numpy()
183
+
184
+ y_eval_multioutput = replicate_for_multioutput(
185
+ y=y_eval, num_quantiles=len(self.quantiles)
186
+ )
187
+ eval_set_multioutput.append((x_eval, y_eval_multioutput))
188
+
189
+ eval_set_multioutput.append((x, y_multioutput))
190
+
191
+ self.estimator_.fit(
192
+ X=x.copy(deep=True),
193
+ y=y_multioutput,
194
+ eval_set=eval_set_multioutput,
195
+ verbose=verbose,
196
+ )
197
+
198
+ # Update state of the estimator
199
+ self.feature_importances_ = self.estimator_.regressor_.feature_importances_
200
+ self.is_fitted_ = True
201
+
202
+ return self
203
+
204
+ def predict(self, x: np.array, quantile: float = 0.5) -> np.array:
205
+ """Makes a prediction for a desired quantile.
206
+
207
+ Args:
208
+ x: Feature matrix.
209
+ quantile: Quantile for which a prediciton is desired,
210
+ note that only quantile are available for which a model is trained,
211
+ and that this is a quantile-model specific keyword.
212
+
213
+ Returns:
214
+ Prediction
215
+
216
+ Raises:
217
+ ValueError in case no model is trained for the requested quantile.
218
+
219
+ """
220
+ # Check if model is trained for this quantile
221
+ if quantile not in self.quantiles:
222
+ raise ValueError("No model trained for requested quantile!")
223
+
224
+ # Check/validate input
225
+ check_array(x, force_all_finite="allow-nan")
226
+ check_is_fitted(self)
227
+
228
+ # best_iteration is only available if early stopping was used during training
229
+ prediction: np.array
230
+ if hasattr(self.estimator_, "best_iteration"):
231
+ prediction = self.estimator_.predict(
232
+ X=x,
233
+ iteration_range=(0, self.estimator_.best_iteration + 1),
234
+ )
235
+ else:
236
+ prediction = self.estimator_.predict(X=x)
237
+
238
+ quantile_index = self.quantile_indices_[quantile]
239
+ return prediction[:, quantile_index]
240
+
241
+ @property
242
+ def feature_names(self):
243
+ return self.estimator_.feature_names_in_
244
+
245
+ @property
246
+ def can_predict_quantiles(self):
247
+ return True
248
+
249
+
250
+ def replicate_for_multioutput(y: np.array, num_quantiles: int) -> np.array:
251
+ """Replicates a 1D array to a 2D array for multioutput regression.
252
+
253
+ Args:
254
+ y: 1D array.
255
+ num_quantiles: Number of columns in the output array.
256
+
257
+ Returns:
258
+ 2D array with shape (len(y), num_quantiles)
259
+
260
+ """
261
+ return np.repeat(y[:, None], num_quantiles, axis=1)
@@ -18,7 +18,7 @@ from openstef.settings import Settings
18
18
 
19
19
  # Set the path for the Dazls stored model
20
20
  DAZLS_STORED = str(
21
- PROJECT_ROOT / "openstef" / "data" / "dazls_model_3.4.7" / "dazls_stored_3.4.7_"
21
+ PROJECT_ROOT / "openstef" / "data" / "dazls_model_3.4.24" / "dazls_stored_3.4.24_"
22
22
  )
23
23
 
24
24
 
@@ -113,24 +113,7 @@ def create_components_forecast_pipeline(
113
113
  # Save and load the model as .sav file (or as .z file)
114
114
  # For the code contact: korte.termijn.prognoses@alliander.com
115
115
  dazls_model = Dazls()
116
- dazls_model.domain_model = joblib.load(DAZLS_STORED + "domain_model.z")
117
- dazls_model.domain_model_scaler = joblib.load(
118
- DAZLS_STORED + "domain_model_scaler.z"
119
- )
120
- dazls_model.domain_model_input_columns = joblib.load(
121
- DAZLS_STORED + "domain_model_features.z"
122
- )
123
-
124
- dazls_model.adaptation_model = joblib.load(DAZLS_STORED + "adaptation_model.z")
125
- dazls_model.adaptation_model_scaler = joblib.load(
126
- DAZLS_STORED + "adaptation_model_scaler.z"
127
- )
128
- dazls_model.adaptation_model_input_columns = joblib.load(
129
- DAZLS_STORED + "adaptation_model_features.z"
130
- )
131
-
132
- dazls_model.target_columns = joblib.load(DAZLS_STORED + "target.z")
133
- dazls_model.target_scaler = joblib.load(DAZLS_STORED + "target_scaler.z")
116
+ dazls_model.model_ = joblib.load(DAZLS_STORED + "baseline_model.z")
134
117
 
135
118
  logger.info("DAZLS model loaded", dazls_model=str(dazls_model))
136
119
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openstef
3
- Version: 3.4.23
3
+ Version: 3.4.25
4
4
  Summary: Open short term energy forecaster
5
5
  Home-page: https://github.com/OpenSTEF/openstef
6
6
  Author: Alliander N.V
@@ -128,4 +128,4 @@ Please read [CODE_OF_CONDUCT.md](https://github.com/OpenSTEF/.github/blob/main/C
128
128
 
129
129
  # Contact
130
130
  Please read [SUPPORT.md](https://github.com/OpenSTEF/.github/blob/main/SUPPORT.md) for how to connect and get into contact with the OpenSTEF project
131
-
131
+
@@ -1,35 +1,17 @@
1
1
  openstef/__init__.py,sha256=93UM6m0LLQhO69-mSqLuUy73jgs4W7Iuxfo3Lm8c98g,419
2
2
  openstef/__main__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
3
3
  openstef/app_settings.py,sha256=EJTDtimctFQQ-3f7ZcOQaRYohpZk3JD6aZBWPFYM2_A,582
4
- openstef/enums.py,sha256=LRKvmrCP_ntLE-r-AzKeSGt569WUfX0uX5db8Rk_Ag8,669
4
+ openstef/enums.py,sha256=i2EujJ6giJpzcxQYyVtr07D6DFnAmJpS7KEByZ2chMw,727
5
5
  openstef/exceptions.py,sha256=U4u2LTcdT6cmzpipT2Jh7kq9nCjT_-6gntn8yjuhGU0,1993
6
6
  openstef/settings.py,sha256=nSgkBqFxuqB3w7Rwo60i8j37c5ngDbt6vpjHS6QtJXQ,354
7
7
  openstef/data/dutch_holidays_2020-2022.csv,sha256=pS-CjE0igYXd-2dG-MlqyvR2fgYgXkbNmgCKyTjmwxs,23704
8
8
  openstef/data/dutch_holidays_2020-2022.csv.license,sha256=AxxHusqwIXU5RHl5ZMU65LyXmgtbj6QlcnFaOEN4kEE,145
9
9
  openstef/data/pv_single_coefs.csv,sha256=jadIEYdHvl1lnV_06X_FASkJZ6C3Hecs5xZnH1gPMvI,24779
10
10
  openstef/data/pv_single_coefs.csv.license,sha256=AxxHusqwIXU5RHl5ZMU65LyXmgtbj6QlcnFaOEN4kEE,145
11
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_adaptation_model.z,sha256=BRtD0Wr9DmMJypYxdWOY2xHFe_tg0-Jz9nnlInvswHM,29609700
12
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_adaptation_model.z.license,sha256=AxxHusqwIXU5RHl5ZMU65LyXmgtbj6QlcnFaOEN4kEE,145
13
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_adaptation_model_features.z,sha256=J9mF1mqfVwrZoyzJ8VoWPehKIoGtRakfe1a1m5lZt5I,88
14
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_adaptation_model_features.z.license,sha256=AxxHusqwIXU5RHl5ZMU65LyXmgtbj6QlcnFaOEN4kEE,145
15
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_adaptation_model_scaler.z,sha256=qukM4z9nZBi_70-1Y5RXpB2tEOwt8oI3KlDVkhnpnVM,879
16
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_adaptation_model_scaler.z.license,sha256=AxxHusqwIXU5RHl5ZMU65LyXmgtbj6QlcnFaOEN4kEE,145
17
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_domain_model.z,sha256=Sissl8ax7pm7Y3zWeoE350GTC3-Dl6iAEQl5_zbZe7g,32608923
18
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_domain_model.z.license,sha256=AxxHusqwIXU5RHl5ZMU65LyXmgtbj6QlcnFaOEN4kEE,145
19
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_domain_model_features.z,sha256=UUwyRZcUl4S884R86bL-8g9llaDHINmW5-WRoMJF0Do,123
20
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_domain_model_features.z.license,sha256=AxxHusqwIXU5RHl5ZMU65LyXmgtbj6QlcnFaOEN4kEE,145
21
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_domain_model_scaler.z,sha256=MddERJN1LmFrgSgzEnIxrpvbL8-dn4iLsyCMXBQDs8o,1173
22
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_domain_model_scaler.z.license,sha256=AxxHusqwIXU5RHl5ZMU65LyXmgtbj6QlcnFaOEN4kEE,145
23
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_model_card.md,sha256=HwYMHaYLqIZbxKbZEDVstp30P0VENLRdlVQJnmFxFqo,534
24
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_model_card.md.license,sha256=AxxHusqwIXU5RHl5ZMU65LyXmgtbj6QlcnFaOEN4kEE,145
25
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_target.z,sha256=7GkwwyQPJosqmGa0LslpfYIf8qgLDMW9Krx8CM_YO10,40
26
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_target.z.license,sha256=AxxHusqwIXU5RHl5ZMU65LyXmgtbj6QlcnFaOEN4kEE,145
27
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_target_scaler.z,sha256=HFldCZItBFxDkFrtg36RS-zyrHHGKOILXya-_hmluYM,686
28
- openstef/data/dazls_model_3.4.7/dazls_stored_3.4.7_target_scaler.z.license,sha256=AxxHusqwIXU5RHl5ZMU65LyXmgtbj6QlcnFaOEN4kEE,145
29
11
  openstef/data_classes/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
30
12
  openstef/data_classes/data_prep.py,sha256=gRSL7UiHvZis8m8z7VoTCZc0Ccffhef5_hmSyApnqK0,3417
31
13
  openstef/data_classes/model_specifications.py,sha256=Uod1W3QzhRqVLb6zvXwxh9wRL3EHCzSvX0oDNd28cFk,1197
32
- openstef/data_classes/prediction_job.py,sha256=t4PtGFWAX27AeaqDOtdhECuiosuCiuL0hBK7D1l3ghU,5165
14
+ openstef/data_classes/prediction_job.py,sha256=hjJmOBzVNEb3w3Iqh6e1nSoHmToentMwnEghnvHodpI,5206
33
15
  openstef/data_classes/split_function.py,sha256=ljQIQQu1t1Y_CVWGAy25jrM6wG9odIVVQVimrT1n-1s,3358
34
16
  openstef/feature_engineering/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
35
17
  openstef/feature_engineering/apply_features.py,sha256=-3fyisOVj9ckIkRe2iYfWutbXSX8iqBkcvt8AYr-gmE,3906
@@ -43,15 +25,15 @@ openstef/feature_engineering/missing_values_transformer.py,sha256=pKz_vRZRzfUNBw
43
25
  openstef/feature_engineering/weather_features.py,sha256=Lr9DItyHvJ2CpWQ1r6A83tJKtR2k_Wwn32FdFTGblO0,15750
44
26
  openstef/metrics/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
45
27
  openstef/metrics/figure.py,sha256=KDoezYem9wdS13kUx7M7FOy-4u88Sg3OX1DuhNT6kgQ,9751
46
- openstef/metrics/metrics.py,sha256=t2BIqflvmwzfa6UqS5jpAtNvailpDgD0J09bxjvGlMc,13341
28
+ openstef/metrics/metrics.py,sha256=si93EP2i34v3IPg-nOcm_aheoFAdu46i3azV_PjPmF8,15237
47
29
  openstef/metrics/reporter.py,sha256=w1Q6xWoYGmvnjwjXik-Gz7_gnb0lOeJMep-whEV5mNk,7897
48
30
  openstef/model/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
49
31
  openstef/model/basecase.py,sha256=caI6Q-8y0ymlxGK9Js_H3Vh0q6ruNHlGD5RG0_kE5M0,2878
50
32
  openstef/model/confidence_interval_applicator.py,sha256=XAk3m4gPhneCoQJlOmyEcoeI0sdHNC-ch4T1CWWHPrQ,8934
51
33
  openstef/model/fallback.py,sha256=VV9ehgnoMZtWzqKk9H1t8wnERFh5CyC4TvDIuRP_ZDI,2861
52
- openstef/model/model_creator.py,sha256=XQXtYI_q4Q2a2P-8I3lUuTMZqet3nqsNE7mzmjNsxIg,5310
53
- openstef/model/objective.py,sha256=eqNBYGfhEVGegOm0PbizowuFImKblRqHgxkp9lgaKQc,13500
54
- openstef/model/objective_creator.py,sha256=Rjd2YF1Ie9Z-au_v4fOuR63IcM69EEeoe_5Hj_Dz8-E,1970
34
+ openstef/model/model_creator.py,sha256=rQI7aEUcNI58x43vHmIRCIhymCis56SfLo3bhPBn410,5755
35
+ openstef/model/objective.py,sha256=2wPoONbk11WbySyPyqFMmXBx2lDFeUq_7jFPaCNETao,14572
36
+ openstef/model/objective_creator.py,sha256=_qIjq0ckrVIFr7k0L0NN0WyF0LIDaEYWA9NtVLzGs9g,2167
55
37
  openstef/model/serializer.py,sha256=IUiiAWvoGVoWzmS-akI6LC7jHRY5Ln_vOCBZy1LnESY,17238
56
38
  openstef/model/standard_deviation_generator.py,sha256=Od9bzXi2TLb1v8Nz-VhBMZHSopWH6ssaDe8gYLlqO1I,2911
57
39
  openstef/model/metamodels/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
@@ -60,12 +42,13 @@ openstef/model/metamodels/missing_values_handler.py,sha256=veyvYZHhKvlYZxaUpxRQ7
60
42
  openstef/model/regressors/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
61
43
  openstef/model/regressors/arima.py,sha256=wt7FVykjSvljpl7vjtliq61SiyjQ7KKtw8PF9x0xf04,7587
62
44
  openstef/model/regressors/custom_regressor.py,sha256=Hsmxahc9nfSWD0aEZ6cm4pxW2noQ8B1SujS17_fmxcU,1768
63
- openstef/model/regressors/dazls.py,sha256=cCYFewJEv3Fn01wdZpaKNSiYmEwzuED7PQrrWzwyTEg,8084
45
+ openstef/model/regressors/dazls.py,sha256=dQMx11kfMZCl4K61n8Dug2CyBhjlmiw3-ilv7KmowqM,3990
64
46
  openstef/model/regressors/lgbm.py,sha256=zCdn1euEdSFxYJzH8XqQFFnb6R4JVUnmineKjX_Gy-g,800
65
47
  openstef/model/regressors/linear.py,sha256=uOvZMLGZH_9nXfmS5honCMfyVeyGXP1Cza9A_BdXlVw,3665
66
48
  openstef/model/regressors/linear_quantile.py,sha256=N-cia8aba39Th6BzOdtcESLuxhY9YtSGaOYIc6STgag,7830
67
49
  openstef/model/regressors/regressor.py,sha256=uJcx59AyCPE9f_yPcAQ59h2ZS7eNsDpIHJrladKvHIw,3461
68
50
  openstef/model/regressors/xgb.py,sha256=HggA1U10srzdysjV560BMMX66kfaxCKAnOZB3JyyT_Y,808
51
+ openstef/model/regressors/xgb_multioutput_quantile.py,sha256=xWzA7tymC_o-F1OS3I7vUKf9zP6RR1ZglEeY4NAgjU0,9146
69
52
  openstef/model/regressors/xgb_quantile.py,sha256=PzKIxqN_CnEPFmzXACNuzLSmZSHbooTuiJ5ckJ9vh_E,7805
70
53
  openstef/model_selection/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
71
54
  openstef/model_selection/model_selection.py,sha256=R34tJBecZo6IiUwCCRLeBI2ZCX6GP8W7FDBlGFWtmG8,11167
@@ -74,7 +57,7 @@ openstef/monitoring/performance_meter.py,sha256=6aCGjJFXFq-7qwaJyBkF3MLqjgVK6FMF
74
57
  openstef/monitoring/teams.py,sha256=A-tlZeuAgolxFHjgT3gGjraxzW2dmuB-UAOz4xgYNIQ,6668
75
58
  openstef/pipeline/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
76
59
  openstef/pipeline/create_basecase_forecast.py,sha256=YkpiqohETTAETb4GiVlK_btw5dpixJy2LmFZdm10iaI,4623
77
- openstef/pipeline/create_component_forecast.py,sha256=A0dmILy_BuAAf2U_9i2FOj6KItIdZdGzi6hNDk-da4Q,6416
60
+ openstef/pipeline/create_component_forecast.py,sha256=XlE9oo37qwmZPE2Dgg19CDfFPRKgrLuyW069pS035UQ,5668
78
61
  openstef/pipeline/create_forecast.py,sha256=F09civdIumNQwJq2hraea5QTQx7DgvEliXKs4Y3f8Mc,5689
79
62
  openstef/pipeline/optimize_hyperparameters.py,sha256=3SLkcLR7XC4IeN48C-XT_lxlfCqW_D0NoMpZcrB9UUM,11045
80
63
  openstef/pipeline/train_create_forecast_backtest.py,sha256=-kZqCWal5zYLL0k0Sapks1zTmU5unNAooVPaPos1_7E,6050
@@ -100,8 +83,8 @@ openstef/tasks/utils/predictionjobloop.py,sha256=Ysy3zF5lzPMz_asYDKeF5m0qgVT3tCt
100
83
  openstef/tasks/utils/taskcontext.py,sha256=L9K14ycwgVxbIVUjH2DIn_QWbnu-OfxcGtQ1K9T6sus,5630
101
84
  openstef/validation/__init__.py,sha256=bIyGTSA4V5VoOLTwdaiJJAnozmpSzvQooVYlsf8H4eU,163
102
85
  openstef/validation/validation.py,sha256=628xaDbAm8B4AYtFOAn8_SXLjejNfULGCfX3hVf_mU0,11119
103
- openstef-3.4.23.dist-info/LICENSE,sha256=7Pm2fWFFHHUG5lDHed1vl5CjzxObIXQglnYsEdtjo_k,14907
104
- openstef-3.4.23.dist-info/METADATA,sha256=ZtURJ-TH2PoNGcDMSM3F7sSASCuGOYUhI1i3qCzGlEY,7393
105
- openstef-3.4.23.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
106
- openstef-3.4.23.dist-info/top_level.txt,sha256=kD0H4PqrQoncZ957FvqwfBxa89kTrun4Z_RAPs_HhLs,9
107
- openstef-3.4.23.dist-info/RECORD,,
86
+ openstef-3.4.25.dist-info/LICENSE,sha256=7Pm2fWFFHHUG5lDHed1vl5CjzxObIXQglnYsEdtjo_k,14907
87
+ openstef-3.4.25.dist-info/METADATA,sha256=RahtAo0FrqIzmTJhj7dvqCRL53PlDod_bUGASwLxnKU,7394
88
+ openstef-3.4.25.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
89
+ openstef-3.4.25.dist-info/top_level.txt,sha256=kD0H4PqrQoncZ957FvqwfBxa89kTrun4Z_RAPs_HhLs,9
90
+ openstef-3.4.25.dist-info/RECORD,,
@@ -1,3 +0,0 @@
1
- SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com>
2
-
3
- SPDX-License-Identifier: MPL-2.0
@@ -1,3 +0,0 @@
1
- SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com>
2
-
3
- SPDX-License-Identifier: MPL-2.0
@@ -1,3 +0,0 @@
1
- SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com>
2
-
3
- SPDX-License-Identifier: MPL-2.0
@@ -1,3 +0,0 @@
1
- SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com>
2
-
3
- SPDX-License-Identifier: MPL-2.0
@@ -1,2 +0,0 @@
1
- x^%�;
2
- �0DS����#U�}� $c��
@@ -1,3 +0,0 @@
1
- SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com>
2
-
3
- SPDX-License-Identifier: MPL-2.0
@@ -1,3 +0,0 @@
1
- SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com>
2
-
3
- SPDX-License-Identifier: MPL-2.0
@@ -1,14 +0,0 @@
1
- "
2
- # Model details : dazls_model_test_eval
3
-
4
- ## Description
5
- **Model Name**: dazls_model_test_eval
6
- **Author**: KTP, Alliander
7
- **Model type**: Energy splitting model
8
- **Model Architecture**: KNeighestNeighbours
9
- **Date**: 2024-01-31
10
-
11
- ## Intended use
12
- This is a DAZLs model aimed at determining the energy splits for substations.
13
- Each of these splits are determined based on a set of features that are available in production,
14
- and in this case have their origin in the Dutch energy grid.
@@ -1,3 +0,0 @@
1
- SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com>
2
-
3
- SPDX-License-Identifier: MPL-2.0
@@ -1,3 +0,0 @@
1
- SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com>
2
-
3
- SPDX-License-Identifier: MPL-2.0
@@ -1,3 +0,0 @@
1
- SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com>
2
-
3
- SPDX-License-Identifier: MPL-2.0