def _buildKrigingAlgo(self, inputSample, outputSample): """ Build the functional chaos algorithm without running it. """ if self._basis is None: # create linear basis only for the defect parameter (1st parameter), # constant otherwise input = ['x' + str(i) for i in range(self._dim)] functions = [] # constant functions.append(ot.SymbolicFunction(input, ['1'])) # linear for the first parameter only functions.append(ot.SymbolicFunction(input, [input[0]])) self._basis = ot.Basis(functions) if self._covarianceModel is None: # anisotropic squared exponential covariance model self._covarianceModel = ot.SquaredExponential([1] * self._dim) # normalization mean = inputSample.computeMean() try: stddev = inputSample.computeStandardDeviation() except AttributeError: stddev = inputSample.computeStandardDeviationPerComponent() linear = ot.SquareMatrix(self._dim) for j in range(self._dim): linear[j, j] = 1.0 / stddev[j] if abs(stddev[j]) > 1e-12 else 1.0 zero = [0.0] * self._dim transformation = ot.LinearFunction(mean, zero, linear) algoKriging = ot.KrigingAlgorithm(transformation(inputSample), outputSample, self._covarianceModel, self._basis) return algoKriging, transformation
def hyperplane(coefs): """ Generate a linear NMF from its coefficients """ dim = len(coefs) constant = [0.] center = [0.] * len(coefs) linear = ot.Matrix(1, dim) for i in range(dim): linear[0, i] = coefs[i] function = ot.LinearFunction(center, constant, linear) return function
import openturns as ot from openturns.viewer import View center = [0.0] constant = [3.0] linear = ot.Matrix([[2.0]]) f = ot.LinearFunction(center, constant, linear) graph = f.draw(0.0, 10.0) graph.setTitle('$y=2x+3$') View(graph, figure_kwargs={'figsize': (8, 4)}, add_legend=True)
from matplotlib import pyplot as plt from openturns.viewer import View from math import sqrt domain = ot.Interval(-1.0, 1.0) basis = ot.OrthogonalProductFunctionFactory([ot.FourierSeriesFactory()]) basisSize = 10 experiment = ot.GaussProductExperiment(basis.getMeasure(), [20]) mustScale = False threshold = 0.001 factory = ot.KarhunenLoeveQuadratureFactory(domain, experiment, basis, basisSize, mustScale, threshold) model = ot.AbsoluteExponential([1.0]) ev = ot.NumericalPoint() functions = factory.build(model, ev) g = ot.Graph() g.setXTitle("$t$") g.setYTitle("$\sqrt{\lambda_n}\phi_n$") for i in range(functions.getSize()): g.add((functions.build(i) * ot.LinearFunction([0.0] * domain.getDimension(), [sqrt(ev[i])], ot.Matrix(1, domain.getDimension()))).draw( -1.0, 1.0, 256)) g.setColors(ot.Drawable.BuildDefaultPalette(functions.getSize())) fig = plt.figure(figsize=(6, 4)) plt.suptitle("P1 approx. of KL expansion for $C(s,t)=e^{-|s-t|}$") axis = fig.add_subplot(111) axis.set_xlim(auto=True) View(g, figure=fig, axes=[axis], add_legend=False)
def run(self): """ Launch the algorithm and build the POD models. Notes ----- This method launches the iterative algorithm. First the censored data are filtered if needed. The Box Cox transformation is performed if it is enabled. Then the enrichment of the design of experiments is performed. Once the algorithm stops, it builds the POD models : conditional samples are simulated for each defect size, then the distributions of the probability estimator (for MC simulation) are built. Eventually, a sample of this distribution is used to compute the mean POD and the POD at the confidence level. """ # Create an initial uniform distribution if not given if self._distribution is None: inputMin = self._input.getMin() inputMin[0] = np.min(self._defectSizes) inputMax = self._input.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) # Create the design of experiments of the candidate points where the # criterion is computed if self._distribution.hasIndependentCopula(): # without copula use low discrepancy experiment as first doe doeCandidate = ot.LowDiscrepancyExperiment(ot.SobolSequence(), self._distribution, self._candidateSize).generate() else: # else simple Monte Carlo distribution doeCandidate = self._distribution.getSample(self._candidateSize) # build initial kriging model # build the kriging model without optimization algoKriging, transformation = self._buildKrigingAlgo(self._input, self._signals) if self._verbose: print('Building the kriging model') print('Optimization of the covariance model parameters...') llDim = algoKriging.getReducedLogLikelihoodFunction().getInputDimension() lowerBound = [0.001] * llDim upperBound = [50] * llDim algoKriging = self._estimKrigingTheta(algoKriging, lowerBound, upperBound, self._initialStartSize) algoKriging.run() # Get kriging results self._krigingResult = algoKriging.getResult() self._covarianceModel = self._krigingResult.getCovarianceModel() self._basis = self._krigingResult.getBasisCollection() metamodel = ot.ComposedFunction(self._krigingResult.getMetaModel(), transformation) self._Q2 = self._computeQ2(self._input, self._signals, self._krigingResult, transformation) if self._verbose: print('Kriging validation Q2 (>0.9): {:0.4f}\n'.format(self._Q2)) plt.ion() # Start the improvment loop iteration = 0 while iteration < self._nIteration: iteration += 1 if self._verbose: print('Iteration : {}/{}'.format(iteration, self._nIteration)) # compute POD (ptrue = pn-1) for bias reducing in the criterion # Monte Carlo for all defect sizes in a vectorized way. # get Sample for all parameters except the defect size samplePred = self._distribution.getSample(self._samplingSize)[:,1:] fullSamplePred = ot.Sample(self._samplingSize * self._defectNumber, self._dim) # Add the defect sizes as first value for i, defect in enumerate(self._defectSizes): fullSamplePred[self._samplingSize*i:self._samplingSize*(i+1), :] = \ self._mergeDefectInX(defect, samplePred) meanPredictionSample = metamodel(fullSamplePred) meanPredictionSample = np.reshape(meanPredictionSample, (self._samplingSize, self._defectNumber), 'F') # compute the POD for all defect sizes currentPOD = np.mean(meanPredictionSample > self._detectionBoxCox, axis=0) # Compute criterion for all candidate in the candidate doe criterion = 1000000000 for icand, candidate in enumerate(doeCandidate): # add the current candidate to the kriging doe inputAugmented = self._input[:] inputAugmented.add(candidate) signalsAugmented = self._signals[:] # predict the signal value of the candidate using the current # kriging model signalsAugmented.add(metamodel(candidate)) # create a temporary kriging model with the new doe and without # updating the covariance model parameters # normalization mean = inputAugmented.computeMean() try: stddev = inputAugmented.computeStandardDeviation() except AttributeError: stddev = inputAugmented.computeStandardDeviationPerComponent() linear = ot.SquareMatrix(self._dim) for j in range(self._dim): linear[j, j] = 1.0 / stddev[j] if abs(stddev[j]) > 1e-12 else 1.0 zero = [0.0] * self._dim transformation = ot.LinearFunction(mean, zero, linear) algoKrigingTemp = ot.KrigingAlgorithm(transformation(inputAugmented), signalsAugmented, self._covarianceModel, self._basis) optimizer = algoKrigingTemp.getOptimizationAlgorithm() optimizer.setMaximumIterationNumber(0) algoKrigingTemp.setOptimizationAlgorithm(optimizer) algoKrigingTemp.run() krigingResultTemp = algoKrigingTemp.getResult() # compute the criterion for all defect size crit = [] # save results, used to compute the PODModel et PODCLModel PODPerDefect = ot.Sample(self._simulationSize * self._samplingSize, self._defectNumber) for idef, defect in enumerate(self._defectSizes): podSample = self._computePODSamplePerDefect(defect, self._detectionBoxCox, krigingResultTemp, transformation, self._distribution, self._simulationSize, self._samplingSize) PODPerDefect[:, idef] = podSample meanPOD = podSample.computeMean()[0] varPOD = podSample.computeVariance()[0] crit.append(varPOD + (meanPOD - currentPOD[idef])**2) # compute the criterion aggregated for all defect sizes newCriterion = np.sqrt(np.mean(crit)) # check if the result is better or not if newCriterion < criterion: self._PODPerDefect = PODPerDefect criterion = newCriterion indexOpt = icand if self._verbose: updateProgress(icand, int(doeCandidate.getSize()), 'Computing criterion') # get the best candidate candidateOpt = doeCandidate[indexOpt] # add new point to DOE self._input.add(candidateOpt) # add the signal computed by the physical model if self._boxCox: self._signals.add(self._boxCoxTransform(self._physicalModel(candidateOpt) + [self._shift])) else: self._signals.add(self._physicalModel(candidateOpt)) # remove added candidate from the doeCandidate doeCandidate.erase(indexOpt) if self._verbose: print('Criterion value : {:0.4f}'.format(criterion)) print('Added point : {}'.format(candidateOpt)) print('Update the kriging model') # update the kriging model without optimization algoKriging, transformation = self._buildKrigingAlgo(self._input, self._signals) algoKriging.setOptimizeParameters(False) algoKriging.run() self._Q2 = self._computeQ2(self._input, self._signals, algoKriging.getResult(), transformation) # Check the quality of the kriging model if it needs optimization if self._Q2 < 0.95: if self._verbose: print('Optimization of the covariance model parameters...') algoKriging.setOptimizeParameters(True) algoKriging = self._estimKrigingTheta(algoKriging, lowerBound, upperBound, self._initialStartSize) algoKriging.run() # Get kriging results self._krigingResult = algoKriging.getResult() self._covarianceModel = self._krigingResult.getCovarianceModel() self._basis = self._krigingResult.getBasisCollection() self._Q2 = self._computeQ2(self._input, self._signals, self._krigingResult, transformation) if self._verbose: print('Kriging validation Q2 (>0.9): {:0.4f}'.format(self._Q2)) if self._graph: # create the interpolate function of the POD model meanPOD = self._PODPerDefect.computeMean() interpModel = interp1d(self._defectSizes, np.array(meanPOD), kind='linear') self._PODmodel = ot.PythonFunction(1, 1, interpModel) # The POD at confidence level is built in getPODCLModel() directly fig, ax = self.drawPOD(self._probabilityLevel, self._confidenceLevel) plt.draw() plt.pause(0.001) plt.show() if self._graphDirectory is not None: if not os.path.exists(self._graphDirectory): os.makedirs(self._graphDirectory) fig.savefig(os.path.join(self._graphDirectory, 'AdaptiveSignalPOD_')+str(iteration), bbox_inches='tight', transparent=True) # Compute the final POD with the last updated kriging model if self._verbose: print('\nStart computing the POD with the last updated kriging model') # compute the sample containing the POD values for all defect self._PODPerDefect = ot.Sample(self._simulationSize * self._samplingSize, self._defectNumber) for i, defect in enumerate(self._defectSizes): self._PODPerDefect[:, i] = self._computePODSamplePerDefect(defect, self._detectionBoxCox, self._krigingResult, transformation, self._distribution, self._simulationSize, self._samplingSize) if self._verbose: updateProgress(i, self._defectNumber, 'Computing POD per defect') # compute the mean POD meanPOD = self._PODPerDefect.computeMean() # create the interpolate function of the POD model interpModel = interp1d(self._defectSizes, np.array(meanPOD), kind='linear') self._PODmodel = ot.PythonFunction(1, 1, interpModel) # The POD at confidence level is built in getPODCLModel() directly # remove the interactive plotting plt.ioff()