def fit(self, X, y, **fit_params): input_dimension = X.shape[1] if self.distribution is None: self.distribution = BuildDistribution(X) if self.enumerate == 'linear': enumerateFunction = ot.LinearEnumerateFunction(input_dimension) elif self.enumerate == 'hyperbolic': enumerateFunction = ot.HyperbolicAnisotropicEnumerateFunction(input_dimension, self.q) else: raise ValueError('enumerate should be "linear" or "hyperbolic"') polynomials = [ot.StandardDistributionPolynomialFactory(self.distribution.getMarginal(i)) for i in range(input_dimension)] productBasis = ot.OrthogonalProductPolynomialFactory(polynomials, enumerateFunction) adaptiveStrategy = ot.FixedStrategy(productBasis, enumerateFunction.getStrataCumulatedCardinal(self.degree)) if self.sparse: projectionStrategy = ot.LeastSquaresStrategy(ot.LeastSquaresMetaModelSelectionFactory(ot.LARS(), ot.CorrectedLeaveOneOut())) else: projectionStrategy = ot.LeastSquaresStrategy(X, y.reshape(-1, 1)) algo = ot.FunctionalChaosAlgorithm(X, y.reshape(-1, 1), self.distribution, adaptiveStrategy, projectionStrategy) algo.run() self._result = algo.getResult() output_dimension = self._result.getMetaModel().getOutputDimension() # sensitivity si = ot.FunctionalChaosSobolIndices(self._result) if output_dimension == 1: self.feature_importances_ = [si.getSobolIndex(i) for i in range(input_dimension)] else: self.feature_importances_ = [[0.0] * input_dimension] * output_dimension for k in range(output_dimension): for i in range(input_dimension): self.feature_importances_[k][i] = si.getSobolIndex(i, k) self.feature_importances_ = np.array(self.feature_importances_) return self
def fit(self, sample, data): """Create the predictor. The result of the Polynomial Chaos is stored as :attr:`pc_result` and the surrogate is stored as :attr:`pc`. It exposes :attr:`self.weights`, :attr:`self.coefficients` and Sobol' indices :attr:`self.s_first` and :attr:`self.s_total`. :param array_like sample: The sample used to generate the data (n_samples, n_features). :param array_like data: The observed data (n_samples, [n_features]). """ trunc_strategy = ot.FixedStrategy(self.basis, self.n_basis) if self.strategy == 'LS': # least-squares method proj_strategy = ot.LeastSquaresStrategy(sample, data) _, self.weights = proj_strategy.getExperiment().generateWithWeights() elif self.strategy == 'SparseLS': app = ot.LeastSquaresMetaModelSelectionFactory(ot.LARS(), ot.CorrectedLeaveOneOut()) proj_strategy = ot.LeastSquaresStrategy(sample, data, app) _, self.weights = proj_strategy.getExperiment().generateWithWeights() max_considered_terms = self.sparse_param.get('max_considered_terms', 120) most_significant = self.sparse_param.get('most_significant', 30) significance_factor = self.sparse_param.get('significance_factor', 1e-3) trunc_strategy = ot.CleaningStrategy(ot.OrthogonalBasis(self.basis), max_considered_terms, most_significant, significance_factor, True) else: proj_strategy = self.proj_strategy sample_ = np.zeros_like(self.sample) sample_[:len(sample)] = sample sample_arg = np.all(np.isin(sample_, self.sample), axis=1) self.weights = np.array(self.weights)[sample_arg] # PC fitting pc_algo = ot.FunctionalChaosAlgorithm(sample, self.weights, data, self.dist, trunc_strategy) pc_algo.setProjectionStrategy(proj_strategy) ot.Log.Show(ot.Log.ERROR) pc_algo.run() # Accessors self.pc_result = pc_algo.getResult() self.pc = self.pc_result.getMetaModel() self.coefficients = self.pc_result.getCoefficients() # sensitivity indices sobol = ot.FunctionalChaosSobolIndices(self.pc_result) self.s_first, self.s_total = [], [] for i, j in product(range(self.in_dim), range(np.array(data).shape[1])): self.s_first.append(sobol.getSobolIndex(i, j)) self.s_total.append(sobol.getSobolTotalIndex(i, j)) self.s_first = np.array(self.s_first).reshape(self.in_dim, -1).T self.s_total = np.array(self.s_total).reshape(self.in_dim, -1).T
# Plot the observed versus the predicted outputs. # %% graph = val.drawValidation() graph.setTitle("Q2=%.2f%%" % (Q2 * 100)) view = viewer.View(graph) # %% # Sensitivity analysis # -------------------- # %% # Retrieve Sobol' sensitivity measures associated to the polynomial chaos decomposition of the model. # %% chaosSI = ot.FunctionalChaosSobolIndices(result) print(chaosSI.summary()) # %% first_order = [chaosSI.getSobolIndex(i) for i in range(dim_input)] total_order = [chaosSI.getSobolTotalIndex(i) for i in range(dim_input)] input_names = g.getInputDescription() graph = ot.SobolIndicesAlgorithm.DrawSobolIndices(input_names, first_order, total_order) view = viewer.View(graph) plt.show() # %% # Conclusion # ---------- #
val = ot.MetaModelValidation(inputTest, outputTest, metamodel) Q2 = val.computePredictivityFactor() graph = val.drawValidation() graph.setTitle("Metamodel validation Q2="+str(Q2)) view = viewer.View(graph) # %% # The coefficient of predictivity is not extremely satisfactory for the first output, but is would be sufficient for a central dispersion study. # The second output has a much more satisfactory Q2: only one single extreme point is far from the diagonal of the graphics. # %% # Compute and print Sobol' indices # -------------------------------- # %% chaosSI = ot.FunctionalChaosSobolIndices(result) print(chaosSI.summary()) # %% # Let us analyse the results of this global sensitivity analysis. # # * We see that the first output involves significant multi-indices with total degree 4. The contribution of the interactions are very significant in this model. # * The second output involves multi-indices with total degrees from 1 to 7, with a significant contribution of multi-indices with total degress 5 and 7. The first variable is especially significant, with a significant contribution of the interactions. # %% # Draw Sobol' indices. # %% sensitivityAnalysis = ot.FunctionalChaosSobolIndices(result) first_order = [sensitivityAnalysis.getSobolIndex(i) for i in range(dimension)] total_order = [sensitivityAnalysis.getSobolTotalIndex(i) for i in range(dimension)]
] sob_T2 = [ sob_2[0] + sob_2[1] + sob_3[0], sob_2[0] + sob_2[2] + sob_3[0], sob_2[1] + sob_2[2] + sob_3[0] ] sob_T3 = [sob_3[0]] model = ot.SymbolicFunction(['xi1', 'xi2', 'xi3'], [ 'sin(xi1) + (' + str(a) + ') * (sin(xi2)) ^ 2 + (' + str(b) + ') * xi3^4 * sin(xi1)' ]) # Create the input distribution distribution = ot.ComposedDistribution([ot.Uniform(-pi, pi)] * dimension) size = 1000 x = distribution.getSample(size) y = model(x) # To reduce the time needed by the test ot.ResourceMap.SetAsUnsignedInteger( "FittingTest-LillieforsMinimumSamplingSize", 4) ot.ResourceMap.SetAsUnsignedInteger( "FittingTest-LillieforsMaximumSamplingSize", 4) algo = ot.FunctionalChaosAlgorithm(x, y) algo.run() result = algo.getResult() sensitivity = ot.FunctionalChaosSobolIndices(result) print(sensitivity.summary())
def fit(self, X, y, **fit_params): """Fit PC regression model. Parameters ---------- X : array-like, shape = (n_samples, n_features) Training data. y : array-like, shape = (n_samples, [n_output_dims]) Target values. Returns ------- self : returns an instance of self. """ if len(X) == 0: raise ValueError( "Can not perform chaos expansion with empty sample") # check data type is accurate if (len(np.shape(X)) != 2): raise ValueError("X has incorrect shape.") input_dimension = len(X[1]) if (len(np.shape(y)) != 2): raise ValueError("y has incorrect shape.") if self.distribution is None: self.distribution = ot.MetaModelAlgorithm.BuildDistribution(X) if self.enumeratef == 'linear': enumerateFunction = ot.LinearEnumerateFunction(input_dimension) elif self.enumeratef == 'hyperbolic': enumerateFunction = ot.HyperbolicAnisotropicEnumerateFunction( input_dimension, self.q) else: raise ValueError('enumeratef should be "linear" or "hyperbolic"') polynomials = [ ot.StandardDistributionPolynomialFactory( self.distribution.getMarginal(i)) for i in range(input_dimension) ] productBasis = ot.OrthogonalProductPolynomialFactory( polynomials, enumerateFunction) adaptiveStrategy = ot.FixedStrategy( productBasis, enumerateFunction.getStrataCumulatedCardinal(self.degree)) if self.sparse: # Filter according to the sparse_fitting_algorithm key if self.sparse_fitting_algorithm == "cloo": fitting_algorithm = ot.CorrectedLeaveOneOut() else: fitting_algorithm = ot.KFold() # Define the correspondinding projection strategy projectionStrategy = ot.LeastSquaresStrategy( ot.LeastSquaresMetaModelSelectionFactory( ot.LARS(), fitting_algorithm)) else: projectionStrategy = ot.LeastSquaresStrategy(X, y) algo = ot.FunctionalChaosAlgorithm(X, y, self.distribution, adaptiveStrategy, projectionStrategy) algo.run() self.result_ = algo.getResult() output_dimension = self.result_.getMetaModel().getOutputDimension() # sensitivity si = ot.FunctionalChaosSobolIndices(self.result_) if output_dimension == 1: self.feature_importances_ = [ si.getSobolIndex(i) for i in range(input_dimension) ] else: self.feature_importances_ = [[0.0] * input_dimension ] * output_dimension for k in range(output_dimension): for i in range(input_dimension): self.feature_importances_[k][i] = si.getSobolIndex(i, k) self.feature_importances_ = np.array(self.feature_importances_) return self
def get_sobol_indices(self): return ot.FunctionalChaosSobolIndices(self._pce_result)