Skip to content

Commit 6a27f93

Browse files
authored
Merge pull request #18 from sandialabs/16-move-bcs-wrapper-into-pce-surrogate-class
16 move bcs wrapper into pce surrogate class
2 parents 94b120a + ffc0489 commit 6a27f93

File tree

4 files changed

+830
-8
lines changed

4 files changed

+830
-8
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,5 @@ cython_debug/
169169

170170
# PyPI configuration file
171171
.pypirc
172+
173+
**/.DS_Store

examples/surrogates/ex_genz_bcs.ipynb

Lines changed: 797 additions & 0 deletions
Large diffs are not rendered by default.

examples/surrogates/ex_pce.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
from pytuq.utils.maps import scale01ToDom
1111
from pytuq.lreg.anl import anl
1212
from pytuq.lreg.lreg import lsq
13+
from pytuq.utils.mindex import get_mi
14+
1315

1416
########################################################
1517
########################################################
@@ -49,6 +51,7 @@
4951
# print(pce.build(regression = 'anl', method = 'vi'))
5052
print(pce.build())
5153
# print(pce.build(regression = 'lsq'))
54+
# print(pce.build(regression = 'bcs'))
5255

5356
# (3) Make predictions for data points and print results:
5457
results = pce.evaluate(x)

src/pytuq/surrogates/pce.py

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from pytuq.utils.mindex import get_mi
2222
from pytuq.lreg.lreg import lsq
2323
from pytuq.lreg.anl import anl
24+
from pytuq.lreg.bcs import bcs
2425

2526

2627
class PCE:
@@ -33,12 +34,13 @@ class PCE:
3334
pctype (list[str]): Type of PC polynomial used.
3435
outdim (int): Physical dimensionality, i.e. # of output variables.
3536
lreg (lreg object): Linear regression object used for fitting the model.
37+
mindex (int np.ndarray): Multiindex array carrying the powers to which the basis functions will be raised to within the PC terms.
3638
regression_method (str): Method used for linear regression. ex] anl, opt, lsq
3739
_x_train (np.ndarray): Input training data
3840
_y_train (np.ndarray): Output training data, corresponding to x_train
3941
"""
4042

41-
def __init__(self, pce_dim, pce_order, pce_type, **kwargs):
43+
def __init__(self, pce_dim, pce_order, pce_type, verbose=0, **kwargs):
4244
r"""Initializes a Polynomial Chaos Random Variable (PCRV) with, at minimum:
4345
stochastic dimensionality, order, and polynomial chaos (PC) type.
4446
@@ -48,6 +50,7 @@ def __init__(self, pce_dim, pce_order, pce_type, **kwargs):
4850
pce_order (int): Order of the PC expansion.
4951
pce_type (str or list): PC type. Either a list of :math:`s` strings (one per stochastic dimension),
5052
or a single string for all dimensions. Supported types include 'LU' (Legendre) and 'HG' (Hermite-Gaussian).
53+
verbose (int): Output verbosity. Higher values print out more information. Default of 0
5154
pce_outdim (int, optional): Physical dimensionality :math:`s` of the PC random variable/vector.
5255
Default of 1 indicates a scalar-valued output.
5356
mi (list or np.ndarray, optional): List of :math:`d` multiindex arrays, each of size :math:`(K_i,s)` for :math:`i=1, \dots, d`.
@@ -66,18 +69,24 @@ def __init__(self, pce_dim, pce_order, pce_type, **kwargs):
6669
self.order = pce_order
6770
self.pctype = pce_type # Choose from options: 'LU', 'HG', or mix of ['HG', 'LU']
6871
self.outdim = kwargs.get('pce_outdim', 1) # Scalar valued output
72+
self.verbose = verbose
6973

7074
self.lreg = None
7175
self._x_train = None
7276
self._y_train = None
7377
self.regression_method = None
7478

79+
# Get the original multiindex, before possible modification in build
80+
self.mindex = kwargs.get('mi', get_mi(self.order, self.sdim))
81+
7582
self.pcrv = PCRV(self.outdim, self.sdim, self.pctype,
76-
mi = kwargs.get('mi', get_mi(self.order, self.sdim)),
77-
cfs = kwargs.get('cfs'))
83+
mi = self.mindex,
84+
cfs = kwargs.get('cfs'))
7885

79-
print(self.pcrv, end='\n\n')
80-
# self.pcrv.printInfo() # Useful for vector valued functions
86+
if self.verbose > 0:
87+
print("Constructed PC Surrogate with the following attributes:")
88+
print(self.pcrv, end='\n\n')
89+
# self.pcrv.printInfo()
8190

8291
def set_training_data(self, x_train, y_train):
8392
r"""Sets the training data with validation.
@@ -127,11 +136,14 @@ def build(self, **kwargs):
127136
- prior_var (float): Available for regression type 'anl', method 'full'.
128137
129138
Returns:
130-
np.ndarray: Coefficients for matrix
139+
np.ndarray: PC coefficients
131140
"""
132141
if self._x_train is None or self._y_train is None:
133142
raise RuntimeError("Training data must be set using set_training_data() before calling build().")
134143

144+
# Reset the multiindex and coefficients
145+
self.pcrv.setMiCfs(self.mindex, cfs=None)
146+
135147
regression = kwargs.get('regression', 'lsq')
136148

137149
if regression == 'lsq':
@@ -142,11 +154,15 @@ def build(self, **kwargs):
142154
self.lreg = anl(method='vi', datavar=kwargs.get('datavar'), cov_nugget=kwargs.get('cov_nugget', 0.0))
143155
else:
144156
self.lreg = anl(datavar=kwargs.get('datavar'), prior_var=kwargs.get('prior_var'), cov_nugget=kwargs.get('cov_nugget', 0.0))
157+
elif regression == 'bcs':
158+
self.lreg = bcs(eta=kwargs.get('eta', 1.e-8), datavar_init=kwargs.get('datavar_init'))
145159
else:
146160
raise ValueError(f"Regression method '{regression}' is not recognized and/or supported yet.")
147161

148162
self.regression_method = type(self.lreg).__name__
149-
print("Regression method:", self.regression_method)
163+
164+
if self.verbose > 0:
165+
print("Regression method:", self.regression_method)
150166

151167
def basisevaluator(x, pars):
152168
self.pcrv, = pars
@@ -155,6 +171,10 @@ def basisevaluator(x, pars):
155171
self.lreg.setBasisEvaluator(basisevaluator, (self.pcrv,))
156172
self.lreg.fit(self._x_train, self._y_train)
157173

174+
# Update the multi-index and coefficients retained by BCS as attributes of pcrv object
175+
if regression == 'bcs':
176+
self.pcrv.setMiCfs([self.mindex[self.lreg.used,:]], [self.lreg.cf])
177+
158178
return self.lreg.cf
159179

160180
def evaluate(self, x_eval, **kwargs):
@@ -166,7 +186,7 @@ def evaluate(self, x_eval, **kwargs):
166186
data_variance (bool, optional): Whether to compute posterior-predictive (i.e. add data variance) or not.
167187
168188
Returns:
169-
dictionary: Dictionary of predicted y-values, along with standard deviation, covariance, and variance of predictions if applicable.
189+
dict: Values for predicted y-values, standard deviation, covariance, and variance of predictions (if applicable) as np.ndarrays.
170190
"""
171191
# If single output (scalar-valued function), standard deviation and variance are calculated,
172192
# but not covariance.

0 commit comments

Comments
 (0)