API
AbstractGP
AbstractGP(kernel, seqs, num_tasks, default_task, solo_task, noise, tfs_noise, requires_grad_noise, shape_noise, derivatives, derivatives_coeffs, adaptive_nugget, ptransform)
Bases: Module
Source code in fastgps/abstract_gp.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | |
x
property
Current sampling locations.
A torch.Tensor for single task problems.
A list for multitask problems.
y
property
Current sampling values.
A torch.Tensor for single task problems.
A list for multitask problems.
save_params
load_params
fit
fit(loss_metric='MLL', iterations=5000, lr=None, optimizer=None, stop_crit_improvement_threshold=0.05, stop_crit_wait_iterations=10, store_hists=False, verbose=5, verbose_indent=4, cv_weights=1, update_prior_mean=True)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
loss_metric
|
str
|
either "MLL" (Marginal Log Likelihood) or "CV" (Cross Validation) or "GCV" (Generalized CV) |
'MLL'
|
iterations
|
int
|
number of optimization iterations |
5000
|
lr
|
float
|
learning rate for default optimizer |
None
|
optimizer
|
Optimizer
|
optimizer defaulted to |
None
|
stop_crit_improvement_threshold
|
float
|
stop fitting when the maximum number of iterations is reached or the best loss is note reduced by |
0.05
|
stop_crit_wait_iterations
|
int
|
number of iterations to wait for improved loss before early stopping, see the argument description for |
10
|
store_hists
|
Union[bool, int]
|
store parameter data every |
False
|
verbose
|
int
|
log every |
5
|
verbose_indent
|
int
|
size of the indent to be applied when logging, helpful for logging multiple models |
4
|
cv_weights
|
Union[str, Tensor]
|
weights for cross validation |
1
|
update_prior_mean
|
bool
|
if |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
hist_data |
dict
|
iteration history data. |
Source code in fastgps/abstract_gp.py
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 | |
get_x_next
Get the next sampling locations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
Union[int, Tensor]
|
maximum sample index per task |
required |
task
|
Union[int, Tensor]
|
task index |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
x_next |
Union[Tensor, List]
|
next samples in the sequence |
Source code in fastgps/abstract_gp.py
add_y_next
Add samples to the GP.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_next
|
Union[Tensor, List]
|
new function evaluations at next sampling locations |
required |
task
|
Union[int, Tensor]
|
task index |
None
|
Source code in fastgps/abstract_gp.py
post_mean
Posterior mean.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Tensor[N, d]
|
sampling locations |
required |
task
|
Union[int, Tensor[T]]
|
task index |
None
|
eval
|
bool
|
if |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
pmean |
Tensor[..., T, N]
|
posterior mean |
Source code in fastgps/abstract_gp.py
post_var
Posterior variance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Tensor[N, d]
|
sampling locations |
required |
task
|
Union[int, Tensor[T]]
|
task indices |
None
|
n
|
Union[int, Tensor[num_tasks]]
|
number of points at which to evaluate the posterior cubature variance. |
None
|
eval
|
bool
|
if |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
pvar |
Tensor[T, N]
|
posterior variance |
Source code in fastgps/abstract_gp.py
post_cov
Posterior covariance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x0
|
Tensor[N, d]
|
left sampling locations |
required |
x1
|
Tensor[M, d]
|
right sampling locations |
required |
task0
|
Union[int, Tensor[T1]]
|
left task index |
None
|
task1
|
Union[int, Tensor[T2]]
|
right task index |
None
|
n
|
Union[int, Tensor[num_tasks]]
|
number of points at which to evaluate the posterior cubature variance. |
None
|
eval
|
bool
|
if |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
pcov |
Tensor[T1, T2, N, M]
|
posterior covariance matrix |
Source code in fastgps/abstract_gp.py
post_error
Posterior error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Tensor[N, d]
|
sampling locations |
required |
task
|
Union[int, Tensor[T]]
|
task indices |
None
|
n
|
Union[int, Tensor[num_tasks]]
|
number of points at which to evaluate the posterior cubature variance. |
None
|
eval
|
bool
|
if |
True
|
confidence
|
float
|
confidence level in \((0,1)\) for the credible interval |
0.99
|
Returns:
| Name | Type | Description |
|---|---|---|
cvar |
Tensor[T]
|
posterior variance |
quantile |
float64
|
|
perror |
Tensor[T]
|
posterior error |
Source code in fastgps/abstract_gp.py
post_ci
Posterior credible interval.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Tensor[N, d]
|
sampling locations |
required |
task
|
Union[int, Tensor[T]]
|
task indices |
None
|
confidence
|
float
|
confidence level in \((0,1)\) for the credible interval |
0.99
|
eval
|
bool
|
if |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
pmean |
Tensor[..., T, N]
|
posterior mean |
pvar |
Tensor[T, N]
|
posterior variance |
quantile |
float64
|
|
pci_low |
Tensor[..., T, N]
|
posterior credible interval lower bound |
pci_high |
Tensor[..., T, N]
|
posterior credible interval upper bound |
Source code in fastgps/abstract_gp.py
post_cubature_mean
Posterior cubature mean.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
eval
|
bool
|
if |
True
|
task
|
Union[int, Tensor[T]]
|
task indices |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
pcmean |
Tensor[..., T]
|
posterior cubature mean |
Source code in fastgps/abstract_gp.py
post_cubature_var
Posterior cubature variance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task
|
Union[int, Tensor[T]]
|
task indices |
None
|
n
|
Union[int, Tensor[num_tasks]]
|
number of points at which to evaluate the posterior cubature variance. |
None
|
eval
|
bool
|
if |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
pcvar |
Tensor[T]
|
posterior cubature variance |
Source code in fastgps/abstract_gp.py
post_cubature_cov
Posterior cubature covariance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task0
|
Union[int, Tensor[T1]]
|
task indices |
None
|
task1
|
Union[int, Tensor[T2]]
|
task indices |
None
|
n
|
Union[int, Tensor[num_tasks]]
|
number of points at which to evaluate the posterior cubature covariance. |
None
|
eval
|
bool
|
if |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
pcvar |
Tensor[T1, T2]
|
posterior cubature covariance |
Source code in fastgps/abstract_gp.py
post_cubature_error
Posterior cubature error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task
|
Union[int, Tensor[T]]
|
task indices |
None
|
n
|
Union[int, Tensor[num_tasks]]
|
number of points at which to evaluate the posterior cubature variance. |
None
|
eval
|
bool
|
if |
True
|
confidence
|
float
|
confidence level in \((0,1)\) for the credible interval |
0.99
|
Returns:
| Name | Type | Description |
|---|---|---|
pcvar |
Tensor[T]
|
posterior cubature variance |
quantile |
float64
|
|
pcerror |
Tensor[T]
|
posterior cubature error |
Source code in fastgps/abstract_gp.py
post_cubature_ci
Posterior cubature credible.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task
|
Union[int, Tensor[T]]
|
task indices |
None
|
confidence
|
float
|
confidence level in \((0,1)\) for the credible interval |
0.99
|
eval
|
bool
|
if |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
pcmean |
Tensor[..., T]
|
posterior cubature mean |
pcvar |
Tensor[T]
|
posterior cubature variance |
quantile |
float64
|
|
pcci_low |
Tensor[..., T]
|
posterior cubature credible interval lower bound |
pcci_high |
Tensor[..., T]
|
posterior cubature credible interval upper bound |
Source code in fastgps/abstract_gp.py
StandardGP
StandardGP(kernel, seqs, noise=0.0001, tfs_noise=(qp.util.transforms.tf_exp_eps_inv, qp.util.transforms.tf_exp_eps), requires_grad_noise=False, shape_noise=torch.Size([1]), derivatives=None, derivatives_coeffs=None, adaptive_nugget=True, data=None, ptransform=None)
Bases: AbstractGP
Standard Gaussian process regression
Examples:
>>> def f_ackley(x, a=20, b=0.2, c=2*np.pi, scaling=32.768):
... # https://www.sfu.ca/~ssurjano/ackley.html
... assert x.ndim==2
... x = 2*scaling*x-scaling
... t1 = a*torch.exp(-b*torch.sqrt(torch.mean(x**2,1)))
... t2 = torch.exp(torch.mean(torch.cos(c*x),1))
... t3 = a+np.exp(1)
... y = -t1-t2+t3
... return y
>>> n = 2**6
>>> d = 2
>>> sgp = StandardGP(
... qp.KernelSquaredExponential(d,torchify=True,device=device),
... qp.DigitalNetB2(dimension=d,seed=7))
>>> x_next = sgp.get_x_next(n)
>>> y_next = f_ackley(x_next)
>>> sgp.add_y_next(y_next)
>>> rng = torch.Generator().manual_seed(17)
>>> x = torch.rand((2**7,d),generator=rng).to(device)
>>> y = f_ackley(x)
>>> pmean.shape
torch.Size([128])
>>> torch.linalg.norm(y-pmean)/torch.linalg.norm(y)
tensor(0.0817)
>>> torch.linalg.norm(sgp.post_mean(sgp.x)-sgp.y)/torch.linalg.norm(y)
tensor(0.0402)
>>> torch.linalg.norm(y-sgp.post_mean(x))/torch.linalg.norm(y)
tensor(0.0472)
>>> z = torch.rand((2**8,d),generator=rng).to(device)
>>> pcov = sgp.post_cov(x,z)
>>> pcov.shape
torch.Size([128, 256])
>>> pcov = sgp.post_cov(x,x)
>>> pcov.shape
torch.Size([128, 128])
>>> (pcov.diagonal()>=0).all()
tensor(True)
>>> pvar = sgp.post_var(x)
>>> pvar.shape
torch.Size([128])
>>> torch.allclose(pcov.diagonal(),pvar)
True
>>> pmean,pstd,q,ci_low,ci_high = sgp.post_ci(x,confidence=0.99)
>>> ci_low.shape
torch.Size([128])
>>> ci_high.shape
torch.Size([128])
>>> pcmean,pcvar,q,pcci_low,pcci_high = sgp.post_cubature_ci(confidence=0.99)
>>> pcci_low
tensor(20.2684)
>>> pcci_high
tensor(20.4647)
>>> pcov_future = sgp.post_cov(x,z,n=2*n)
>>> pvar_future = sgp.post_var(x,n=2*n)
>>> pcvar_future = sgp.post_cubature_var(n=2*n)
>>> x_next = sgp.get_x_next(2*n)
>>> y_next = f_ackley(x_next)
>>> sgp.add_y_next(y_next)
>>> torch.linalg.norm(y-sgp.post_mean(x))/torch.linalg.norm(y)
tensor(0.0589)
>>> torch.allclose(sgp.post_cov(x,z),pcov_future)
True
>>> torch.allclose(sgp.post_var(x),pvar_future)
True
>>> torch.allclose(sgp.post_cubature_var(),pcvar_future)
True
>>> data = sgp.fit(verbose=False)
>>> torch.linalg.norm(y-sgp.post_mean(x))/torch.linalg.norm(y)
tensor(0.0440)
>>> x_next = sgp.get_x_next(4*n)
>>> y_next = f_ackley(x_next)
>>> sgp.add_y_next(y_next)
>>> torch.linalg.norm(y-sgp.post_mean(x))/torch.linalg.norm(y)
tensor(0.0923)
>>> data = sgp.fit(verbose=False)
>>> torch.linalg.norm(y-sgp.post_mean(x))/torch.linalg.norm(y)
tensor(0.0412)
>>> pcov_16n = sgp.post_cov(x,z,n=16*n)
>>> pvar_16n = sgp.post_var(x,n=16*n)
>>> pcvar_16n = sgp.post_cubature_var(n=16*n)
>>> x_next = sgp.get_x_next(16*n)
>>> y_next = f_ackley(x_next)
>>> sgp.add_y_next(y_next)
>>> torch.allclose(sgp.post_cov(x,z),pcov_16n)
True
>>> torch.allclose(sgp.post_var(x),pvar_16n)
True
>>> torch.allclose(sgp.post_cubature_var(),pcvar_16n)
True
Different loss metrics for fitting
>>> n = 2**6
>>> d = 3
>>> sgp = StandardGP(
... qp.KernelMatern52(d,torchify=True,device=device),
... qp.DigitalNetB2(dimension=d,seed=7))
>>> x_next = sgp.get_x_next(n)
>>> y_next = torch.stack([torch.sin(x_next).sum(-1),torch.cos(x_next).sum(-1)],axis=0)
>>> sgp.add_y_next(y_next)
>>> data = sgp.fit(loss_metric="MLL",iterations=5,verbose=0)
>>> data = sgp.fit(loss_metric="CV",iterations=5,verbose=0,cv_weights=1/torch.arange(1,2*n+1,device=device).reshape((2,n)))
>>> data = sgp.fit(loss_metric="CV",iterations=5,verbose=0,cv_weights="L2R")
>>> data = sgp.fit(loss_metric="GCV",iterations=5,verbose=0)
Data Driven
>>> x = [
... torch.rand((3,1),generator=rng).to(device),
... torch.rand((12,1),generator=rng).to(device),
... ]
>>> y = [
... torch.stack([torch.sin(2*np.pi*x[0][:,0]),torch.cos(2*np.pi*x[0][:,0]),torch.acos(x[0][:,0])],dim=0).to(device),
... torch.stack([4*torch.sin(2*np.pi*x[1][:,0]),4*torch.cos(2*np.pi*x[1][:,0]),4*torch.acos(x[1][:,0])],dim=0).to(device),
... ]
>>> sgp = StandardGP(
... qp.KernelMultiTask(
... qp.KernelGaussian(d=1,torchify=True,device=device),
... num_tasks = 2,
... ),
... seqs={"x":x,"y":y},
... noise = 1e-3,
... )
>>> data = sgp.fit(verbose=0,iterations=10)
>>> xticks = torch.linspace(0,1,101,device=device)
>>> pmean,pvar,q,pci_low,pci_high = sgp.post_ci(xticks[:,None])
>>> pcmean,pcvar,q,pcci_low,pcci_high = sgp.post_cubature_ci()
Batch Inference
>>> d = 4
>>> n = 2**10
>>> dnb2 = qp.DigitalNetB2(d,seed=11)
>>> kernel = qp.KernelGaussian(d,torchify=True,shape_scale=(2,1),shape_lengthscales=(3,2,d))
>>> fgp = StandardGP(kernel,dnb2)
>>> x = fgp.get_x_next(n)
>>> x.shape
torch.Size([1024, 4])
>>> y = (x**torch.arange(6).reshape((3,2))[:,:,None,None]).sum(-1)
>>> y.shape
torch.Size([3, 2, 1024])
>>> fgp.add_y_next(y)
>>> data = fgp.fit(verbose=0)
>>> fgp.post_cubature_mean()
tensor([[4.0000, 2.0000],
[1.3333, 1.0000],
[0.8000, 0.6666]])
>>> pcv = fgp.post_cubature_var()
>>> pcv.shape
torch.Size([3, 2])
>>> (pcv<5e-6).all()
tensor(True)
>>> pcv4 = fgp.post_cubature_var(n=4*n)
>>> pcv4.shape
torch.Size([3, 2])
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kernel
|
AbstractKernel
|
Kernel object. Set to |
required |
seqs
|
Union[int,qp.DiscreteDistribution,List]]
|
list of sequence generators. If an int qp.DiscreteDistribution docs for more info.
|
required |
noise
|
float
|
positive noise variance i.e. nugget term |
0.0001
|
tfs_noise
|
Tuple[callable, callable]
|
the first argument transforms to the raw value to be optimized, the second applies the inverse transform |
(tf_exp_eps_inv, tf_exp_eps)
|
requires_grad_noise
|
bool
|
wheather or not to optimize the noise parameter |
False
|
shape_noise
|
Size
|
shape of the noise parameter, defaults to |
Size([1])
|
derivatives
|
list
|
None
|
|
derivatives_coeffs
|
list
|
list of derivative coefficients where if |
None
|
adaptive_nugget
|
bool
|
if True, use the adaptive nugget which modifies noises based on trace ratios. |
True
|
data
|
dict
|
dictory of data with keys 'x' and 'y' where data['x'] and data['y'] are both |
None
|
ptransform
|
str
|
periodization transform in |
None
|
Source code in fastgps/standard_gp.py
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | |
AbstractFastGP
Bases: AbstractGP
Source code in fastgps/abstract_fast_gp.py
ft
One dimensional fast transform along the last dimenions.
For FastGPLattice this is the orthonormal Fast Fourier Transform (FFT).
For FastGPDigitalNetB2 this is the orthonormal Fast Walsh Hadamard Transform (FWHT).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Tensor
|
inputs to be transformed along the last dimension. Require |
required |
Returns:
| Name | Type | Description |
|---|---|---|
y |
Tensor
|
transformed inputs with the same shape as |
Source code in fastgps/abstract_fast_gp.py
ift
One dimensional inverse fast transform along the last dimenions.
For FastGPLattice this is the orthonormal Inverse Fast Fourier Transform (IFFT).
For FastGPDigitalNetB2 this is the orthonormal Fast Walsh Hadamard Transform (FWHT).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Tensor
|
inputs to be transformed along the last dimension. Require |
required |
Returns:
| Name | Type | Description |
|---|---|---|
y |
Tensor
|
transformed inputs with the same shape as |
Source code in fastgps/abstract_fast_gp.py
FastGPLattice
FastGPLattice(kernel, seqs, noise=2 * qp.util.transforms.EPS64, tfs_noise=(qp.util.transforms.tf_exp_eps_inv, qp.util.transforms.tf_exp_eps), requires_grad_noise=False, shape_noise=torch.Size([1]), derivatives=None, derivatives_coeffs=None, adaptive_nugget=False, ptransform=None)
Bases: AbstractFastGP
Fast Gaussian process regression using lattice points and shift invariant kernels
Examples:
>>> def f_ackley(x, a=20, b=0.2, c=2*np.pi, scaling=32.768):
... # https://www.sfu.ca/~ssurjano/ackley.html
... assert x.ndim==2
... x = 2*scaling*x-scaling
... t1 = a*torch.exp(-b*torch.sqrt(torch.mean(x**2,1)))
... t2 = torch.exp(torch.mean(torch.cos(c*x),1))
... t3 = a+np.exp(1)
... y = -t1-t2+t3
... return y
>>> n = 2**10
>>> d = 2
>>> fgp = FastGPLattice(
... qp.KernelShiftInvar(d,torchify=True,device=device),
... seqs = qp.Lattice(dimension=d,seed=7))
>>> x_next = fgp.get_x_next(n)
>>> y_next = f_ackley(x_next)
>>> fgp.add_y_next(y_next)
>>> rng = torch.Generator().manual_seed(17)
>>> x = torch.rand((2**7,d),generator=rng).to(device)
>>> y = f_ackley(x)
>>> pmean = fgp.post_mean(x)
>>> pmean.shape
torch.Size([128])
>>> torch.linalg.norm(y-pmean)/torch.linalg.norm(y)
tensor(0.0334)
>>> torch.allclose(fgp.post_mean(fgp.x),fgp.y,atol=1e-3)
True
>>> torch.linalg.norm(y-fgp.post_mean(x))/torch.linalg.norm(y)
tensor(0.0360)
>>> z = torch.rand((2**8,d),generator=rng).to(device)
>>> pcov = fgp.post_cov(x,z)
>>> pcov.shape
torch.Size([128, 256])
>>> pcov = fgp.post_cov(x,x)
>>> pcov.shape
torch.Size([128, 128])
>>> (pcov.diagonal()>=0).all()
tensor(True)
>>> pvar = fgp.post_var(x)
>>> pvar.shape
torch.Size([128])
>>> torch.allclose(pcov.diagonal(),pvar)
True
>>> pmean,pstd,q,ci_low,ci_high = fgp.post_ci(x,confidence=0.99)
>>> ci_low.shape
torch.Size([128])
>>> ci_high.shape
torch.Size([128])
>>> pcmean,pcvar,q,pcci_low,pcci_high = fgp.post_cubature_ci(confidence=0.99)
>>> pcci_low
tensor(20.1798)
>>> pcci_high
tensor(20.1886)
>>> pcov_future = fgp.post_cov(x,z,n=2*n)
>>> pvar_future = fgp.post_var(x,n=2*n)
>>> pcvar_future = fgp.post_cubature_var(n=2*n)
>>> x_next = fgp.get_x_next(2*n)
>>> y_next = f_ackley(x_next)
>>> fgp.add_y_next(y_next)
>>> torch.linalg.norm(y-fgp.post_mean(x))/torch.linalg.norm(y)
tensor(0.0295)
>>> torch.allclose(fgp.post_cov(x,z),pcov_future)
True
>>> torch.allclose(fgp.post_var(x),pvar_future)
True
>>> torch.allclose(fgp.post_cubature_var(),pcvar_future)
True
>>> data = fgp.fit(verbose=False)
>>> torch.linalg.norm(y-fgp.post_mean(x))/torch.linalg.norm(y)
tensor(0.0274)
>>> x_next = fgp.get_x_next(4*n)
>>> y_next = f_ackley(x_next)
>>> fgp.add_y_next(y_next)
>>> torch.linalg.norm(y-fgp.post_mean(x))/torch.linalg.norm(y)
tensor(0.0277)
>>> data = fgp.fit(verbose=False)
>>> torch.linalg.norm(y-fgp.post_mean(x))/torch.linalg.norm(y)
tensor(0.0276)
>>> pcov_16n = fgp.post_cov(x,z,n=16*n)
>>> pvar_16n = fgp.post_var(x,n=16*n)
>>> pcvar_16n = fgp.post_cubature_var(n=16*n)
>>> x_next = fgp.get_x_next(16*n)
>>> y_next = f_ackley(x_next)
>>> fgp.add_y_next(y_next)
>>> torch.allclose(fgp.post_cov(x,z),pcov_16n)
True
>>> torch.allclose(fgp.post_var(x),pvar_16n)
True
>>> torch.allclose(fgp.post_cubature_var(),pcvar_16n)
True
Different loss metrics for fitting
>>> n = 2**6
>>> d = 3
>>> sgp = FastGPLattice(
... qp.KernelShiftInvar(d,torchify=True,device=device),
... qp.Lattice(dimension=d,seed=7))
>>> x_next = sgp.get_x_next(n)
>>> y_next = torch.stack([torch.sin(x_next).sum(-1),torch.cos(x_next).sum(-1)],axis=0)
>>> sgp.add_y_next(y_next)
>>> data = sgp.fit(loss_metric="MLL",iterations=5,verbose=0)
>>> data = sgp.fit(loss_metric="CV",iterations=5,verbose=0,cv_weights=1/torch.arange(1,2*n+1,device=device).reshape((2,n)))
>>> data = sgp.fit(loss_metric="CV",iterations=5,verbose=0,cv_weights="L2R")
>>> data = sgp.fit(loss_metric="GCV",iterations=5,verbose=0)
Batch Inference
>>> d = 4
>>> n = 2**10
>>> dnb2 = qp.Lattice(d,seed=7)
>>> kernel = qp.KernelSICombined(d,torchify=True,shape_alpha=(2,4,d),shape_scale=(2,1),shape_lengthscales=(3,2,d))
>>> fgp = FastGPLattice(kernel,dnb2)
>>> x = fgp.get_x_next(n)
>>> x.shape
torch.Size([1024, 4])
>>> y = (x**torch.arange(6).reshape((3,2))[:,:,None,None]).sum(-1)
>>> y.shape
torch.Size([3, 2, 1024])
>>> fgp.add_y_next(y)
>>> data = fgp.fit(verbose=0)
>>> fgp.post_cubature_mean()
tensor([[4.0000, 2.0001],
[1.3334, 1.0001],
[0.8001, 0.6668]])
>>> fgp.post_cubature_var()
tensor([[0.0008, 0.0008],
[0.0008, 0.0008],
[0.0008, 0.0008]])
>>> fgp.post_cubature_var(n=4*n)
tensor([[0., 0.],
[0., 0.],
[0., 0.]])
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kernel
|
(KernelShiftInvar, KernelShiftInvarCombined)
|
Kernel object. Set to |
required |
seqs
|
[int, Lattice, List]
|
list of lattice sequence generators
with order="RADICAL INVERSE" and randomize in qp.Lattice docs for more info
|
required |
noise
|
float
|
positive noise variance i.e. nugget term |
2 * EPS64
|
tfs_noise
|
Tuple[callable, callable]
|
the first argument transforms to the raw value to be optimized, the second applies the inverse transform |
(tf_exp_eps_inv, tf_exp_eps)
|
requires_grad_noise
|
bool
|
wheather or not to optimize the noise parameter |
False
|
shape_noise
|
Size
|
shape of the noise parameter, defaults to |
Size([1])
|
derivatives
|
list
|
None
|
|
derivatives_coeffs
|
list
|
list of derivative coefficients where if |
None
|
adaptive_nugget
|
bool
|
if True, use the adaptive nugget which modifies noises based on trace ratios. |
False
|
ptransform
|
str
|
periodization transform in |
None
|
Source code in fastgps/fast_gp_lattice.py
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | |
FastGPDigitalNetB2
FastGPDigitalNetB2(kernel, seqs, noise=2 * qp.util.transforms.EPS64, tfs_noise=(qp.util.transforms.tf_exp_eps_inv, qp.util.transforms.tf_exp_eps), requires_grad_noise=False, shape_noise=torch.Size([1]), derivatives=None, derivatives_coeffs=None, adaptive_nugget=False, ptransform=None)
Bases: AbstractFastGP
Fast Gaussian process regression using digitally shifted digital nets paired with digitally shift invariant kernels
Examples:
>>> def f_ackley(x, a=20, b=0.2, c=2*np.pi, scaling=32.768):
... # https://www.sfu.ca/~ssurjano/ackley.html
... assert x.ndim==2
... x = 2*scaling*x-scaling
... t1 = a*torch.exp(-b*torch.sqrt(torch.mean(x**2,1)))
... t2 = torch.exp(torch.mean(torch.cos(c*x),1))
... t3 = a+np.exp(1)
... y = -t1-t2+t3
... return y
>>> n = 2**10
>>> d = 2
>>> fgp = FastGPDigitalNetB2(
... qp.KernelDigShiftInvar(d,torchify=True,device=device),
... qp.DigitalNetB2(dimension=d,seed=7))
>>> x_next = fgp.get_x_next(n)
>>> y_next = f_ackley(x_next)
>>> fgp.add_y_next(y_next)
>>> rng = torch.Generator().manual_seed(17)
>>> x = torch.rand((2**7,d),generator=rng).to(device)
>>> y = f_ackley(x)
>>> pmean = fgp.post_mean(x)
>>> pmean.shape
torch.Size([128])
>>> torch.linalg.norm(y-pmean)/torch.linalg.norm(y)
tensor(0.0308)
>>> torch.allclose(fgp.post_mean(fgp.x),fgp.y)
True
>>> torch.linalg.norm(y-fgp.post_mean(x))/torch.linalg.norm(y)
tensor(0.0328)
>>> z = torch.rand((2**8,d),generator=rng).to(device)
>>> pcov = fgp.post_cov(x,z)
>>> pcov.shape
torch.Size([128, 256])
>>> pcov = fgp.post_cov(x,x)
>>> pcov.shape
torch.Size([128, 128])
>>> (pcov.diagonal()>=0).all()
tensor(True)
>>> pvar = fgp.post_var(x)
>>> pvar.shape
torch.Size([128])
>>> torch.allclose(pcov.diagonal(),pvar,atol=1e-5)
True
>>> pmean,pstd,q,ci_low,ci_high = fgp.post_ci(x,confidence=0.99)
>>> ci_low.shape
torch.Size([128])
>>> ci_high.shape
torch.Size([128])
>>> pcmean,pcvar,q,pcci_low,pcci_high = fgp.post_cubature_ci(confidence=0.99)
>>> pcci_low
tensor(20.1466)
>>> pcci_high
tensor(20.2227)
>>> pcov_future = fgp.post_cov(x,z,n=2*n)
>>> pvar_future = fgp.post_var(x,n=2*n)
>>> pcvar_future = fgp.post_cubature_var(n=2*n)
>>> x_next = fgp.get_x_next(2*n)
>>> y_next = f_ackley(x_next)
>>> fgp.add_y_next(y_next)
>>> torch.linalg.norm(y-fgp.post_mean(x))/torch.linalg.norm(y)
tensor(0.0267)
>>> torch.allclose(fgp.post_cov(x,z),pcov_future)
True
>>> torch.allclose(fgp.post_var(x),pvar_future)
True
>>> torch.allclose(fgp.post_cubature_var(),pcvar_future)
True
>>> data = fgp.fit(verbose=False)
>>> torch.linalg.norm(y-fgp.post_mean(x))/torch.linalg.norm(y)
tensor(0.0254)
>>> x_next = fgp.get_x_next(4*n)
>>> y_next = f_ackley(x_next)
>>> fgp.add_y_next(y_next)
>>> torch.linalg.norm(y-fgp.post_mean(x))/torch.linalg.norm(y)
tensor(0.0162)
>>> data = fgp.fit(verbose=False)
>>> torch.linalg.norm(y-fgp.post_mean(x))/torch.linalg.norm(y)
tensor(0.0132)
>>> pcov_16n = fgp.post_cov(x,z,n=16*n)
>>> pvar_16n = fgp.post_var(x,n=16*n)
>>> pcvar_16n = fgp.post_cubature_var(n=16*n)
>>> x_next = fgp.get_x_next(16*n)
>>> y_next = f_ackley(x_next)
>>> fgp.add_y_next(y_next)
>>> torch.allclose(fgp.post_cov(x,z),pcov_16n)
True
>>> torch.allclose(fgp.post_var(x),pvar_16n)
True
>>> torch.allclose(fgp.post_cubature_var(),pcvar_16n)
True
Different loss metrics for fitting
>>> n = 2**6
>>> d = 3
>>> sgp = FastGPDigitalNetB2(
... qp.KernelDigShiftInvar(d,torchify=True,device=device),
... qp.DigitalNetB2(dimension=d,seed=7))
>>> x_next = sgp.get_x_next(n)
>>> y_next = torch.stack([torch.sin(x_next).sum(-1),torch.cos(x_next).sum(-1)],axis=0)
>>> sgp.add_y_next(y_next)
>>> data = sgp.fit(loss_metric="MLL",iterations=5,verbose=0)
>>> data = sgp.fit(loss_metric="CV",iterations=5,verbose=0,cv_weights=1/torch.arange(1,2*n+1,device=device).reshape((2,n)))
>>> data = sgp.fit(loss_metric="CV",iterations=5,verbose=0,cv_weights="L2R")
>>> data = sgp.fit(loss_metric="GCV",iterations=5,verbose=0)
Batch Inference
>>> d = 4
>>> n = 2**10
>>> dnb2 = qp.DigitalNetB2(d,seed=7)
>>> kernel = qp.KernelDSICombined(d,torchify=True,shape_alpha=(2,4,d),shape_scale=(2,1),shape_lengthscales=(3,2,d))
>>> fgp = FastGPDigitalNetB2(kernel,dnb2)
>>> x = fgp.get_x_next(n)
>>> x.shape
torch.Size([1024, 4])
>>> y = (x**torch.arange(6).reshape((3,2))[:,:,None,None]).sum(-1)
>>> y.shape
torch.Size([3, 2, 1024])
>>> fgp.add_y_next(y)
>>> data = fgp.fit(verbose=0)
>>> fgp.post_cubature_mean()
tensor([[4.0000, 2.0000],
[1.3333, 1.0000],
[0.8000, 0.6667]])
>>> fgp.post_cubature_var()
tensor([[2.2939e-16, 9.6623e-09],
[1.6232e-08, 7.8090e-09],
[3.7257e-08, 2.0389e-08]])
>>> fgp.post_cubature_var(n=4*n)
tensor([[2.9341e-18, 2.2246e-10],
[2.8796e-10, 1.6640e-10],
[5.9842e-10, 3.7897e-10]])
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kernel
|
Union[KernelDigShiftInvar, KernelDigShiftInvarAdaptiveAlpha, KernelDigShiftInvarCombined]
|
Kernel object. Set to |
required |
seqs
|
Union[int,qp.DigitalNetB2,List]]
|
list of digital sequence generators in base \(b=2\)
with order="RADICAL INVERSE" and randomize in qp.DigitalNetB2 docs for more info.
If num_tasks==1 then randomize may be in ["FALSE","DS","LMS","LMS DS"].
|
required |
noise
|
float
|
positive noise variance i.e. nugget term |
2 * EPS64
|
tfs_noise
|
Tuple[callable, callable]
|
the first argument transforms to the raw value to be optimized, the second applies the inverse transform |
(tf_exp_eps_inv, tf_exp_eps)
|
requires_grad_noise
|
bool
|
wheather or not to optimize the noise parameter |
False
|
shape_noise
|
Size
|
shape of the noise parameter, defaults to |
Size([1])
|
derivatives
|
list
|
None
|
|
derivatives_coeffs
|
list
|
list of derivative coefficients where if |
None
|
adaptive_nugget
|
bool
|
if True, use the adaptive nugget which modifies noises based on trace ratios. |
False
|
ptransform
|
str
|
periodization transform in |
None
|
Source code in fastgps/fast_gp_digital_net_b2.py
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | |