diff --git a/BayesValidRox/tests/AnalyticalFunction/Test_AnalyticalFunction.py b/BayesValidRox/tests/AnalyticalFunction/Test_AnalyticalFunction.py index 820bceede74ff8d64957fc7dc125858f1e99ffae..a2ff59d7721b5e110122548e81c164ab7e6f0641 100755 --- a/BayesValidRox/tests/AnalyticalFunction/Test_AnalyticalFunction.py +++ b/BayesValidRox/tests/AnalyticalFunction/Test_AnalyticalFunction.py @@ -1,14 +1,14 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ -This test shows a surrogate-assisted Bayesian calibration of a time dependent +This test shows a surrogate-assisted Bayesian calibration of a time dependent analytical function. Author: Farid Mohammadi, M.Sc. E-Mail: farid.mohammadi@iws.uni-stuttgart.de Department of Hydromechanics and Modelling of Hydrosystems (LH2) -Institute for Modelling Hydraulic and Environmental Systems (IWS), University of Stuttgart -www.iws.uni-stuttgart.de/lh2/ +Institute for Modelling Hydraulic and Environmental Systems (IWS), University +of Stuttgart, www.iws.uni-stuttgart.de/lh2/ Pfaffenwaldring 61 70569 Stuttgart @@ -18,149 +18,149 @@ Created on Fri Aug 9 2019 import numpy as np import pandas as pd -import sys, joblib +import sys +import joblib import matplotlib matplotlib.use('agg') -sys.path.insert(0,'./../../../BayesValidRox') +sys.path.insert(0, './../../../BayesValidRox') try: import cPickle as pickle except ModuleNotFoundError: import _pickle as pickle -from PyLink.FuncForwardModel import FuncForwardModel +# from PyLink.FuncForwardModel import FuncForwardModel +from PyLink.PyLinkForwardModel_v2 import PyLinkForwardModel from surrogate_models.Input import Input from surrogate_models.surrogate_models import Metamodel from PostProcessing.PostProcessing import PostProcessing from BayesInference.BayesInference import BayesInference, Discrepancy if __name__ == "__main__": - + # Number of parameters - ndim = 2 # 2, 10 - - #===================================================== - #============= COMPUTATIONAL MODEL ================ - #===================================================== - Model = FuncForwardModel() - - Model.Type = 'Function' - Model.pyFile = 'AnalyticalFunction' - Model.Name = 'AnalyticFunc' - - Model.Output.Names = ['Z'] - - + ndim = 2 # 2, 10 + + # ===================================================== + # ============= COMPUTATIONAL MODEL ================ + # ===================================================== + Model = PyLinkForwardModel() # FuncForwardModel() + + Model.link_type = 'Function' + Model.py_file = 'AnalyticalFunction' + Model.name = 'AnalyticFunc' + + Model.Output.names = ['Z'] + # For Bayesian inversion synthetic data with X=[0,0] + Model.Observations = {} Model.Observations['Time [s]'] = np.arange(0, 10, 1.) / 9 - Model.Observations['Z'] = np.repeat([2.],10) - + Model.Observations['Z'] = np.repeat([2.], 10) + # For Checking with the MonteCarlo refrence + Model.MCReference = {} Model.MCReference['Time [s]'] = np.arange(0, 10, 1.) / 9 - Model.MCReference['mean'] = np.load("data/mean_"+str(ndim)+".npy") - Model.MCReference['std'] = np.load("data/std_"+str(ndim)+".npy") + Model.MCReference['mean'] = np.load(f"data/mean_{ndim}.npy") + Model.MCReference['std'] = np.load(f"data/std_{ndim}.npy") - #===================================================== - #========= PROBABILISTIC INPUT MODEL ============== - #===================================================== - # Define the uncertain parameters with their mean and + # ===================================================== + # ========= PROBABILISTIC INPUT MODEL ============== + # ===================================================== + # Define the uncertain parameters with their mean and # standard deviation Inputs = Input() - + # Assuming dependent input variables # Inputs.Rosenblatt = True - + # for i in range(ndim): # Inputs.addMarginals() # Inputs.Marginals[i].Name = '$X_{%s}$'%(i+1) # Inputs.Marginals[i].DistType = 'unif' # Inputs.Marginals[i].Parameters = [-5, 5] - + # arbitrary polynomial chaos inputParams = np.load('data/InputParameters_{}.npy'.format(ndim)) for i in range(ndim): Inputs.addMarginals() - Inputs.Marginals[i].Name = '$X_{%s}$'%(i+1) - Inputs.Marginals[i].InputValues = inputParams[:,i] - - #===================================================== - #========== DEFINITION OF THE METAMODEL ============ - #===================================================== + Inputs.Marginals[i].Name = f'$X_{i+1}$' + Inputs.Marginals[i].InputValues = inputParams[:, i] + + # ===================================================== + # ========== DEFINITION OF THE METAMODEL ============ + # ===================================================== MetaModelOpts = Metamodel(Inputs) - + # Select if you want to preserve the spatial/temporal depencencies # MetaModelOpts.DimRedMethod = 'PCA' # MetaModelOpts.varPCAThreshold = 100 #99.999 - + # Select your metamodel method # 1) PCE (Polynomial Chaos Expansion) 2) GPE (Gaussian Process Emulator) - # 3) PCEKriging (PCE + GPE) MetaModelOpts.metaModel = 'PCE' - + # ------------------------------------------------ # ------------- PCE Specification ---------------- # ------------------------------------------------ - # Select the sparse least-square minimization method for + # Select the sparse least-square minimization method for # the PCE coefficients calculation: - # 1)OLS: Ordinary Least Square 2)BRR: Bayesian Ridge Regression + # 1)OLS: Ordinary Least Square 2)BRR: Bayesian Ridge Regression # 3)LARS: Least angle regression 4)ARD: Bayesian ARD Regression # 5)FastARD: Fast Bayesian ARD Regression # 6)VBL: Variational Bayesian Learning - # 7)EBL: Emperical Bayesian Learning + # 7)EBL: Emperical Bayesian Learning MetaModelOpts.RegMethod = 'FastARD' # Specify the max degree to be compared by the adaptive algorithm: # The degree with the lowest Leave-One-Out cross-validation (LOO) - # error (or the highest score=1-LOO)estimator is chosen as the final + # error (or the highest score=1-LOO)estimator is chosen as the final # metamodel. - MetaModelOpts.MinPceDegree = 6#12 - MetaModelOpts.MaxPceDegree = 6#12 #12 + MetaModelOpts.MinPceDegree = 6 # 12 + MetaModelOpts.MaxPceDegree = 6 # 12 # q-quasi-norm 0<q<1 (default=1) - MetaModelOpts.q = 0.75 if ndim<5 else 0.5 + MetaModelOpts.q = 0.75 if ndim < 5 else 0.5 # MetaModelOpts.q = np.linspace(0.25,0.75, 3) - + # Print summary of the regression results # MetaModelOpts.DisplayFlag = True - + # ------------------------------------------------ # ------ Experimental Design Configuration ------- # ------------------------------------------------ - # Generate an experimental design of size NrExpDesign based on a latin - # hypercube sampling of the input model or user-defined values of X and/or Y: MetaModelOpts.addExpDesign() - + # One-shot (normal) or Sequential Adaptive (sequential) Design - MetaModelOpts.ExpDesign.Method = 'normal' - NrofInitSamples = 50 #50 5*ndim + MetaModelOpts.ExpDesign.Method = 'sequential' + NrofInitSamples = 5*ndim # 50 5*ndim MetaModelOpts.ExpDesign.NrSamples = NrofInitSamples - + # Sampling methods - # 1) random 2) latin_hypercube 3) sobol 4) halton 5) hammersley 6) chebyshev(FT) - # 7) korobov 8) grid(FT) 9) nested_grid(FT) 10)user + # 1) random 2) latin_hypercube 3) sobol 4) halton 5) hammersley 6) korobov + # 7) chebyshev(FT) 8) grid(FT) 9) nested_grid(FT) 10)user MetaModelOpts.ExpDesign.SamplingMethod = 'latin_hypercube' - + # Provide the experimental design object with a hdf5 file # MetaModelOpts.ExpDesign.hdf5File = 'ExpDesign_AnalyticFunc.hdf5' - + # Sequential experimental design (needed only for sequential ExpDesign) MetaModelOpts.ExpDesign.NrofNewSample = 1 - MetaModelOpts.ExpDesign.MaxNSamples = 75 #150 + MetaModelOpts.ExpDesign.MaxNSamples = 20 # 150 MetaModelOpts.ExpDesign.ModifiedLOOThreshold = 1e-16 - + # Defining the measurement error, if it's known a priori obsData = pd.DataFrame(Model.Observations, columns=Model.Output.Names) DiscrepancyOpts = Discrepancy('') DiscrepancyOpts.Type = 'Gaussian' DiscrepancyOpts.Parameters = obsData**2 MetaModelOpts.Discrepancy = DiscrepancyOpts - + # Plot the posterior snapshots for SeqDesign MetaModelOpts.ExpDesign.PostSnapshot = False MetaModelOpts.ExpDesign.stepSnapshot = 1 MetaModelOpts.ExpDesign.MAP = [0] * ndim - MetaModelOpts.ExpDesign.parNames = ['$X_{%s}$'%(i+1) for i in range(ndim)] - + MetaModelOpts.ExpDesign.parNames = [f'$X_{i+1}$' for i in range(ndim)] + # ------------------------------------------------ # ------- Sequential Design configuration -------- # ------------------------------------------------ @@ -169,112 +169,115 @@ if __name__ == "__main__": MetaModelOpts.ExpDesign.TradeOffScheme = 'None' # MetaModelOpts.ExpDesign.nReprications = 20 # -------- Exploration ------ - #1)'Voronoi' 2)'random' 3)'latin_hypercube' 4)'LOOCV' 5)'dual annealing' + # 1)'Voronoi' 2)'random' 3)'latin_hypercube' 4)'LOOCV' 5)'dual annealing' MetaModelOpts.ExpDesign.ExploreMethod = 'latin_hypercube' - + # Use when 'dual annealing' chosen MetaModelOpts.ExpDesign.MaxFunItr = 200 - + # Use when 'Voronoi' or 'random' or 'latin_hypercube' chosen - MetaModelOpts.ExpDesign.NCandidate = 5000 - MetaModelOpts.ExpDesign.NrofCandGroups = 4 #8 - + MetaModelOpts.ExpDesign.NCandidate = 5000 + MetaModelOpts.ExpDesign.NrofCandGroups = 4 # 8 + # -------- Exploitation ------ - # 1)'BayesOptDesign' 2)'BayesActDesign' 3)'VarOptDesign' 4)'alphabetic' + # 1)'BayesOptDesign' 2)'BayesActDesign' 3)'VarOptDesign' 4)'alphabetic' # 5)'Space-filling' MetaModelOpts.ExpDesign.ExploitMethod = 'VarOptDesign' - + # BayesOptDesign -> when data is available # 1)DKL (Kullback-Leibler Divergence) 2)DPP (D-Posterior-percision) # 3)APP (A-Posterior-percision) # ['DKL', 'BME', 'infEntropy'] # MetaModelOpts.ExpDesign.UtilityFunction = 'DKL' - + # VarBasedOptDesign -> when data is not available # Only with Vornoi >>> 1)Entropy 2)EIGF, 3)LOOCV - MetaModelOpts.ExpDesign.UtilityFunction = 'Entropy' #['EIGF', 'Entropy', 'LOOCV'] - + # or a combination as a list + MetaModelOpts.ExpDesign.UtilityFunction = 'Entropy' + # alphabetic # 1)D-Opt (D-Optimality) 2)A-Opt (A-Optimality) - # 3)K-Opt (K-Optimality) - # MetaModelOpts.ExpDesign.UtilityFunction = 'D-Opt' #['D-Opt', 'A-Opt', 'K-Opt'] - - # For colculation of validation error for SeqDesign - MetaModelOpts.validSamples = np.load("data/Prior_"+str(ndim)+".npy") - MetaModelOpts.validModelRuns = {'Z':np.load("data/origModelOutput_"+str(ndim)+".npy")} - MetaModelOpts.validLikelihoods = np.load("data/validLikelihoods_"+str(ndim)+".npy") - + # 3)K-Opt (K-Optimality) or a combination as a list + # MetaModelOpts.ExpDesign.UtilityFunction = 'D-Opt' + + # For colculation of validation error for SeqDesign + prior = np.load(f"data/Prior_{ndim}.npy") + prior_outputs = np.load(f"data/origModelOutput_{ndim}.npy") + likelihood = np.load(f"data/validLikelihoods_{ndim}.npy") + MetaModelOpts.validSamples = prior + MetaModelOpts.validModelRuns = {'Z': prior_outputs} + MetaModelOpts.validLikelihoods = likelihood + # >>>>>>>>>>>>>>>>>>>>>> Build Surrogate <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - # Adaptive sparse arbitrary polynomial chaos expansion + # Train the meta model PCEModel = MetaModelOpts.create_metamodel(Model) - - # # Save PCE models - # with open('PCEModel_'+Model.Name+'.pkl', 'wb') as output: - # joblib.dump(PCEModel, output, 2) - + + # Save PCE models + with open(f'PCEModel_{Model.name}.pkl', 'wb') as output: + joblib.dump(PCEModel, output, 2) + # Load PCEModel - # with open('PCEModel_'+Model.Name+'.pkl', 'rb') as input: + # with open(f'PCEModel_{Model.name}.pkl', 'rb') as input: # PCEModel = joblib.load(input) - #===================================================== - #========= POST PROCESSING OF METAMODELS =========== - #===================================================== + # ===================================================== + # ========= POST PROCESSING OF METAMODELS =========== + # ===================================================== PostPCE = PostProcessing(PCEModel) - + # Plot to check validation visually. PostPCE.validMetamodel(nValidSamples=3) # Compute the moments and compare with the Monte-Carlo reference if MetaModelOpts.metaModel != 'GPE': PostPCE.plotMoments() - + # Plot the evolution of the KLD,BME, and Modified LOOCV error if MetaModelOpts.ExpDesign.Method == 'sequential': refBME_KLD = np.load("data/refBME_KLD_"+str(ndim)+".npy") PostPCE.seqDesignDiagnosticPlots(refBME_KLD) - + # Plot the sobol indices if MetaModelOpts.metaModel != 'GPE': sobol_cell, total_sobol = PostPCE.sobolIndicesPCE() - + # Compute and print RMSE error PostPCE.accuracyCheckMetaModel(nSamples=200) - - #===================================================== - #======== Bayesian inference with Emulator ========== - #===================================================== + sys.exit() + # ===================================================== + # ======== Bayesian inference with Emulator ========== + # ===================================================== BayesOpts = BayesInference(PCEModel) BayesOpts.emulator = True BayesOpts.PlotPostPred = True - + # BayesOpts.selectedIndices = [0, 3, 5, 7, 9] # BME Bootstrap # BayesOpts.Bootstrap = True # BayesOpts.BootstrapItrNr = 500 # BayesOpts.BootstrapNoise = 100 - + # Bayesian cross validation # BayesOpts.BayesLOOCV = True - + # Select the inference method BayesOpts.SamplingMethod = 'MCMC' BayesOpts.MCMCnwalkers = 30 - # BayesOpts.MCMCinitSamples = np.zeros((1,10)) + 1e-3 * np.random.randn(200, 10) + # BayesOpts.MCMCinitSamples = np.zeros((1,10))+1e-3*np.random.randn(200, 10) # BayesOpts.MCMCnSteps = 1000 import emcee BayesOpts.MCMCmoves = emcee.moves.KDEMove() # BayesOpts.MultiProcessMCMC = True - + # ----- Define the discrepancy model ------- - # obsData = pd.DataFrame(Model.Observations, columns=Model.Output.Names) BayesOpts.MeasurementError = obsData - + # # -- (Option B) -- DiscrepancyOpts = Discrepancy('') DiscrepancyOpts.Type = 'Gaussian' DiscrepancyOpts.Parameters = obsData**2 # DiscrepancyOpts.Parameters = {'Z':np.ones(10)} BayesOpts.Discrepancy = DiscrepancyOpts - + # -- (Option C) -- # DiscOutputOpts = Input() # # # OutputName = 'Z' @@ -284,7 +287,7 @@ if __name__ == "__main__": # DiscOutputOpts.Marginals[0].Parameters = [0, 10] # BayesOpts.Discrepancy = {'known': DiscrepancyOpts, # 'infer': Discrepancy(DiscOutputOpts)} - + # BayesOpts.BiasInputs = {'Z':np.arange(0, 10, 1.).reshape(-1,1) / 9} # DiscOutputOpts = Input() # # OutputName = 'lambda' @@ -292,78 +295,59 @@ if __name__ == "__main__": # DiscOutputOpts.Marginals[0].Name = '$\lambda$' # DiscOutputOpts.Marginals[0].DistType = 'unif' # DiscOutputOpts.Marginals[0].Parameters = [0, 1] - + # # OutputName = 'sigma_f' # DiscOutputOpts.addMarginals() # DiscOutputOpts.Marginals[1].Name = '$\sigma_f$' # DiscOutputOpts.Marginals[1].DistType = 'unif' # DiscOutputOpts.Marginals[1].Parameters = [0, 1e-4] # BayesOpts.Discrepancy = Discrepancy(DiscOutputOpts) - # BayesOpts.Discrepancy = {'known': DiscrepancyOpts, + # BayesOpts.Discrepancy = {'known': DiscrepancyOpts, # 'infer': Discrepancy(DiscOutputOpts)} - - + # Start the calibration/inference Bayes_PCE = BayesOpts.create_Inference() - + # Save class objects - with open('Bayes_'+Model.Name+'.pkl', 'wb') as output: + with open(f'Bayes_{Model.name}.pkl', 'wb') as output: joblib.dump(Bayes_PCE, output, 2) sys.exit('STOP!!') - #===================================================== - #====== Bayesian inference with Forward Model ======== - #===================================================== + # ===================================================== + # ====== Bayesian inference with Forward Model ======== + # ===================================================== if ndim < 7: PCEModel.ModelObj.Name = 'OrigAnalyticFunc' - + BayesOptsModel = BayesInference(PCEModel) BayesOptsModel.emulator = False - BayesOptsModel.NrofSamples = 10000#00 - - # Evaluation of forward model predictions for the samples used for PCEModel + BayesOptsModel.NrofSamples = 10000 + + # Evaluation of forward model predictions for the surrogate posterior # BayesOptsModel.Samples = Bayes_PCE.Samples # BayesOptsModel.SamplingMethod = 'MCMC' - + # Bootstrap for BME calulations BayesOptsModel.Bootstrap = True BayesOptsModel.BootstrapItrNr = 1 BayesOptsModel.BootstrapNoise = 0.05 - + BayesOptsModel.PlotPostDist = True BayesOptsModel.PlotPostPred = False - - + # ----- Define the discrepancy model ------- BayesOptsModel.MeasurementError = obsData # (Option B) DiscrepancyOpts = Discrepancy('') DiscrepancyOpts.Type = 'Gaussian' - DiscrepancyOpts.Parameters = obsData **2 - - BayesOptsModel.Discrepancy = DiscrepancyOpts - + DiscrepancyOpts.Parameters = obsData ** 2 + BayesOptsModel.Discrepancy = DiscrepancyOpts + + # Start the infernce Bayes_Model = BayesOptsModel.create_Inference() - - #===================================================== - #============== Save class objects ================= - #===================================================== - with open('AnalyticFunc_Results.pkl', 'wb') as output: - pickle.dump(PCEModel, output, pickle.HIGHEST_PROTOCOL) - - pickle.dump(PostPCE, output, pickle.HIGHEST_PROTOCOL) - - pickle.dump(Bayes_PCE, output, pickle.HIGHEST_PROTOCOL) - - if ndim < 7: - pickle.dump(Bayes_Model, output, pickle.HIGHEST_PROTOCOL) - -# del PCEModel -# del PostPCE -# del Bayes - - # Load the objects -# with open('AnalyticFunc_Results.pkl', 'rb') as input: -# PCEModel = pickle.load(input) -# PostPCE = pickle.load(input) -# Bayes_PCE = pickle.load(input) -# Bayes_Model = pickle.load(input) \ No newline at end of file + + # ===================================================== + # ============== Save class objects ================= + # ===================================================== + if ndim < 7: + with open('AnalyticFunc_Results.pkl', 'wb') as output: + joblib.dump(Bayes_Model, output, 2)