-
-
Save tupui/09f065d6afc923d4c2f5d6d430e11696 to your computer and use it in GitHub Desktop.
"""Sobol' indices. | |
Compute Sobol' variance based sensitivity indices. | |
Use formulations from Saltelli2010. | |
Reference: | |
Saltelli et al. Variance based sensitivity analysis of model output. Design and estimator for the total sensitivity index, | |
Computer Physics Communications, 2010. DOI: 10.1016/j.cpc.2009.09.018 | |
--------------------------- | |
MIT License | |
Copyright (c) 2018 Pamphile Tupui ROY | |
Permission is hereby granted, free of charge, to any person obtaining a copy | |
of this software and associated documentation files (the "Software"), to deal | |
in the Software without restriction, including without limitation the rights | |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
copies of the Software, and to permit persons to whom the Software is | |
furnished to do so, subject to the following conditions: | |
The above copyright notice and this permission notice shall be included in all | |
copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
SOFTWARE. | |
""" | |
import numpy as np | |
import itertools | |
def f_ishigami(x): | |
"""Ishigami function. | |
:param array_like x: [n, [x1, x2, x3]]. | |
:return: Function evaluation. | |
:rtype: array_like (n, 1) | |
""" | |
x = np.atleast_2d(x) | |
return np.array([np.sin(xi[0]) + 7 * np.sin(xi[1])**2 + \ | |
0.1 * (xi[2]**4) * np.sin(xi[0]) for xi in x]).reshape(-1, 1) | |
def sobol(func, n_sample, dim, *, bounds=None, seed=None): | |
"""Sobol' indices. | |
The total number of function call is N(p+2). | |
Three matrices are required for the computation of | |
the indices: A, B and a permutation matrix AB based | |
on both A and B. | |
:param callable func: Function to analyse. | |
:param int n_sample: Number of samples. | |
:param int dim: Number of dimensions. | |
:param array_like bounds: Desired range of transformed data. | |
The transformation apply the bounds on the sample and not | |
the theoretical space, unit cube. Thus min and | |
max values of the sample will coincide with the bounds. | |
([min, n_features], [max, n_features]). | |
:param seed: Seed of the random number generator. | |
:return: first orders and total orders indices. | |
:rtype: list(float) (n_features), list(float) (n_features) | |
""" | |
rng = np.random.default_rng(seed) | |
A = rng.random((n_sample, dim)) | |
B = rng.random((n_sample, dim)) | |
if bounds is not None: | |
bounds = np.asarray(bounds) | |
min_ = bounds.min(axis=0) | |
max_ = bounds.max(axis=0) | |
A = (max_ - min_) * A + min_ | |
B = (max_ - min_) * B + min_ | |
f_A = func(A) | |
f_B = func(B) | |
var = np.var(np.vstack([f_A, f_B]), axis=0) | |
# Total effect of pairs of factors: generalization of Saltenis | |
# st2 = np.zeros((dim, dim)) | |
# for j, i in itertools.combinations(range(0, dim), 2): | |
# st2[i, j] = 1 / (2 * n_sample) * np.sum((f_AB[i] - f_AB[j]) ** 2, axis=0) / var | |
f_AB = [] | |
for i in range(dim): | |
f_AB.append(func(np.column_stack((A[:, 0:i], B[:, i], A[:, i+1:])))) | |
f_AB = np.array(f_AB).reshape(dim, n_sample) | |
s = 1 / n_sample * np.sum(f_B * (np.subtract(f_AB, f_A.flatten()).T), axis=0) / var | |
st = 1 / (2 * n_sample) * np.sum(np.subtract(f_A.flatten(), f_AB).T ** 2, axis=0) / var | |
return s, st | |
print(f_ishigami([[0, 1, 3], [2, 4, 2]])) | |
indices = sobol(f_ishigami, 2000, 3, [[-np.pi, -np.pi, -np.pi], [np.pi, np.pi, np.pi]]) | |
print(indices) |
Hi Pamphile, thank you. I will take a look into your gists :)
HI Pamphile, sorry for all my questions!
With your experience and background, do you think that the best approach is "Cosine transformation sensitivity indice" for the first order of sensitivity indices? I was using first, second and Total Sobol Indices to quantify the influence of the parameters. But maybe Cosine transformation could be a better approach for only the First order... What do you think?
Regards,
Marc
HI Pamphile, sorry for all my questions!
No problem @marcrocasalonso 😄 (not sure if I need to ping you so you know I commented...)
With your experience and background, do you think that the best approach is "Cosine transformation sensitivity indice" for the first order of sensitivity indices? I was using first, second and Total Sobol Indices to quantify the influence of the parameters. But maybe Cosine transformation could be a better approach for only the First order... What do you think?
Personally I would stick with first and total indices of Sobol' (don't forget the '
, it's a diacritic part of the name 😉 ). COSI did not receive much validation, hence it might be harder to justify. If you need more information, moment independent methods are also a good alternative. And in case of correlations you can also use Shapley values.
thank you :) , I will try to go deeper into what you have told me.
@tupui Thanks for the notebook. However, I have one question. How can I use correlated variables in the code? Your response will be highly appreciated.
Hi @samdanicivilruet, thanks 😊 As I said above, Sobol’ is not well suited for correlated inputs. That’s a base assumption of the method. Instead I would suggest you to have a look at the moment independent method. I have a gist showing how this work and also SALib had an implementation.
@tupui thanks again for the clarification. I really appreciate it. Best regards
Hi @marcrocasalonso, thanks for checking this out. I did not, but you can find second order in SaLib. Personally I would not try to get third orders as their interpretation is quite complicated and they require a lot of computation. If you did not check it out, I have other gists that calculate SA using moment independent method instead (takes into account other moments, not just the variance).