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 _buildChaosAlgo(self, inputSample, outputSample): """ Build the functional chaos algorithm without running it. """ if self._distribution is None: # create default distribution : Uniform between min and max of the # input sample inputSample = ot.Sample(inputSample) inputMin = inputSample.getMin() inputMin[0] = np.min(self._defectSizes) inputMax = inputSample.getMax() inputMax[0] = np.max(self._defectSizes) marginals = [ot.Uniform(inputMin[i], inputMax[i]) for i in range(self._dim)] self._distribution = ot.ComposedDistribution(marginals) # put description of the inputSample into decription of the distribution self._distribution.setDescription(inputSample.getDescription()) if self._adaptiveStrategy is None: # Create the adaptive strategy : default is fixed strategy of degree 5 # with linear enumerate function polyCol = [0.]*self._dim for i in range(self._dim): polyCol[i] = ot.StandardDistributionPolynomialFactory( self._distribution.getMarginal(i)) enumerateFunction = ot.LinearEnumerateFunction(self._dim) multivariateBasis = ot.OrthogonalProductPolynomialFactory(polyCol, enumerateFunction) # default degree is 3 (in __init__) indexMax = enumerateFunction.getStrataCumulatedCardinal(self._degree) self._adaptiveStrategy = ot.FixedStrategy(multivariateBasis, indexMax) if self._projectionStrategy is None: # sparse polynomial chaos basis_sequence_factory = ot.LARS() fitting_algorithm = ot.KFold() approximation_algorithm = ot.LeastSquaresMetaModelSelectionFactory( basis_sequence_factory, fitting_algorithm) self._projectionStrategy = ot.LeastSquaresStrategy(inputSample, outputSample, approximation_algorithm) return ot.FunctionalChaosAlgorithm(inputSample, outputSample, \ self._distribution, self._adaptiveStrategy, self._projectionStrategy)
]) # %% # Prepare the input/output samples sampleSize = 250 X = distribution.getSample(sampleSize) Y = myModel(X) dimension = X.getDimension() # %% # build the orthogonal basis coll = [ ot.StandardDistributionPolynomialFactory(distribution.getMarginal(i)) for i in range(dimension) ] enumerateFunction = ot.LinearEnumerateFunction(dimension) productBasis = ot.OrthogonalProductPolynomialFactory(coll, enumerateFunction) # %% # create the algorithm degree = 6 adaptiveStrategy = ot.FixedStrategy( productBasis, enumerateFunction.getStrataCumulatedCardinal(degree)) projectionStrategy = ot.LeastSquaresStrategy() algo = ot.FunctionalChaosAlgorithm(X, Y, distribution, adaptiveStrategy, projectionStrategy) algo.run() # %% # get the metamodel function result = algo.getResult()
# %% # Create the input independent joint distribution distribution = ot.Normal(2) distribution.setDescription(['X1', 'X2']) # %% # Create the correlated input distribution S = ot.CorrelationMatrix(2) S[1, 0] = 0.3 R = ot.NormalCopula.GetCorrelationFromSpearmanCorrelation(S) copula = ot.NormalCopula(R) distribution_corr = ot.ComposedDistribution([ot.Normal()] * 2, copula) # %% # ANCOVA needs a functional decomposition of the model enumerateFunction = ot.LinearEnumerateFunction(2) productBasis = ot.OrthogonalProductPolynomialFactory([ot.HermiteFactory()] * 2, enumerateFunction) adaptiveStrategy = ot.FixedStrategy( productBasis, enumerateFunction.getStrataCumulatedCardinal(4)) samplingSize = 250 projectionStrategy = ot.LeastSquaresStrategy( ot.MonteCarloExperiment(samplingSize)) algo = ot.FunctionalChaosAlgorithm(model, distribution, adaptiveStrategy, projectionStrategy) algo.run() result = ot.FunctionalChaosResult(algo.getResult()) # %% # Create the input sample taking account the correlation size = 2000
# %% polyColl[0] = ot.HermiteFactory() polyColl[1] = ot.LegendreFactory() polyColl[2] = ot.LaguerreFactory(2.75) # Parameter for the Jacobi factory : 'Probabilty' encoded with 1 polyColl[3] = ot.JacobiFactory(2.5, 3.5, 1) # %% # Create the enumeration function. # %% # The first possibility is to use the `LinearEnumerateFunction`. # %% enumerateFunction = ot.LinearEnumerateFunction(inputDimension) # %% # Another possibility is to use the `HyperbolicAnisotropicEnumerateFunction`, which gives less weight to interactions. # %% q = 0.4 enumerateFunction_1 = ot.HyperbolicAnisotropicEnumerateFunction( inputDimension, q) # %% # Create the multivariate orthonormal basis which is the the cartesian product of the univariate basis. # %% multivariateBasis = ot.OrthogonalProductPolynomialFactory( polyColl, enumerateFunction)
# %% # The coefficients of marginal i i = 1 result.getCoefficients()[i] # %% # Get the indices of the selected polynomials : K subsetK = result.getIndices() subsetK # %% # Get the composition of the polynomials # of the truncated multivariate basis for i in range(subsetK.getSize()): print("Polynomial number ", i, " in truncated basis <-> polynomial number ", subsetK[i], " = ", ot.LinearEnumerateFunction(dimension)(subsetK[i]), " in complete basis") # %% # Get the multivariate basis # as a collection of Function reduced = result.getReducedBasis() # %% # Get the orthogonal basis orthgBasis = result.getOrthogonalBasis() # %% # Get the distribution of variables Z orthgBasis.getMeasure() # %%
# The coefficients of marginal i i = 1 result.getCoefficients()[i] # %% # Get the indices of the selected polynomials : K subsetK = result.getIndices() subsetK # %% # Get the composition of the polynomials # of the truncated multivariate basis for i in range(subsetK.getSize()): print("Polynomial number ", i, " in truncated basis <-> polynomial number ", subsetK[i], " = ", ot.LinearEnumerateFunction(dimension)(subsetK[i]), " in complete basis") # %% # Get the multivariate basis # as a collection of Function reduced = result.getReducedBasis() # %% # Get the orthogonal basis orthgBasis = result.getOrthogonalBasis() orthgBasis # %% # Get the distribution of variables Z orthgBasis.getMeasure()
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 train(self): self.input_dim = self.training_points[None][0][0].shape[1] x_train = ot.Sample(self.training_points[None][0][0]) y_train = ot.Sample(self.training_points[None][0][1]) # Distribution choice of the inputs to Create the input distribution distributions = [] dist_specs = self.options["uncertainty_specs"] if dist_specs: if len(dist_specs) != self.input_dim: raise SurrogateOpenturnsException( "Number of distributions should be equal to input \ dimensions. Should be {}, got {}".format( self.input_dim, len(dist_specs) ) ) for ds in dist_specs: dist_klass = getattr(sys.modules["openturns"], ds["name"]) args = [ds["kwargs"][name] for name in DISTRIBUTION_SIGNATURES[ds["name"]]] distributions.append(dist_klass(*args)) else: for i in range(self.input_dim): mean = np.mean(x_train[:, i]) lower, upper = 0.95 * mean, 1.05 * mean if mean < 0: lower, upper = upper, lower distributions.append(ot.Uniform(lower, upper)) distribution = ot.ComposedDistribution(distributions) # Polynomial basis # step 1 - Construction of the multivariate orthonormal basis: # Build orthonormal or orthogonal univariate polynomial families # (associated to associated input distribution) polynoms = [0.0] * self.input_dim for i in range(distribution.getDimension()): polynoms[i] = ot.StandardDistributionPolynomialFactory( distribution.getMarginal(i) ) enumerateFunction = ot.LinearEnumerateFunction(self.input_dim) productBasis = ot.OrthogonalProductPolynomialFactory( polynoms, enumerateFunction ) # step 2 - Truncation strategy of the multivariate orthonormal basis: # a strategy must be chosen for the selection of the different terms # of the multivariate basis. # Truncature strategy of the multivariate orthonormal basis # We choose all the polynomials of degree <= degree degree = self.options["pce_degree"] index_max = enumerateFunction.getStrataCumulatedCardinal(degree) adaptive_strategy = ot.FixedStrategy(productBasis, index_max) basis_sequenceFactory = ot.LARS() fitting_algorithm = ot.CorrectedLeaveOneOut() approximation_algorithm = ot.LeastSquaresMetaModelSelectionFactory( basis_sequenceFactory, fitting_algorithm ) projection_strategy = ot.LeastSquaresStrategy( x_train, y_train, approximation_algorithm ) algo = ot.FunctionalChaosAlgorithm( x_train, y_train, distribution, adaptive_strategy, projection_strategy ) # algo = ot.FunctionalChaosAlgorithm(X_train_NS, Y_train_NS) algo.run() self._pce_result = algo.getResult()