PCE METAMODELING: CONSTRUCTION OF ORTHOGONAL BASIS FOR ARBITRARY DISTRIBUTION¶
This example demonstrates the numerical basis construction with Stieltjes procedure. The Ishigami function with Gaussian distributions restricted to the $[-\pi, \pi]$ interval is used. The Stieltjes procedure is expected to produce a basis that performs better than the Legendre polynomials, the default basis for all bounded distribution.
Package imports¶
from uqpylab import sessions, display_util
import numpy as np
import matplotlib.pyplot as plt
%matplotlib notebook
Initialize common plotting parameters¶
display_util.load_plt_defaults()
uq_colors = display_util.get_uq_color_order()
Start a remote UQCloud session¶
# Start the session
mySession = sessions.cloud()
# (Optional) Get a convenient handle to the command line interface
uq = mySession.cli
# Reset the session
mySession.reset()
Processing .
.
done! uqpylab.sessions :: INFO :: This is UQ[py]Lab, version 1.00, running on https://uqcloud.ethz.ch. UQ[py]Lab is free software, published under the open source BSD 3-clause license. To request special permissions, please contact: - Stefano Marelli (marelli@ibk.baug.ethz.ch). A new session (f01a706455a94b8c89c469cf0607e892) started.
uqpylab.sessions :: INFO :: Reset successful.
Set the random seed for reproducibility¶
uq.rng(100, 'twister');
Computational model¶
The Ishigami function is defined as:
$$Y(\mathbf{x}) = \sin(x_1) + 7 \sin^2(x_2) + 0.1 x_3^4 \sin(x_1)$$
where $x_i \in [-\pi, \pi], \; i = 1,2,3.$
This computation is carried out by the function
model
supplied within ishigami.py
.
The input parameters of this function are gathered into the vector X
.
Create a MODEL from the function file:
ModelOpts = {
'Type': 'Model',
'ModelFun':'ishigami.model'
}
myModel = uq.createModel(ModelOpts)
Probabilistic input model¶
The probabilistic input model consists of three independent uniform random variables:
$$X_i \sim \mathcal{U}(-\pi, \pi) \qquad i = 1,2,3 $$
Specify the marginals:
InputOpts = {
"Marginals": [
{"Type": "Uniform",
"Parameters": [-np.pi, np.pi]
},
{"Type": "Uniform",
"Parameters": [-np.pi, np.pi]
},
{"Type": "Uniform",
"Parameters": [-np.pi, np.pi]
}
]
}
Create an INPUT object based on the specified marginals:
myInput = uq.createInput(InputOpts)
PCE with Legendre polynomials¶
This section showcases several ways to calculate the polynomial chaos expansion (PCE) coefficients.
Select PCE as the metamodeling tool:
MetaOpts= {
"Type": "Metamodel",
"MetaType": "PCE",
}
Assign the Ishigami function model as the full computational model of the PCE metamodel:
MetaOpts["FullModel"] = myModel['Name']
The sparse-favoring least-square minimization LARS can be enabled by:
MetaOpts["Method"] = "LARS"
LARS allows for degree-adaptive calculation of the PCE coefficients. That is, if an array of possible degrees is given, the degree with the lowest Leave-One-Out cross-validation error (LOO error) is automatically selected. Specify the range for the degree selection:
MetaOpts["Degree"] = np.arange(3,16).tolist()
Manually select the Legendre orthonormal polynomials
MetaOpts["PolyTypes"] = ['Legendre','Legendre','Legendre']
The following options configure UQLab to generate an experimental design of size $150$ based on a latin hypercube sampling of the input model:
MetaOpts["ExpDesign"] = {
"NSamples" : 150
}
Create the LARS-based PCE metamodel:
# reset the rng generator to obtain the same experimental design between trials
uq.rng(100, 'twister')
myPCE_Legendre = uq.createModel(MetaOpts)
uqpylab.sessions :: INFO :: Received intermediate compute request, function: ishigami.model.
uqpylab.sessions :: INFO :: Carrying out local computation...
uqpylab.sessions :: INFO :: Local computation complete.
uqpylab.sessions :: INFO :: Starting transmission of intermediate compute results ((150,))...
uqpylab.sessions :: INFO :: Intermediate compute results sent.
Print a report on the calculated coefficients:
uq.print(myPCE_Legendre)
%------------ Polynomial chaos output ------------% Number of input variables: 3 Maximal degree: 15 q-norm: 1.00 Size of full basis: 816 Size of sparse basis: 50 Full model evaluations: 150 Leave-one-out error: 9.2344374e-12 Modified leave-one-out error: 2.4664321e-11 Mean value: 3.5000 Standard deviation: 3.7208 Coef. of variation: 106.309% %--------------------------------------------------%
Create a visual representation of the distribution of the coefficients:
uq.display(myPCE_Legendre);
PCE with numerically estimated polynomials¶
We now set the polynomial families to "arbitrary", so that polynomials orthogonal to the input marginals are numerically constructed:
MetaOpts["PolyTypes"] = ['Arbitrary','Arbitrary','Arbitrary']
Create the OMP-based PCE metamodel:
# reset the rng generator to obtain the same experimental design between trials
uq.rng(100, 'twister')
myPCE_Arbitrary = uq.createModel(MetaOpts)
uqpylab.sessions :: INFO :: Received intermediate compute request, function: ishigami.model.
uqpylab.sessions :: INFO :: Carrying out local computation...
uqpylab.sessions :: INFO :: Local computation complete.
uqpylab.sessions :: INFO :: Starting transmission of intermediate compute results ((150,))...
uqpylab.sessions :: INFO :: Intermediate compute results sent.
Print a report on the calculated coefficients:
uq.print(myPCE_Arbitrary)
%------------ Polynomial chaos output ------------% Number of input variables: 3 Maximal degree: 15 q-norm: 1.00 Size of full basis: 816 Size of sparse basis: 50 Full model evaluations: 150 Leave-one-out error: 9.2344374e-12 Modified leave-one-out error: 2.4664321e-11 Mean value: 3.5000 Standard deviation: 3.7208 Coef. of variation: 106.309% %--------------------------------------------------%
Create a visual representation of the distribution of the coefficients:
uq.display(myPCE_Arbitrary);
Xval = uq.getSample(N=1e4)
Evaluate the full model response at the validation sample points:
Yval = uq.evalModel(myModel,Xval)
Evaluate the corresponding responses for each of the three PCE metamodels created before:
YLARS = uq.evalModel(myPCE_Legendre,Xval)
YArb = uq.evalModel(myPCE_Arbitrary,Xval)
YPCE = [YLARS, YArb]
Comparison of the results¶
To visually assess the performance of each metamodel, produce scatter plots of the metamodel vs. the true response on the validation set:
methodLabels = ['Legendre','Arbitrary']
fig = plt.figure(figsize=(3,3), dpi=300, constrained_layout=True)
for idx,mLabel in enumerate(methodLabels):
plt.subplot(1,2,idx+1)
plt.scatter(Yval, YPCE[idx], color=uq_colors[idx], marker='.',alpha=.5, s=1)
plt.plot([np.min(Yval), np.max(Yval)], [np.min(Yval), np.max(Yval)], 'k--',linewidth=.5)
plt.title(methodLabels[idx],fontsize=8)
plt.xlabel('$Y_{true}$',fontsize=6)
plt.ylabel('$Y_{PC}$',fontsize=6)
plt.tick_params(axis='both', labelsize=6)
plt.xlim(np.min(Yval), np.max(Yval))
plt.ylim(np.min(Yval), np.max(Yval))
plt.gca().set_aspect('equal', adjustable='box')
Terminate the remote UQCloud session¶
mySession.quit()
uqpylab.sessions :: INFO :: Session f01a706455a94b8c89c469cf0607e892 terminated.
True