surrogates_interface 4.1.1__tar.gz → 4.2.0__tar.gz

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.
@@ -1,18 +1,18 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: surrogates_interface
3
- Version: 4.1.1
3
+ Version: 4.2.0
4
4
  Summary: Interface for surrogate models.
5
5
  Home-page: https://gitlab.windenergy.dtu.dk/surrogate-models/surrogate-models-interface
6
6
  License: MIT
7
7
  Author: DTU Wind and Energy Systems
8
8
  Maintainer: Riccardo Riva
9
9
  Maintainer-email: ricriv@dtu.dk
10
- Requires-Python: >=3.9,<3.12
10
+ Requires-Python: >=3.10,<3.13
11
11
  Classifier: License :: OSI Approved :: MIT License
12
12
  Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.9
14
13
  Classifier: Programming Language :: Python :: 3.10
15
14
  Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
16
  Provides-Extra: code-style
17
17
  Provides-Extra: docs
18
18
  Provides-Extra: om
@@ -20,29 +20,29 @@ Provides-Extra: smt
20
20
  Provides-Extra: test
21
21
  Provides-Extra: tf
22
22
  Provides-Extra: torch
23
- Requires-Dist: black ; extra == "code-style"
24
- Requires-Dist: codespell ; extra == "code-style"
25
- Requires-Dist: flake8 ; extra == "code-style"
26
- Requires-Dist: h5py
27
- Requires-Dist: isort ; extra == "code-style"
28
- Requires-Dist: matplotlib ; extra == "test" or extra == "smt"
23
+ Requires-Dist: black (>=24.0.0,<25.0.0) ; extra == "code-style"
24
+ Requires-Dist: codespell (>=2.0.0,<3.0.0) ; extra == "code-style"
25
+ Requires-Dist: flake8 (>=7.0.0,<8.0.0) ; extra == "code-style"
26
+ Requires-Dist: h5py (>=3.10.0,<4.0.0)
27
+ Requires-Dist: isort (>=5.0.0,<6.0.0) ; extra == "code-style"
28
+ Requires-Dist: keras (>=3.0.0,<4.0.0) ; extra == "tf" or extra == "torch"
29
+ Requires-Dist: matplotlib (>=3.8.0,<4.0.0) ; extra == "test" or extra == "smt"
29
30
  Requires-Dist: numpy (>=1.10.0)
30
- Requires-Dist: numpydoc ; extra == "docs"
31
+ Requires-Dist: numpydoc (>=1.8.0,<2.0.0) ; extra == "docs"
31
32
  Requires-Dist: openmdao (>=3.25,<4.0) ; extra == "docs" or extra == "test" or extra == "om"
32
33
  Requires-Dist: pydata-sphinx-theme ; extra == "docs"
33
- Requires-Dist: pytest ; extra == "test"
34
- Requires-Dist: pytest-cov ; extra == "test"
35
- Requires-Dist: pytest-testmon ; extra == "test"
36
- Requires-Dist: scikit-learn ; extra == "test" or extra == "smt" or extra == "tf"
34
+ Requires-Dist: pytest (>=8.0.0,<9.0.0) ; extra == "test"
35
+ Requires-Dist: pytest-cov (>=6.0.0,<7.0.0) ; extra == "test"
36
+ Requires-Dist: scikit-learn (>=1.4.0,<2.0.0) ; extra == "test" or extra == "smt" or extra == "tf" or extra == "torch"
37
37
  Requires-Dist: smt (>=2.0.1,<3.0.0) ; extra == "test" or extra == "smt"
38
- Requires-Dist: sphinx ; extra == "docs"
38
+ Requires-Dist: sphinx (>=8.0.0,<9.0.0) ; extra == "docs"
39
39
  Requires-Dist: sphinx-copybutton ; extra == "docs"
40
- Requires-Dist: sphinx-sitemap ; extra == "docs"
40
+ Requires-Dist: sphinx-sitemap (>=2.0.0,<3.0.0) ; extra == "docs"
41
41
  Requires-Dist: sphinx_design ; extra == "docs"
42
42
  Requires-Dist: tensorflow (>=2.10.0,<3.0.0) ; extra == "test" or extra == "tf"
43
43
  Requires-Dist: tensorflow-intel (>=2.10.0,<3.0.0) ; (sys_platform == "win32") and (extra == "test" or extra == "tf")
44
- Requires-Dist: tensorflow-io-gcs-filesystem (<0.32.0) ; (python_version >= "3.9" and python_version < "3.12" and platform_system == "Windows") and (extra == "test" or extra == "tf")
45
- Requires-Dist: tensorflow-io-gcs-filesystem (>=0.23.1) ; (platform_machine != "arm64" and python_version >= "3.9" and python_version < "3.12" or platform_system != "Darwin" and python_version >= "3.9" and python_version < "3.12") and (extra == "test" or extra == "tf")
44
+ Requires-Dist: tensorflow-io-gcs-filesystem (<0.32.0) ; (python_version >= "3.10" and python_version < "3.12" and platform_system == "Windows") and (extra == "test" or extra == "tf")
45
+ Requires-Dist: tensorflow-io-gcs-filesystem (>=0.23.1) ; (platform_machine != "arm64" and python_version >= "3.10" and python_version < "3.12" or platform_system != "Darwin" and python_version >= "3.10" and python_version < "3.12") and (extra == "test" or extra == "tf")
46
46
  Requires-Dist: tomli (>=2.0.1,<3.0.0) ; (python_version < "3.11") and (extra == "test")
47
47
  Requires-Dist: torch (>=2.0.0,<3.0.0) ; extra == "test" or extra == "torch"
48
48
  Project-URL: Repository, https://gitlab.windenergy.dtu.dk/surrogate-models/surrogate-models-interface
@@ -55,7 +55,7 @@ Description-Content-Type: text/markdown
55
55
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
56
56
  [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
57
57
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
58
- [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.8282614.svg)](https://doi.org/10.5281/10.5281/zenodo.8282614)
58
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.8282614.svg)](https://doi.org/10.5281/zenodo.8282614)
59
59
 
60
60
  Provides a common interface to several surrogate models, including an OpenMDAO wrapper.
61
61
 
@@ -5,7 +5,7 @@
5
5
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
6
6
  [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
8
- [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.8282614.svg)](https://doi.org/10.5281/10.5281/zenodo.8282614)
8
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.8282614.svg)](https://doi.org/10.5281/zenodo.8282614)
9
9
 
10
10
  Provides a common interface to several surrogate models, including an OpenMDAO wrapper.
11
11
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "surrogates_interface"
3
- version = "4.1.1"
3
+ version = "4.2.0"
4
4
  description = "Interface for surrogate models."
5
5
  authors = ["DTU Wind and Energy Systems"]
6
6
  maintainers = [
@@ -16,33 +16,33 @@ generate-setup-file = false
16
16
 
17
17
  [tool.poetry.dependencies]
18
18
 
19
- python = ">=3.9,<3.12"
20
- numpy = ">=1.10.0"
21
- h5py = "*"
22
- black = {version="*", optional=true}
23
- flake8 = {version="*", optional=true}
24
- isort = {version="*", optional=true}
25
- codespell = {version="*", optional=true}
26
- pytest = {version="*", optional=true}
27
- pytest-cov = {version="*", optional=true}
28
- pytest-testmon = {version="*", optional=true}
19
+ python = ">=3.10,<3.13"
20
+ numpy = {version=">=1.10.0"}
21
+ h5py = {version="^3.10.0"}
22
+ black = {version="^24.0.0", optional=true}
23
+ flake8 = {version="^7.0.0", optional=true}
24
+ isort = {version="^5.0.0", optional=true}
25
+ codespell = {version="^2.0.0", optional=true}
26
+ pytest = {version="^8.0.0", optional=true}
27
+ pytest-cov = {version="^6.0.0", optional=true}
29
28
  tomli = {version="^2.0.1", python="<3.11", optional=true}
30
- sphinx = {version="*", optional=true}
29
+ sphinx = {version="^8.0.0", optional=true}
31
30
  pydata-sphinx-theme = {version="*", optional=true}
32
31
  sphinx-copybutton = {version="*", optional=true}
33
- sphinx-sitemap = {version="*", optional=true}
32
+ sphinx-sitemap = {version="^2.0.0", optional=true}
34
33
  sphinx_design = {version="*", optional=true}
35
- numpydoc = {version="*", optional=true}
36
- matplotlib = {version="*", optional=true}
37
- scikit-learn = {version="*", optional=true}
34
+ numpydoc = {version="^1.8.0", optional=true}
35
+ matplotlib = {version="^3.8.0", optional=true}
36
+ scikit-learn = {version="^1.4.0", optional=true}
38
37
  # The following configuration for TensorFlow seems to work on Windows and linux, as tested at
39
38
  # https://gitlab.windenergy.dtu.dk/surrogate-models/test-poetry-and-tensorflow
40
39
  tensorflow = {version = "^2.10.0", optional=true }
41
40
  tensorflow-io-gcs-filesystem = [
42
- {version = ">= 0.23.1", markers = "platform_machine!='arm64' or platform_system!='Darwin'", python=">=3.9,<3.12", optional=true},
43
- {version = "< 0.32.0", markers = "platform_system == 'Windows'", python=">=3.9,<3.12", optional=true}
41
+ {version = ">= 0.23.1", markers = "platform_machine!='arm64' or platform_system!='Darwin'", python=">=3.10,<3.12", optional=true},
42
+ {version = "< 0.32.0", markers = "platform_system == 'Windows'", python=">=3.10,<3.12", optional=true}
44
43
  ]
45
44
  tensorflow-intel = {version="^2.10.0", platform = "win32", optional=true}
45
+ keras = {version="^3.0.0", optional=true}
46
46
  smt = {version="^2.0.1", optional=true}
47
47
  openmdao = {version="^3.25", optional=true}
48
48
  torch = { version = "^2.0.0", optional=true }
@@ -67,7 +67,6 @@ code_style = ["black",
67
67
  test = ["matplotlib", # Needed by SMT.
68
68
  "pytest",
69
69
  "pytest-cov",
70
- "pytest-testmon",
71
70
  "tomli",
72
71
  "scikit-learn",
73
72
  "smt",
@@ -87,11 +86,15 @@ tf = ["scikit-learn",
87
86
  "tensorflow",
88
87
  "tensorflow-io-gcs-filesystem",
89
88
  "tensorflow-intel",
89
+ "keras",
90
90
  ]
91
91
 
92
92
  om = ["openmdao"]
93
93
 
94
- torch = ["torch"]
94
+ torch = ["torch",
95
+ "scikit-learn",
96
+ "keras",
97
+ ]
95
98
 
96
99
 
97
100
 
@@ -90,8 +90,8 @@ class SurrogateModelCompFD(om.ExplicitComponent):
90
90
  self.options.declare(
91
91
  "input_type",
92
92
  desc="""Type of the input.
93
- - If `InputOutputType.JOINED` there will be only 1 input named `input_name`.
94
- - If `InputOutputType.SPLIT` there will be 1 input per input channel. Their names will be taken from `model.input_names`.
93
+ - If `InputOutputType.JOINED` there will be only 1 input named `options["input_name"]`.
94
+ - If `InputOutputType.SPLIT` there will be 1 input per channel. Their names will be taken from `model.input_names`.
95
95
  """,
96
96
  check_valid=self._check_in_out_type,
97
97
  )
@@ -99,8 +99,8 @@ class SurrogateModelCompFD(om.ExplicitComponent):
99
99
  self.options.declare(
100
100
  "output_type",
101
101
  desc="""Type of the output.
102
- - If `InputOutputType.JOINED` there will be only 1 output named `output_name`.
103
- - If `InputOutputType.SPLIT` there will be 1 input per output channel. Their names will be taken from `model.output_names`.
102
+ - If `InputOutputType.JOINED` there will be only 1 output named `options["output_name"]`.
103
+ - If `InputOutputType.SPLIT` there will be 1 output per channel. Their names will be taken from `model.output_names`.
104
104
  """,
105
105
  check_valid=self._check_in_out_type,
106
106
  )
@@ -150,13 +150,13 @@ class SurrogateModelCompFD(om.ExplicitComponent):
150
150
  ----------
151
151
  inputs : dict
152
152
  Inputs.
153
- - If `input_type is InputOutputType.JOINED` we expect one input named `input_name` of shape `(n_points, n_inputs)`.
153
+ - If `input_type is InputOutputType.JOINED` we expect one input named `options["input_name"]` of shape `(n_points, n_inputs)`.
154
154
  - If `input_type is InputOutputType.SPLIT` we expect one input per feature of shape `(n_points,)`.
155
- The inputs will be stacked according to `input_names`.
155
+ The inputs will be stacked according to `model.input_names`.
156
156
  outputs : dict
157
157
  Outputs.
158
- - If `output_type is InputOutputType.JOINED` we expect one output named `output_name` of shape `(n_points, n_outputs)`.
159
- The outputs will be stacked according to `output_names`.
158
+ - If `output_type is InputOutputType.JOINED` we expect one output named `options["output_name"]` of shape `(n_points, n_outputs)`.
159
+ The outputs will be stacked according to `model.output_names`.
160
160
  - If `output_type is InputOutputType.SPLIT` we expect one output per feature of shape `(n_points,)`.
161
161
 
162
162
  Returns
@@ -240,9 +240,9 @@ class SurrogateModelComp(SurrogateModelCompFD):
240
240
  ----------
241
241
  inputs : dict
242
242
  Inputs.
243
- - If `input_type is InputOutputType.JOINED` we expect one input named `input_name` of shape `(n_points, n_inputs)`.
243
+ - If `input_type is InputOutputType.JOINED` we expect one input named `options["input_name"]` of shape `(n_points, n_inputs)`.
244
244
  - If `input_type is InputOutputType.SPLIT` we expect one input per feature of shape `(n_points,)`.
245
- The inputs will be stacked according to `input_names`.
245
+ The inputs will be stacked according to `model.input_names`.
246
246
  partials : dict
247
247
  Jacobian.
248
248
  - If `output_type is InputOutputType.JOINED` we expect one Jacobian of shape `(n_points, n_outputs)`.
@@ -364,6 +364,10 @@ class SurrogateModel:
364
364
  .. math::
365
365
  \hat{y} = g_1^{-1} \circ g_2^{-1} \circ \cdots \circ g_m^{-1} \circ \hat{\tilde{y}}
366
366
 
367
+ and by substitution we find
368
+
369
+ .. math::
370
+ \hat{y} = g_1^{-1}(g_2^{-1}(g_m^{-1}(s(f_n(f_2(f_1(x)))))))
367
371
 
368
372
  Parameters
369
373
  ----------
@@ -419,9 +423,26 @@ class SurrogateModel:
419
423
  raise NotImplementedError()
420
424
 
421
425
  def predict_output_and_jacobian(self, x, *args, **kwargs):
422
- """
426
+ r"""
423
427
  Predict the complete model output and Jacobian, including all input and output transformations.
424
428
 
429
+ Let's recall that the predicted output is given by
430
+
431
+ .. math::
432
+ \hat{y} = g_1^{-1}(g_2^{-1}(g_m^{-1}(s(f_n(f_2(f_1(x)))))))
433
+
434
+ By indicating with :math:`J_h(z)` the Jacobian of :math:`h` evaluated at :math:`z`, we obtain
435
+ the Jacobian of the predicted output by applying the chain rule
436
+
437
+ .. math::
438
+ J = &J_{g_1^{-1}}(g_2^{-1}(g_m^{-1}(s(f_n(f_2(f_1(x))))))) \\
439
+ &J_{g_2^{-1}}(g_m^{-1}(s(f_n(f_2(f_1(x)))))) \\
440
+ &J_{g_m^{-1}}(s(f_n(f_2(f_1(x))))) \\
441
+ &J_{s}(f_n(f_2(f_1(x)))) \\
442
+ &J_{f_n}(f_2(f_1(x)))
443
+ J_{f_2}(f_1(x))
444
+ J_{f_1}(x)
445
+
425
446
  Parameters
426
447
  ----------
427
448
  x : array-like of shape (n_points, n_inputs)
@@ -125,7 +125,7 @@ class GainOffsetScaler(Transformer):
125
125
  x : array-like of shape (n_points, n_features)
126
126
  Input data that will be transformed.
127
127
  inplace : bool
128
- `True` if the transformation must happen inplace. Same behavior of the `copy` attribute in scikit-learn.
128
+ `True` if the transformation must happen inplace, which means that no additional memory is allocated.
129
129
 
130
130
  Returns
131
131
  -------
@@ -147,7 +147,7 @@ class GainOffsetScaler(Transformer):
147
147
  x : array-like of shape (n_points, n_features)
148
148
  Input data that will be transformed.
149
149
  inplace : bool
150
- True if the transformation must happen inplace. Same behavior of the `copy` attribute in scikit-learn.
150
+ `True` if the transformation must happen inplace, which means that no additional memory is allocated.
151
151
 
152
152
  Returns
153
153
  -------
@@ -173,6 +173,7 @@ class GainOffsetScaler(Transformer):
173
173
  -------
174
174
  y : array-like of shape (n_points, n_features)
175
175
  Gradient of the direct transformation evaluated on the input data.
176
+ Since all features are independent, the gradient is stored in compact form.
176
177
  Warning: a read-only view is returned.
177
178
  """
178
179
  y = np.broadcast_to(self.gain_, x.shape)
@@ -190,6 +191,7 @@ class GainOffsetScaler(Transformer):
190
191
  -------
191
192
  y : array-like of shape (n_points, n_features)
192
193
  Gradient of the inverse transformation evaluated on the input data.
194
+ Since all features are independent, the gradient is stored in compact form.
193
195
  Warning: a read-only view is returned.
194
196
  """
195
197
  y = np.broadcast_to(self.inv_gain_, x.shape)
@@ -344,7 +346,7 @@ class PCA(Transformer):
344
346
  x : ndarray of shape (n_points, n_features)
345
347
  Input data that will be transformed.
346
348
  inplace : bool, optional
347
- Must be `False`. Although it would be possible to to update the first `n_components` columns of `x`,
349
+ Must be `False`. Although it would be possible to update the first `n_components` columns of `x`,
348
350
  we choose to not do it, so that `predict_output()` can be supported more easily.
349
351
 
350
352
  Returns
@@ -527,7 +529,7 @@ class PowerTransformerYeoJohnson(Transformer):
527
529
  x : array-like of shape (n_points, n_features)
528
530
  Input data that will be transformed.
529
531
  inplace : bool
530
- `True` if the transformation must happen inplace. Same behavior of the `copy` attribute in scikit-learn.
532
+ `True` if the transformation must happen inplace, which means that no additional memory is allocated.
531
533
 
532
534
  Returns
533
535
  -------
@@ -627,7 +629,7 @@ class PowerTransformerYeoJohnson(Transformer):
627
629
  x : array-like of shape (n_points, n_features)
628
630
  Input data that will be transformed.
629
631
  inplace : bool
630
- True if the transformation must happen inplace. Same behavior of the `copy` attribute in scikit-learn.
632
+ `True` if the transformation must happen inplace, which means that no additional memory is allocated.
631
633
 
632
634
  Returns
633
635
  -------
@@ -726,6 +728,7 @@ class PowerTransformerYeoJohnson(Transformer):
726
728
  -------
727
729
  y : array-like of shape (n_points, n_features)
728
730
  Gradient of the transformation evaluated on the input data.
731
+ Since all features are independent, the gradient is stored in compact form.
729
732
  """
730
733
  y = np.zeros_like(x)
731
734
 
@@ -780,6 +783,7 @@ class PowerTransformerYeoJohnson(Transformer):
780
783
  -------
781
784
  y : array-like of shape (n_points, n_features)
782
785
  Gradient of the inverse transformation evaluated on the input data.
786
+ Since all features are independent, the gradient is stored in compact form.
783
787
  """
784
788
  y = np.zeros_like(x)
785
789
 
@@ -817,39 +821,50 @@ class PowerTransformerYeoJohnson(Transformer):
817
821
 
818
822
 
819
823
  class StandardScalerTorch(StandardScaler):
820
- import torch
821
824
 
822
825
  def __init__(self, scale, mean):
826
+ import torch
827
+
823
828
  super().__init__(scale, mean)
824
- device = self.torch.device("cuda" if self.torch.cuda.is_available() else "cpu")
829
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
825
830
  self.device = device
826
831
  def __np2torch(v): # fmt: skip
827
- return self.torch.as_tensor(v).to(device)
832
+ return torch.as_tensor(v).to(device)
828
833
  self.gain_ = __np2torch(self.gain_)
829
834
  self.inv_gain_ = __np2torch(self.inv_gain_)
830
835
  self.offset_ = __np2torch(self.offset_)
831
836
 
832
837
  def transform(self, x, inplace=True):
838
+ import torch
839
+
833
840
  if inplace:
834
841
  raise ValueError("No inplace...")
835
- x = self.torch.as_tensor(x, device=self.device, dtype=self.torch.float32)
842
+ x = torch.as_tensor(x, device=self.device, dtype=torch.float32)
836
843
  return super().transform(x, inplace)
837
844
 
838
845
  def inverse_transform(self, x, inplace=True):
846
+ import torch
847
+
839
848
  if inplace:
840
849
  raise ValueError("No inplace...")
841
- x = self.torch.as_tensor(x, device=self.device, dtype=self.torch.float32)
850
+ x = torch.as_tensor(x, device=self.device, dtype=torch.float32)
842
851
  return super().inverse_transform(x, inplace)
843
852
 
844
853
  def transform_gradient(self, x):
845
- return self.torch.broadcast_to(self.gain_, x.shape).numpy()
854
+ import torch
855
+
856
+ return torch.broadcast_to(self.gain_, x.shape).numpy()
846
857
 
847
858
  def inverse_transform_gradient(self, x):
848
- return self.torch.broadcast_to(self.inv_gain_, x.shape).numpy()
859
+ import torch
860
+
861
+ return torch.broadcast_to(self.inv_gain_, x.shape).numpy()
849
862
 
850
863
  def __eq__(self, other):
864
+ import torch
865
+
851
866
  if isinstance(other, self.__class__):
852
- test_gain = self.torch.equal(self.gain_, other.gain_)
853
- test_offset = self.torch.equal(self.offset_, other.offset_)
867
+ test_gain = torch.equal(self.gain_, other.gain_)
868
+ test_offset = torch.equal(self.offset_, other.offset_)
854
869
  return test_gain and test_offset
855
870
  return False