From 9374b1f189060b12ae2af9abdbe51681b3401134 Mon Sep 17 00:00:00 2001 From: kohlhaasrebecca <rebecca.kohlhaas@outlook.com> Date: Thu, 14 Nov 2024 10:20:41 +0100 Subject: [PATCH] First tests for Sobol calculation --- .../surrogate_models/polynomial_chaos.py | 15 +++++---- tests/test_PolynomialChaosEmulator.py | 31 +++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/bayesvalidrox/surrogate_models/polynomial_chaos.py b/src/bayesvalidrox/surrogate_models/polynomial_chaos.py index ba8e0de1c..afedbe764 100644 --- a/src/bayesvalidrox/surrogate_models/polynomial_chaos.py +++ b/src/bayesvalidrox/surrogate_models/polynomial_chaos.py @@ -868,6 +868,8 @@ class PCE(MetaModel): pce_stds_b = {} for b_i in range(self.n_bootstrap_itrs): + pce_means_b[b_i] = {} + pce_stds_b[b_i] = {} _coeffs_dicts = self._coeffs_dict[f'b_{b_i + 1}'].items() for output, coef_dict in _coeffs_dicts: @@ -927,7 +929,7 @@ class PCE(MetaModel): return pce_means, pce_stds - def calculate_sobol(self): + def calculate_sobol(self, Y_train = None): """ Provides Sobol' indices as a sensitivity measure to infer the importance of the input parameters. See Eq. 27 in [1] for more details. For the @@ -945,7 +947,9 @@ class PCE(MetaModel): Parameters ---------- - None. + Y_train: dict, optional + Trainings outputs. They are needed when used in combination with PCA. + The default is None Returns ------- @@ -1057,8 +1061,7 @@ class PCE(MetaModel): # Compute the sobol indices according to Ref. 2 if self.dim_red_method.lower() == "pca": - # TODO: Update so that it does not use the ExpDesign anymore! - n_c_points = self.engine.ExpDesign.Y[output].shape[1] + n_c_points = Y_train[output].shape[1] pca = self.pca[f"b_{b_i+1}"][output] comp_pca = pca.components_ n_comp = comp_pca.shape[0] @@ -1076,7 +1079,7 @@ class PCE(MetaModel): for t_idx in range(n_c_points): var_yt = np.var( - self.engine.ExpDesign.Y[output][:, t_idx] + Y_train[output][:, t_idx] ) term1, term2 = 0.0, 0.0 if var_yt != 0.0: @@ -1103,7 +1106,7 @@ class PCE(MetaModel): s_zi = total_sobol_array[par_idx] for t_idx in range(n_c_points): - var_yt = np.var(self.engine.ExpDesign.Y[output][:, t_idx]) + var_yt = np.var(Y_train[output][:, t_idx]) term1, term2 = 0.0, 0.0 if var_yt != 0.0: for i in range(n_comp): diff --git a/tests/test_PolynomialChaosEmulator.py b/tests/test_PolynomialChaosEmulator.py index b62bd09da..64858588d 100644 --- a/tests/test_PolynomialChaosEmulator.py +++ b/tests/test_PolynomialChaosEmulator.py @@ -842,3 +842,34 @@ def test_calculate_moments_pca() -> None: #%% Test PCE.update_metamodel # TODO: taken from engine + + +#%% Test PCE.calculate_sobol + +def test_calculate_sobol(): + """ + Calculate Sobol' indices of a pce-surrogate + """ + inp = Input() + inp.add_marginals() + inp.Marginals[0].dist_type = 'normal' + inp.Marginals[0].parameters = [0, 1] + mm = PCE(inp) + mm.fit([[0.2], [0.8]], {'Z': [[0.4, 0.4], [0.5, 0.6]]}) + sobol, totalsobol = mm.calculate_sobol() + # TODO are there theory-related checks that could be applied here? + + +def test_calculate_sobol_pca(): + """ + Calculate Sobol' indices of a pce-surrogate with PCA + """ + inp = Input() + inp.add_marginals() + inp.Marginals[0].dist_type = 'normal' + inp.Marginals[0].parameters = [0, 1] + mm = PCE(inp) + mm.dim_red_method = 'pca' + mm.fit([[0.2], [0.8]], {'Z': [[0.4, 0.4], [0.5, 0.6]]}) + sobol, totalsobol = mm.calculate_sobol({'Z': np.array([[0.4, 0.4], [0.5, 0.6]])}) + # TODO are there theory-related checks that could be applied here? -- GitLab