Kernels
UML Overview
AbstractKernel
Bases: object
Source code in qmcpy/kernel/abstract_kernel.py
__call__
Evaluate the kernel with (optional) partial derivatives
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x0
|
Union[ndarray, Tensor]
|
Shape |
required |
x1
|
Union[ndarray, Tensor]
|
Shape |
required |
beta0
|
Union[ndarray, Tensor]
|
Shape |
None
|
beta1
|
Union[ndarray, Tensor]
|
Shape |
None
|
c
|
Union[ndarray, Tensor]
|
Shape |
None
|
kwargs
|
dict
|
keyword arguments to parsed call |
{}
|
Returns:
k (Union[np.ndarray,torch.Tensor]): Shape y.shape=(x0+x1).shape[:-1] kernel evaluations.
Source code in qmcpy/kernel/abstract_kernel.py
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 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | |
single_integral_01d
Evaluate the integral of the kernel over the unit cube
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Union[ndarray, Tensor]
|
Shape |
required |
Returns:
| Name | Type | Description |
|---|---|---|
tildek |
Union[ndarray, Tensor]
|
Shape |
Source code in qmcpy/kernel/abstract_kernel.py
double_integral_01d
Evaluate the integral of the kernel over the unit cube
Returns:
| Name | Type | Description |
|---|---|---|
tildek |
Union[ndarray, Tensor]
|
Double integral kernel evaluations. |
Source code in qmcpy/kernel/abstract_kernel.py
AbstractKernelScaleLengthscales
Bases: AbstractKernel
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
d
|
int
|
Dimension. |
required |
scale
|
Union[ndarray, Tensor]
|
Scaling factor \(S\). |
1.0
|
lengthscales
|
Union[ndarray, Tensor]
|
Lengthscales \(\boldsymbol{\gamma}\). |
1.0
|
shape_scale
|
list
|
Shape of |
[1]
|
shape_lengthscales
|
list
|
Shape of |
None
|
tfs_scale
|
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)
|
tfs_lengthscales
|
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)
|
torchify
|
bool
|
If |
False
|
requires_grad_scale
|
bool
|
If |
True
|
requires_grad_lengthscales
|
bool
|
If |
True
|
device
|
device
|
If |
'cpu'
|
compile_call
|
bool
|
If |
False
|
comiple_call_kwargs
|
dict
|
When |
{}
|
Source code in qmcpy/kernel/abstract_kernel.py
KernelShiftInvar
Bases: AbstractSIDSIKernel
Shift invariant kernel with smoothness \(\boldsymbol{\alpha}\), product weights (lengthscales) \(\boldsymbol{\gamma}\), and scale \(S\):
where \(B_n\) is the \(n^\text{th}\) Bernoulli polynomial.
Examples:
>>> from qmcpy import Lattice, fftbr, ifftbr
>>> n = 8
>>> d = 4
>>> lat = Lattice(d,seed=11)
>>> x = lat(n)
>>> x.shape
(8, 4)
>>> x.dtype
dtype('float64')
>>> kernel = KernelShiftInvar(
... d = d,
... alpha = list(range(1,d+1)),
... scale = 10,
... lengthscales = [1/j**2 for j in range(1,d+1)])
>>> k00 = kernel(x[0],x[0])
>>> k00.item()
91.23444453396341
>>> k0 = kernel(x,x[0])
>>> with np.printoptions(precision=2):
... print(k0)
[91.23 -2.32 5.69 5.69 12.7 -4.78 -4.78 12.7 ]
>>> assert k0[0]==k00
>>> kmat = kernel(x[:,None,:],x[None,:,:])
>>> with np.printoptions(precision=2):
... print(kmat)
[[91.23 -2.32 5.69 5.69 12.7 -4.78 -4.78 12.7 ]
[-2.32 91.23 5.69 5.69 -4.78 12.7 12.7 -4.78]
[ 5.69 5.69 91.23 -2.32 12.7 -4.78 12.7 -4.78]
[ 5.69 5.69 -2.32 91.23 -4.78 12.7 -4.78 12.7 ]
[12.7 -4.78 12.7 -4.78 91.23 -2.32 5.69 5.69]
[-4.78 12.7 -4.78 12.7 -2.32 91.23 5.69 5.69]
[-4.78 12.7 12.7 -4.78 5.69 5.69 91.23 -2.32]
[12.7 -4.78 -4.78 12.7 5.69 5.69 -2.32 91.23]]
>>> assert (kmat[:,0]==k0).all()
>>> lam = np.sqrt(n)*fftbr(k0)
>>> y = np.random.Generator(np.random.PCG64(7)).uniform(low=0,high=1,size=(n))
>>> np.allclose(ifftbr(fftbr(y)*lam),kmat@y)
True
>>> np.allclose(ifftbr(fftbr(y)/lam),np.linalg.solve(kmat,y))
True
>>> import torch
>>> xtorch = torch.from_numpy(x)
>>> kernel_torch = KernelShiftInvar(
... d = d,
... alpha = list(range(1,d+1)),
... scale = 10,
... lengthscales = [1/j**2 for j in range(1,d+1)],
... torchify = True)
>>> kmat_torch = kernel_torch(xtorch[:,None,:],xtorch[None,:,:])
>>> np.allclose(kmat_torch.detach().numpy(),kmat)
True
>>> kernel.single_integral_01d(x)
array([10., 10., 10., 10., 10., 10., 10., 10.])
>>> kernel_torch.single_integral_01d(xtorch)
tensor([10., 10., 10., 10., 10., 10., 10., 10.], dtype=torch.float64,
grad_fn=<AddBackward0>)
Batch Params
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelShiftInvar(
... d = 2,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,2])
>>> x = rng.uniform(low=0,high=1,size=(6,5,2))
>>> kernel(x,x).shape
(4, 3, 6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(4, 3, 6, 5, 5)
>>> kfast = kernel(x[:,None,:,None,:],x[None,:,None,:,:])
>>> kfast.shape
(4, 3, 6, 6, 5, 5)
>>> kstable = kernel(x[:,None,:,None,:],x[None,:,None,:,:],stable=True)
>>> np.abs(kfast-kstable).max()
np.float64(4.440892098500626e-16)
Derivatives
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> scale = rng.uniform(low=0,high=1,size=(1,))
>>> lengthscales = rng.uniform(low=0,high=1,size=(3,))
>>> kernel = KernelShiftInvar(
... d = 3,
... alpha = 3,
... torchify = True,
... scale = torch.from_numpy(scale),
... lengthscales = torch.from_numpy(lengthscales))
>>> x0 = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,))).requires_grad_(True)
>>> x1 = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,))).requires_grad_(True)
>>> x2 = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,))).requires_grad_(True)
>>> x = torch.stack([x0,x1,x2],axis=-1)
>>> z0 = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,))).requires_grad_(True)
>>> z1 = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,))).requires_grad_(True)
>>> z2 = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,))).requires_grad_(True)
>>> z = torch.stack([z0,z1,z2],axis=-1)
>>> c = torch.from_numpy(rng.uniform(low=0,high=1,size=(2,)))
>>> beta0 = torch.tensor([
... [1,0,0],
... [0,2,0]])
>>> beta1 = torch.tensor([
... [0,0,2],
... [2,1,0]])
>>> with torch.no_grad():
... y = kernel(x,z,beta0,beta1,c)
>>> with np.printoptions(formatter={"float": lambda x: "%.2f"%x}):
... y.numpy()
array([1455.14, 9475.57, 7807.08, 2785.47])
>>> y_no_deriv = kernel(x,z)
>>> y_first = y_no_deriv.clone()
>>> y_first = torch.autograd.grad(y_first,x0,grad_outputs=torch.ones_like(y_first,requires_grad=True),create_graph=True)[0]
>>> y_first = torch.autograd.grad(y_first,z2,grad_outputs=torch.ones_like(y_first,requires_grad=True),create_graph=True)[0]
>>> y_first = torch.autograd.grad(y_first,z2,grad_outputs=torch.ones_like(y_first,requires_grad=True),create_graph=True)[0]
>>> y_second = y_no_deriv.clone()
>>> y_second = torch.autograd.grad(y_second,x1,grad_outputs=torch.ones_like(y_second,requires_grad=True),create_graph=True)[0]
>>> y_second = torch.autograd.grad(y_second,x1,grad_outputs=torch.ones_like(y_second,requires_grad=True),create_graph=True)[0]
>>> y_second = torch.autograd.grad(y_second,z0,grad_outputs=torch.ones_like(y_second,requires_grad=True),create_graph=True)[0]
>>> y_second = torch.autograd.grad(y_second,z0,grad_outputs=torch.ones_like(y_second,requires_grad=True),create_graph=True)[0]
>>> y_second = torch.autograd.grad(y_second,z1,grad_outputs=torch.ones_like(y_second,requires_grad=True),create_graph=True)[0]
>>> yhat = (y_first*c[0]+y_second*c[1]).detach()
>>> with np.printoptions(formatter={"float": lambda x: "%.3f"%x}):
... yhat.numpy()
array([1455.140, 9475.570, 7807.076, 2785.473])
>>> torch.allclose(y,yhat)
True
>>> kernel = KernelShiftInvar(
... d = 3,
... alpha = 3,
... scale = scale,
... lengthscales = lengthscales)
>>> ynp = kernel(x.detach().numpy(),z.detach().numpy(),beta0.numpy(),beta1.numpy(),c.numpy())
>>> with np.printoptions(formatter={"float": lambda x: "%.2f"%x}):
... ynp
array([1455.14, 9475.59, 7807.09, 2785.48])
>>> np.allclose(ynp,y.numpy())
True
References:
- Kaarnioja, Vesa, Frances Y. Kuo, and Ian H. Sloan.
"Lattice-based kernel approximation and serendipitous weights for parametric PDEs in very high dimensions."
International Conference on Monte Carlo and Quasi-Monte Carlo Methods in Scientific Computing. Cham: Springer International Publishing, 2022.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
d
|
int
|
Dimension. |
required |
scale
|
Union[ndarray, Tensor]
|
Scaling factor \(S\). |
1.0
|
lengthscales
|
Union[ndarray, Tensor]
|
Product weights \((\gamma_1,\dots,\gamma_d)\). |
None
|
alpha
|
Union[ndarray, Tensor]
|
Smoothness parameters \((\alpha_1,\dots,\alpha_d)\) where \(\alpha_j \geq 1\) for \(j=1,\dots,d\). |
2
|
shape_scale
|
list
|
Shape of |
[1]
|
shape_lengthscales
|
list
|
Shape of |
None
|
tfs_scale
|
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)
|
tfs_lengthscales
|
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)
|
torchify
|
bool
|
If |
False
|
requires_grad_scale
|
bool
|
If |
True
|
requires_grad_lengthscales
|
bool
|
If |
True
|
device
|
device
|
If |
'cpu'
|
compile_call
|
bool
|
If |
False
|
comiple_call_kwargs
|
dict
|
When |
{}
|
Source code in qmcpy/kernel/si_dsi_kernels.py
KernelShiftInvarCombined
Bases: AbstractSIDSIKernel
Shift invariant kernel with combination weights \(\boldsymbol{\alpha}_1,\dots,\boldsymbol{\alpha}_d \in \mathbb{R}_{>0}^4\), product weights (lengthscales) \(\boldsymbol{\gamma}\), and scale \(S\):
where, \(\tilde{K}_p\) are defined in KernelShiftInvar for \(p \in \{1,2,3,4\}\)
Examples:
>>> from qmcpy import Lattice, fftbr, ifftbr
>>> n = 8
>>> d = 4
>>> lat = Lattice(d,seed=11)
>>> x = lat(n)
>>> x.shape
(8, 4)
>>> x.dtype
dtype('float64')
>>> kernel = KernelShiftInvarCombined(
... d = d,
... scale = 10,
... lengthscales = [1/j**2 for j in range(1,d+1)])
>>> k00 = kernel(x[0],x[0])
>>> k00.item()
117.22427096475315
>>> k0 = kernel(x,x[0])
>>> with np.printoptions(precision=2):
... print(k0)
[ 117.22 153.84 28.59 36.1 -139.83 77.1 -8.51 35.22]
>>> assert k0[0]==k00
>>> kmat = kernel(x[:,None,:],x[None,:,:])
>>> with np.printoptions(precision=2):
... print(kmat)
[[ 117.22 153.84 36.1 28.59 35.22 -8.51 77.1 -139.83]
[ 153.84 117.22 28.59 36.1 -8.51 35.22 -139.83 77.1 ]
[ 28.59 36.1 117.22 153.84 -139.83 77.1 35.22 -8.51]
[ 36.1 28.59 153.84 117.22 77.1 -139.83 -8.51 35.22]
[-139.83 77.1 35.22 -8.51 117.22 153.84 36.1 28.59]
[ 77.1 -139.83 -8.51 35.22 153.84 117.22 28.59 36.1 ]
[ -8.51 35.22 -139.83 77.1 28.59 36.1 117.22 153.84]
[ 35.22 -8.51 77.1 -139.83 36.1 28.59 153.84 117.22]]
>>> assert (kmat[:,0]==k0).all()
>>> lam = np.sqrt(n)*fftbr(k0)
>>> y = np.random.Generator(np.random.PCG64(7)).uniform(low=0,high=1,size=(n))
>>> np.allclose(ifftbr(fftbr(y)*lam),kmat@y)
True
>>> np.allclose(ifftbr(fftbr(y)/lam),np.linalg.solve(kmat,y))
True
>>> import torch
>>> xtorch = torch.from_numpy(x)
>>> kernel_torch = KernelShiftInvarCombined(
... d = d,
... scale = 10,
... lengthscales = [1/j**2 for j in range(1,d+1)],
... torchify = True)
>>> kmat_torch = kernel_torch(xtorch[:,None,:],xtorch[None,:,:])
>>> np.allclose(kmat_torch.detach().numpy(),kmat)
True
>>> kernel.single_integral_01d(x)
array([10., 10., 10., 10., 10., 10., 10., 10.])
>>> kernel_torch.single_integral_01d(xtorch)
tensor([10., 10., 10., 10., 10., 10., 10., 10.], dtype=torch.float64,
grad_fn=<AddBackward0>)
Batch Params
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelShiftInvarCombined(
... d = 2,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,2])
>>> x = rng.uniform(low=0,high=1,size=(6,5,2))
>>> kernel(x,x).shape
(4, 3, 6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(4, 3, 6, 5, 5)
>>> kfast = kernel(x[:,None,:,None,:],x[None,:,None,:,:])
>>> kfast.shape
(4, 3, 6, 6, 5, 5)
>>> kstable = kernel(x[:,None,:,None,:],x[None,:,None,:,:],stable=True)
>>> np.abs(kfast-kstable).max()
np.float64(3.552713678800501e-15)
References:
- Kaarnioja, Vesa, Frances Y. Kuo, and Ian H. Sloan.
"Lattice-based kernel approximation and serendipitous weights for parametric PDEs in very high dimensions."
International Conference on Monte Carlo and Quasi-Monte Carlo Methods in Scientific Computing. Cham: Springer International Publishing, 2022.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
d
|
int
|
Dimension. |
required |
scale
|
Union[ndarray, Tensor]
|
Scaling factor \(S\). |
1.0
|
lengthscales
|
Union[ndarray, Tensor]
|
Product weights \((\gamma_1,\dots,\gamma_d)\). |
None
|
alpha
|
Union[ndarray, Tensor]
|
Weights \(\boldsymbol{\alpha}_1,\dots,\boldsymbol{\alpha}_d \in \mathbb{R}_{>0}^4\). |
1
|
shape_scale
|
list
|
Shape of |
[1]
|
shape_lengthscales
|
list
|
Shape of |
None
|
shape_alpha
|
list
|
Shape of |
None
|
tfs_scale
|
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)
|
tfs_lengthscales
|
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)
|
tfs_alpha
|
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)
|
torchify
|
bool
|
If |
False
|
requires_grad_scale
|
bool
|
If |
True
|
requires_grad_lengthscales
|
bool
|
If |
True
|
requires_grad_alpha
|
bool
|
If |
True
|
device
|
device
|
If |
'cpu'
|
compile_call
|
bool
|
If |
False
|
comiple_call_kwargs
|
dict
|
When |
{}
|
Source code in qmcpy/kernel/si_dsi_kernels.py
KernelDigShiftInvar
Bases: AbstractSIDSIKernel
Digitally shift invariant kernel in base \(b=2\) with smoothness \(\boldsymbol{\alpha}\), product weights \(\boldsymbol{\gamma}\), and scale \(S\):
where
- \(x \oplus z\) is XOR between bits,
- \(\mathrm{wal}_k\) is the \(k^\text{th}\) Walsh function,
- \(\beta(x) = - \lfloor \log_2(x) \rfloor\) and \(t_\nu(x) = 2^{-\nu \beta(x)}\) where \(\beta(0)=t_\nu(0) = 0\), and
- and \(\mu_\alpha\) is the Dick weight function which sums the first \(\alpha\) largest indices of \(1\) bits in the binary expansion of \(k\) e.g. \(k=13=1101_2\) has 1-bit indexes \((4,3,1)\) so
Examples:
>>> from qmcpy import DigitalNetB2, fwht
>>> n = 8
>>> d = 4
>>> dnb2 = DigitalNetB2(d,seed=11)
>>> x = dnb2(n,return_binary=True)
>>> x.shape
(8, 4)
>>> x.dtype
dtype('uint64')
>>> kernel = KernelDigShiftInvar(
... d = d,
... t = dnb2.t,
... alpha = list(range(1,d+1)),
... scale = 10,
... lengthscales = [1/j**2 for j in range(1,d+1)])
>>> k00 = kernel(x[0],x[0])
>>> k00.item()
34.490370029184525
>>> k0 = kernel(x,x[0])
>>> with np.printoptions(precision=2):
... print(k0)
[34.49 4.15 9.59 4.98 15.42 5.45 11.99 4.51]
>>> assert k0[0]==k00
>>> kmat = kernel(x[:,None,:],x[None,:,:])
>>> with np.printoptions(precision=2):
... print(kmat)
[[34.49 4.15 9.59 4.98 15.42 5.45 11.99 4.51]
[ 4.15 34.49 4.98 9.59 5.45 15.42 4.51 11.99]
[ 9.59 4.98 34.49 4.15 11.99 4.51 15.42 5.45]
[ 4.98 9.59 4.15 34.49 4.51 11.99 5.45 15.42]
[15.42 5.45 11.99 4.51 34.49 4.15 9.59 4.98]
[ 5.45 15.42 4.51 11.99 4.15 34.49 4.98 9.59]
[11.99 4.51 15.42 5.45 9.59 4.98 34.49 4.15]
[ 4.51 11.99 5.45 15.42 4.98 9.59 4.15 34.49]]
>>> assert (kmat[:,0]==k0).all()
>>> lam = np.sqrt(n)*fwht(k0)
>>> y = np.random.Generator(np.random.PCG64(7)).uniform(low=0,high=1,size=(n))
>>> np.allclose(fwht(fwht(y)*lam),kmat@y)
True
>>> np.allclose(fwht(fwht(y)/lam),np.linalg.solve(kmat,y))
True
>>> import torch
>>> xtorch = bin_from_numpy_to_torch(x)
>>> kernel_torch = KernelDigShiftInvar(
... d = d,
... t = dnb2.t,
... alpha = list(range(1,d+1)),
... scale = 10,
... lengthscales = [1/j**2 for j in range(1,d+1)],
... torchify = True)
>>> kmat_torch = kernel_torch(xtorch[:,None,:],xtorch[None,:,:])
>>> np.allclose(kmat_torch.detach().numpy(),kmat)
True
>>> xf = to_float(x,dnb2.t)
>>> kmat_from_floats = kernel(xf[:,None,:],xf[None,:,:])
>>> np.allclose(kmat,kmat_from_floats)
True
>>> xftorch = to_float(xtorch,dnb2.t)
>>> xftorch.dtype
torch.float32
>>> kmat_torch_from_floats = kernel_torch(xftorch[:,None,:],xftorch[None,:,:])
>>> torch.allclose(kmat_torch_from_floats,kmat_torch)
True
>>> kernel.single_integral_01d(x)
array([10., 10., 10., 10., 10., 10., 10., 10.])
>>> kernel_torch.single_integral_01d(xtorch)
tensor([10., 10., 10., 10., 10., 10., 10., 10.], grad_fn=<AddBackward0>)
Batch Params
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelDigShiftInvar(
... d = 2,
... t = 10,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,2])
>>> x = rng.uniform(low=0,high=1,size=(6,5,2))
>>> kernel(x,x).shape
(4, 3, 6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(4, 3, 6, 5, 5)
>>> kfast = kernel(x[:,None,:,None,:],x[None,:,None,:,:])
>>> kfast.shape
(4, 3, 6, 6, 5, 5)
>>> kstable = kernel(x[:,None,:,None,:],x[None,:,None,:,:],stable=True)
>>> np.abs(kfast-kstable).max()
np.float64(4.440892098500626e-16)
References:
-
Dick, Josef.
"Walsh spaces containing smooth functions and quasi-Monte Carlo rules of arbitrary high order."
SIAM Journal on Numerical Analysis 46.3 (2008): 1519-1553. -
Dick, Josef.
"The decay of the Walsh coefficients of smooth functions."
Bulletin of the Australian Mathematical Society 80.3 (2009): 430-453. -
Jagadeeswaran, Rathinavel, and Fred J. Hickernell.
"Fast automatic Bayesian cubature using Sobol' sampling."
Advances in Modeling and Simulation: Festschrift for Pierre L'Ecuyer. Cham: Springer International Publishing, 2022. 301-318. -
Rathinavel, Jagadeeswaran.
Fast automatic Bayesian cubature using matching kernels and designs.
Illinois Institute of Technology, 2019. -
Sorokin, Aleksei.
"A Unified Implementation of Quasi-Monte Carlo Generators, Randomization Routines, and Fast Kernel Methods."
arXiv preprint arXiv:2502.14256 (2025).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
d
|
int
|
Dimension. |
required |
t
|
int
|
number of bits in binary represtnations. Typically |
None
|
scale
|
Union[ndarray, Tensor]
|
Scaling factor \(S\). |
1.0
|
lengthscales
|
Union[ndarray, Tensor]
|
Product weights \((\gamma_1,\dots,\gamma_d)\). |
None
|
alpha
|
Union[ndarray, Tensor]
|
Smoothness parameters \((\alpha_1,\dots,\alpha_d)\) where \(\alpha_j \geq 1\) for \(j=1,\dots,d\). |
2
|
shape_scale
|
list
|
Shape of |
[1]
|
shape_lengthscales
|
list
|
Shape of |
None
|
tfs_scale
|
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)
|
tfs_lengthscales
|
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)
|
torchify
|
bool
|
If |
False
|
requires_grad_scale
|
bool
|
If |
True
|
requires_grad_lengthscales
|
bool
|
If |
True
|
device
|
device
|
If |
'cpu'
|
compile_call
|
bool
|
If |
False
|
comiple_call_kwargs
|
dict
|
When |
{}
|
Source code in qmcpy/kernel/si_dsi_kernels.py
KernelDigShiftInvarAdaptiveAlpha
Bases: AbstractSIDSIKernel
Digitally shift invariant kernel in base \(b=2\) with smoothness \(\boldsymbol{\alpha} \geq \boldsymbol{0}\), product weights \(\boldsymbol{\gamma}\), and scale \(S\):
where
- \(x \oplus z\) is XOR between bits,
- \(\mathrm{wal}_k\) is the \(k^\text{th}\) Walsh function,
- \(\beta(x) = - \lfloor \log_2(x) \rfloor\) and \(t_\nu(x) = 2^{-\nu \beta(x)}\) where \(\beta(0)=t_\nu(0) = 0\), and
- and \(\mu_\alpha\) is the Dick weight function which sums the first \(\alpha\) largest indices of \(1\) bits in the binary expansion of \(k\) e.g. \(k=13=1101_2\) has 1-bit indexes \((4,3,1)\) so
Examples:
>>> from qmcpy import DigitalNetB2, fwht
>>> n = 8
>>> d = 4
>>> dnb2 = DigitalNetB2(d,seed=11)
>>> x = dnb2(n,return_binary=True)
>>> x.shape
(8, 4)
>>> x.dtype
dtype('uint64')
>>> kernel = KernelDigShiftInvarAdaptiveAlpha(
... d = d,
... t = dnb2.t,
... alpha = list(range(1,d+1)),
... scale = 10,
... lengthscales = [1/j**2 for j in range(1,d+1)])
>>> k00 = kernel(x[0],x[0])
>>> k00.item()
48.084656084656096
>>> k0 = kernel(x,x[0])
>>> with np.printoptions(precision=2):
... print(k0)
[48.08 0. 9.38 0. 19.74 0. 14.84 0. ]
>>> assert k0[0]==k00
>>> kmat = kernel(x[:,None,:],x[None,:,:])
>>> with np.printoptions(precision=2):
... print(kmat)
[[48.08 0. 9.38 0. 19.74 0. 14.84 0. ]
[ 0. 48.08 0. 9.38 0. 19.74 0. 14.84]
[ 9.38 0. 48.08 0. 14.84 0. 19.74 0. ]
[ 0. 9.38 0. 48.08 0. 14.84 0. 19.74]
[19.74 0. 14.84 0. 48.08 0. 9.38 0. ]
[ 0. 19.74 0. 14.84 0. 48.08 0. 9.38]
[14.84 0. 19.74 0. 9.38 0. 48.08 0. ]
[ 0. 14.84 0. 19.74 0. 9.38 0. 48.08]]
>>> assert (kmat[:,0]==k0).all()
>>> lam = np.sqrt(n)*fwht(k0)
>>> y = np.random.Generator(np.random.PCG64(7)).uniform(low=0,high=1,size=(n))
>>> np.allclose(fwht(fwht(y)*lam),kmat@y)
True
>>> np.allclose(fwht(fwht(y)/lam),np.linalg.solve(kmat,y))
True
>>> import torch
>>> xtorch = bin_from_numpy_to_torch(x)
>>> kernel_torch = KernelDigShiftInvarAdaptiveAlpha(
... d = d,
... t = dnb2.t,
... alpha = list(range(1,d+1)),
... scale = 10,
... lengthscales = [1/j**2 for j in range(1,d+1)],
... torchify = True)
>>> kmat_torch = kernel_torch(xtorch[:,None,:],xtorch[None,:,:])
>>> np.allclose(kmat_torch.detach().numpy(),kmat,atol=1e-5)
True
>>> xf = to_float(x,dnb2.t)
>>> kmat_from_floats = kernel(xf[:,None,:],xf[None,:,:])
>>> np.allclose(kmat,kmat_from_floats)
True
>>> xftorch = to_float(xtorch,dnb2.t)
>>> xftorch.dtype
torch.float32
>>> kmat_torch_from_floats = kernel_torch(xftorch[:,None,:],xftorch[None,:,:])
>>> torch.allclose(kmat_torch_from_floats,kmat_torch)
True
>>> kernel.single_integral_01d(x)
array([10., 10., 10., 10., 10., 10., 10., 10.])
>>> kernel_torch.single_integral_01d(xtorch)
tensor([10., 10., 10., 10., 10., 10., 10., 10.], grad_fn=<AddBackward0>)
Batch Params
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelDigShiftInvarAdaptiveAlpha(
... d = 2,
... t = 10,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,2])
>>> x = rng.uniform(low=0,high=1,size=(6,5,2))
>>> kernel(x,x).shape
(4, 3, 6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(4, 3, 6, 5, 5)
>>> kfast = kernel(x[:,None,:,None,:],x[None,:,None,:,:])
>>> kfast.shape
(4, 3, 6, 6, 5, 5)
>>> kstable = kernel(x[:,None,:,None,:],x[None,:,None,:,:],stable=True)
>>> np.abs(kfast-kstable).max()
np.float64(4.440892098500626e-16)
References:
- Dick, Josef, and Friedrich Pillichshammer.
"Multivariate integration in weighted Hilbert spaces based on Walsh functions and weighted Sobolev spaces."
Journal of Complexity 21.2 (2005): 149-195.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
d
|
int
|
Dimension. |
required |
t
|
int
|
number of bits in binary represtnations. Typically |
None
|
scale
|
Union[ndarray, Tensor]
|
Scaling factor \(S\). |
1.0
|
lengthscales
|
Union[ndarray, Tensor]
|
Product weights \((\gamma_1,\dots,\gamma_d)\). |
None
|
alpha
|
Union[ndarray, Tensor]
|
Smoothness parameters \((\alpha_1,\dots,\alpha_d)\) where \(\alpha_j \geq 1\) for \(j=1,\dots,d\). |
1
|
shape_alpha
|
list
|
Shape of |
None
|
shape_scale
|
list
|
Shape of |
[1]
|
shape_lengthscales
|
list
|
Shape of |
None
|
tfs_scale
|
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)
|
tfs_lengthscales
|
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)
|
tfs_alpha
|
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)
|
torchify
|
bool
|
If |
False
|
requires_grad_scale
|
bool
|
If |
True
|
requires_grad_lengthscales
|
bool
|
If |
True
|
requires_grad_alpha
|
bool
|
If |
True
|
device
|
device
|
If |
'cpu'
|
compile_call
|
bool
|
If |
False
|
comiple_call_kwargs
|
dict
|
When |
{}
|
Source code in qmcpy/kernel/si_dsi_kernels.py
KernelDigShiftInvarCombined
Bases: AbstractSIDSIKernel
Digitally shift invariant kernel in base \(b=2\) with combination weights \(\boldsymbol{\alpha}_1,\dots,\boldsymbol{\alpha}_d \in \mathbb{R}_{>0}^4\), smoothness \(\boldsymbol{\alpha}\), product weights \(\boldsymbol{\gamma}\), and scale \(S\):
where, \(\oplus\) is defined in the docs for KernelDigShiftInvar and so are \(\tilde{K}_p\) for \(p \in \{1,2,3,4\}\)
Examples:
>>> from qmcpy import DigitalNetB2, fwht
>>> n = 8
>>> d = 4
>>> dnb2 = DigitalNetB2(d,seed=11)
>>> x = dnb2(n,return_binary=True)
>>> x.shape
(8, 4)
>>> x.dtype
dtype('uint64')
>>> kernel = KernelDigShiftInvarCombined(
... d = d,
... t = dnb2.t,
... scale = 10,
... lengthscales = [1/j**2 for j in range(1,d+1)])
>>> k00 = kernel(x[0],x[0])
>>> k00.item()
306.66030731930863
>>> k0 = kernel(x,x[0])
>>> with np.printoptions(precision=2):
... print(k0)
[306.66 -1.65 6.88 -13.5 22.57 -9.34 7.99 -7.54]
>>> assert k0[0]==k00
>>> kmat = kernel(x[:,None,:],x[None,:,:])
>>> with np.printoptions(precision=2):
... print(kmat)
[[306.66 -1.65 6.88 -13.5 22.57 -9.34 7.99 -7.54]
[ -1.65 306.66 -13.5 6.88 -9.34 22.57 -7.54 7.99]
[ 6.88 -13.5 306.66 -1.65 7.99 -7.54 22.57 -9.34]
[-13.5 6.88 -1.65 306.66 -7.54 7.99 -9.34 22.57]
[ 22.57 -9.34 7.99 -7.54 306.66 -1.65 6.88 -13.5 ]
[ -9.34 22.57 -7.54 7.99 -1.65 306.66 -13.5 6.88]
[ 7.99 -7.54 22.57 -9.34 6.88 -13.5 306.66 -1.65]
[ -7.54 7.99 -9.34 22.57 -13.5 6.88 -1.65 306.66]]
>>> assert (kmat[:,0]==k0).all()
>>> lam = np.sqrt(n)*fwht(k0)
>>> y = np.random.Generator(np.random.PCG64(7)).uniform(low=0,high=1,size=(n))
>>> np.allclose(fwht(fwht(y)*lam),kmat@y)
True
>>> np.allclose(fwht(fwht(y)/lam),np.linalg.solve(kmat,y))
True
>>> import torch
>>> xtorch = bin_from_numpy_to_torch(x)
>>> kernel_torch = KernelDigShiftInvarCombined(
... d = d,
... t = dnb2.t,
... scale = 10,
... lengthscales = [1/j**2 for j in range(1,d+1)],
... torchify = True)
>>> kmat_torch = kernel_torch(xtorch[:,None,:],xtorch[None,:,:])
>>> np.allclose(kmat_torch.detach().numpy(),kmat)
True
>>> xf = to_float(x,dnb2.t)
>>> kmat_from_floats = kernel(xf[:,None,:],xf[None,:,:])
>>> np.allclose(kmat,kmat_from_floats)
True
>>> xftorch = to_float(xtorch,dnb2.t)
>>> xftorch.dtype
torch.float32
>>> kmat_torch_from_floats = kernel_torch(xftorch[:,None,:],xftorch[None,:,:])
>>> torch.allclose(kmat_torch_from_floats,kmat_torch)
True
>>> kernel.single_integral_01d(x)
array([10., 10., 10., 10., 10., 10., 10., 10.])
>>> kernel_torch.single_integral_01d(xtorch)
tensor([10., 10., 10., 10., 10., 10., 10., 10.], grad_fn=<AddBackward0>)
Batch Params
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelDigShiftInvarCombined(
... d = 2,
... t = 10,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,2])
>>> x = rng.uniform(low=0,high=1,size=(6,5,2))
>>> kernel(x,x).shape
(4, 3, 6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(4, 3, 6, 5, 5)
>>> kfast = kernel(x[:,None,:,None,:],x[None,:,None,:,:])
>>> kfast.shape
(4, 3, 6, 6, 5, 5)
>>> kstable = kernel(x[:,None,:,None,:],x[None,:,None,:,:],stable=True)
>>> np.abs(kfast-kstable).max()
np.float64(8.881784197001252e-16)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
d
|
int
|
Dimension. |
required |
t
|
int
|
number of bits in binary represtnations. Typically |
None
|
scale
|
Union[ndarray, Tensor]
|
Scaling factor \(S\). |
1.0
|
lengthscales
|
Union[ndarray, Tensor]
|
Product weights \((\gamma_1,\dots,\gamma_d)\). |
None
|
alpha
|
Union[ndarray, Tensor]
|
Weights \(\boldsymbol{\alpha}_1,\dots,\boldsymbol{\alpha}_d \in \mathbb{R}_{>0}^4\). |
1.0
|
shape_scale
|
list
|
Shape of |
[1]
|
shape_lengthscales
|
list
|
Shape of |
None
|
shape_alpha
|
list
|
Shape of |
None
|
tfs_scale
|
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)
|
tfs_lengthscales
|
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)
|
torchify
|
bool
|
If |
False
|
requires_grad_scale
|
bool
|
If |
True
|
requires_grad_lengthscales
|
bool
|
If |
True
|
requires_grad_alpha
|
bool
|
If |
True
|
device
|
device
|
If |
'cpu'
|
compile_call
|
bool
|
If |
False
|
comiple_call_kwargs
|
dict
|
When |
{}
|
Source code in qmcpy/kernel/si_dsi_kernels.py
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 | |
KernelGaussian
Bases: AbstractKernelGaussianSE
Gaussian / Squared Exponential kernel implemented using the product of exponentials.
Examples:
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelGaussian(d=2)
>>> x = rng.uniform(low=0,high=1,size=(4,2))
>>> kernel(x[0],x[0]).item()
1.0
>>> kernel(x,x)
array([1., 1., 1., 1.])
>>> kernel(x[:,None,:],x[None,:,:])
array([[1. , 0.78888466, 0.9483142 , 0.8228498 ],
[0.78888466, 1. , 0.72380317, 0.62226176],
[0.9483142 , 0.72380317, 1. , 0.95613874],
[0.8228498 , 0.62226176, 0.95613874, 1. ]])
Multiple randomizations
>>> x = rng.uniform(low=0,high=1,size=(6,5,2))
>>> kernel(x,x).shape
(6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(6, 5, 5)
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
(6, 6, 5, 5)
Batch hyperparameters
>>> kernel = KernelGaussian(
... d = 2,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,1])
>>> kernel(x,x).shape
(4, 3, 6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(4, 3, 6, 5, 5)
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
(4, 3, 6, 6, 5, 5)
Integrals
>>> kernel = KernelGaussian(
... d = 2,
... scale = rng.uniform(low=0,high=1,size=(3,1,)),
... lengthscales = rng.uniform(low=0,high=1,size=(1,2)))
>>> kintint = kernel.double_integral_01d()
>>> kintint
array([0.50079567, 0.11125229, 0.34760005])
>>> x_qmc_4d = DigitalNetB2(4,seed=7)(2**16)
>>> kintint_qmc = kernel(x_qmc_4d[:,:2],x_qmc_4d[:,2:]).mean(1)
>>> kintint_qmc
array([0.5007959 , 0.11125234, 0.34760021])
>>> with np.printoptions(formatter={"float":lambda x: "%.1e"%x}):
... np.abs(kintint-kintint_qmc)
array([2.3e-07, 5.1e-08, 1.6e-07])
>>> x = rng.uniform(low=0,high=1,size=(4,2))
>>> kint = kernel.single_integral_01d(x)
>>> kint
array([[0.54610372, 0.4272801 , 0.43001936, 0.44688778],
[0.12131753, 0.09492073, 0.09552926, 0.0992766 ],
[0.37904817, 0.29657323, 0.29847453, 0.31018283]])
>>> x_qmc_2d = DigitalNetB2(2,seed=7)(2**16)
>>> kint_qmc = kernel(x[:,None,:],x_qmc_2d).mean(-1)
>>> kint_qmc
array([[0.54610372, 0.4272801 , 0.43001936, 0.44688778],
[0.12131753, 0.09492073, 0.09552926, 0.0992766 ],
[0.37904817, 0.29657323, 0.29847453, 0.31018283]])
>>> with np.printoptions(formatter={"float":lambda x: "%.1e"%x}):
... np.abs(kint-kint_qmc)
array([[2.2e-13, 4.0e-13, 4.2e-12, 3.9e-12],
[4.8e-14, 8.9e-14, 9.4e-13, 8.8e-13],
[1.5e-13, 2.8e-13, 2.9e-12, 2.7e-12]])
>>> k_1l = KernelGaussian(d=2,lengthscales=[.5])
>>> k_2l = KernelGaussian(d=2,lengthscales=[.5,.5])
>>> print("%.5f"%k_2l.double_integral_01d())
0.58363
>>> print("%.5f"%k_1l.double_integral_01d())
0.58363
>>> k_1l.single_integral_01d(x)
array([0.58119655, 0.46559577, 0.57603494, 0.53494393])
>>> k_2l.single_integral_01d(x)
array([0.58119655, 0.46559577, 0.57603494, 0.53494393])
PyTorch
>>> import torch
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelGaussian(d=2,torchify=True)
>>> x = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,2)))
>>> kernel(x[0],x[0]).item()
1.0
>>> kernel(x,x)
tensor([1., 1., 1., 1.], dtype=torch.float64, grad_fn=<MulBackward0>)
>>> kernel(x[:,None,:],x[None,:,:])
tensor([[1.0000, 0.7889, 0.9483, 0.8228],
[0.7889, 1.0000, 0.7238, 0.6223],
[0.9483, 0.7238, 1.0000, 0.9561],
[0.8228, 0.6223, 0.9561, 1.0000]], dtype=torch.float64,
grad_fn=<MulBackward0>)
Multiple randomizations
>>> x = torch.from_numpy(rng.uniform(low=0,high=1,size=(6,5,2)))
>>> kernel(x,x).shape
torch.Size([6, 5])
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
torch.Size([6, 5, 5])
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
torch.Size([6, 6, 5, 5])
Batch hyperparameters
>>> kernel = KernelGaussian(
... d = 2,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,1],
... torchify = True)
>>> kernel(x,x).shape
torch.Size([4, 3, 6, 5])
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
torch.Size([4, 3, 6, 5, 5])
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
torch.Size([4, 3, 6, 6, 5, 5])
Integrals
>>> kernel = KernelGaussian(
... d = 2,
... torchify = True,
... scale = torch.from_numpy(rng.uniform(low=0,high=1,size=(3,1,))),
... lengthscales = torch.from_numpy(rng.uniform(low=0,high=1,size=(1,2))),
... requires_grad_scale = False,
... requires_grad_lengthscales = False)
>>> kintint = kernel.double_integral_01d()
>>> kintint
tensor([0.5008, 0.1113, 0.3476], dtype=torch.float64)
>>> x_qmc_4d = torch.from_numpy(DigitalNetB2(4,seed=7)(2**16))
>>> kintint_qmc = kernel(x_qmc_4d[:,:2],x_qmc_4d[:,2:]).mean(1)
>>> kintint_qmc
tensor([0.5008, 0.1113, 0.3476], dtype=torch.float64)
>>> with np.printoptions(formatter={"float":lambda x: "%.1e"%x}):
... torch.abs(kintint-kintint_qmc).numpy()
array([2.3e-07, 5.1e-08, 1.6e-07])
>>> x = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,2)))
>>> kint = kernel.single_integral_01d(x)
>>> kint
tensor([[0.5461, 0.4273, 0.4300, 0.4469],
[0.1213, 0.0949, 0.0955, 0.0993],
[0.3790, 0.2966, 0.2985, 0.3102]], dtype=torch.float64)
>>> x_qmc_2d = torch.from_numpy(DigitalNetB2(2,seed=7)(2**16))
>>> kint_qmc = kernel(x[:,None,:],x_qmc_2d).mean(-1)
>>> kint_qmc
tensor([[0.5461, 0.4273, 0.4300, 0.4469],
[0.1213, 0.0949, 0.0955, 0.0993],
[0.3790, 0.2966, 0.2985, 0.3102]], dtype=torch.float64)
>>> with np.printoptions(formatter={"float":lambda x: "%.1e"%x}):
... torch.abs(kint-kint_qmc).numpy()
array([[2.2e-13, 4.0e-13, 4.2e-12, 3.9e-12],
[4.8e-14, 8.9e-14, 9.4e-13, 8.8e-13],
[1.5e-13, 2.8e-13, 2.9e-12, 2.7e-12]])
>>> k_1l = KernelGaussian(d=2,lengthscales=[.5],torchify=True)
>>> k_2l = KernelGaussian(d=2,lengthscales=[.5,.5],torchify=True)
>>> k_2l.double_integral_01d()
tensor(0.5836, grad_fn=<MulBackward0>)
>>> k_1l.double_integral_01d()
tensor(0.5836, grad_fn=<MulBackward0>)
>>> k_1l.single_integral_01d(x)
tensor([0.5812, 0.4656, 0.5760, 0.5349], dtype=torch.float64,
grad_fn=<MulBackward0>)
>>> k_2l.single_integral_01d(x)
tensor([0.5812, 0.4656, 0.5760, 0.5349], dtype=torch.float64,
grad_fn=<MulBackward0>)
Derivatives
>>> kernel = KernelGaussian(
... d = 3,
... torchify = True,
... scale = torch.from_numpy(rng.uniform(low=0,high=1,size=(1,))),
... lengthscales = torch.from_numpy(rng.uniform(low=0,high=1,size=(3,))))
>>> x0 = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,))).requires_grad_(True)
>>> x1 = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,))).requires_grad_(True)
>>> x2 = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,))).requires_grad_(True)
>>> x = torch.stack([x0,x1,x2],axis=-1)
>>> z0 = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,))).requires_grad_(True)
>>> z1 = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,))).requires_grad_(True)
>>> z2 = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,))).requires_grad_(True)
>>> z = torch.stack([z0,z1,z2],axis=-1)
>>> c = torch.from_numpy(rng.uniform(low=0,high=1,size=(2,)))
>>> beta0 = torch.tensor([
... [1,0,0],
... [0,2,0]])
>>> beta1 = torch.tensor([
... [0,0,2],
... [2,1,0]])
>>> with torch.no_grad():
... y = kernel(x,z,beta0,beta1,c)
>>> y
tensor([ 97.6657, 3.8621, -65.9329, -1.1932], dtype=torch.float64)
>>> y_no_deriv = kernel(x,z)
>>> y_first = y_no_deriv.clone()
>>> y_first = torch.autograd.grad(y_first,x0,grad_outputs=torch.ones_like(y_first,requires_grad=True),create_graph=True)[0]
>>> y_first = torch.autograd.grad(y_first,z2,grad_outputs=torch.ones_like(y_first,requires_grad=True),create_graph=True)[0]
>>> y_first = torch.autograd.grad(y_first,z2,grad_outputs=torch.ones_like(y_first,requires_grad=True),create_graph=True)[0]
>>> y_second = y_no_deriv.clone()
>>> y_second = torch.autograd.grad(y_second,x1,grad_outputs=torch.ones_like(y_second,requires_grad=True),create_graph=True)[0]
>>> y_second = torch.autograd.grad(y_second,x1,grad_outputs=torch.ones_like(y_second,requires_grad=True),create_graph=True)[0]
>>> y_second = torch.autograd.grad(y_second,z0,grad_outputs=torch.ones_like(y_second,requires_grad=True),create_graph=True)[0]
>>> y_second = torch.autograd.grad(y_second,z0,grad_outputs=torch.ones_like(y_second,requires_grad=True),create_graph=True)[0]
>>> y_second = torch.autograd.grad(y_second,z1,grad_outputs=torch.ones_like(y_second,requires_grad=True),create_graph=True)[0]
>>> yhat = (y_first*c[0]+y_second*c[1]).detach()
>>> yhat
tensor([ 97.6657, 3.8621, -65.9329, -1.1932], dtype=torch.float64)
>>> torch.allclose(y,yhat)
True
Source code in qmcpy/kernel/abstract_kernel.py
KernelSquaredExponential
Bases: AbstractKernelGaussianSE
Gaussian / Squared Exponential kernel implemented using the pairwise distance function.
Please use KernelGaussian when using derivative information.
Examples:
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelSquaredExponential(d=2)
>>> x = rng.uniform(low=0,high=1,size=(4,2))
>>> kernel(x[0],x[0]).item()
1.0
>>> kernel(x,x)
array([1., 1., 1., 1.])
>>> kernel(x[:,None,:],x[None,:,:])
array([[1. , 0.78888466, 0.9483142 , 0.8228498 ],
[0.78888466, 1. , 0.72380317, 0.62226176],
[0.9483142 , 0.72380317, 1. , 0.95613874],
[0.8228498 , 0.62226176, 0.95613874, 1. ]])
Multiple randomizations
>>> x = rng.uniform(low=0,high=1,size=(6,5,2))
>>> kernel(x,x).shape
(6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(6, 5, 5)
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
(6, 6, 5, 5)
Batch hyperparameters
>>> kernel = KernelSquaredExponential(
... d = 2,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,1])
>>> kernel(x,x).shape
(4, 3, 6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(4, 3, 6, 5, 5)
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
(4, 3, 6, 6, 5, 5)
PyTorch
>>> import torch
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelSquaredExponential(d=2,torchify=True)
>>> x = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,2)))
>>> kernel(x[0],x[0]).item()
1.0
>>> kernel(x,x)
tensor([1., 1., 1., 1.], dtype=torch.float64, grad_fn=<MulBackward0>)
>>> kernel(x[:,None,:],x[None,:,:])
tensor([[1.0000, 0.7889, 0.9483, 0.8228],
[0.7889, 1.0000, 0.7238, 0.6223],
[0.9483, 0.7238, 1.0000, 0.9561],
[0.8228, 0.6223, 0.9561, 1.0000]], dtype=torch.float64,
grad_fn=<MulBackward0>)
Multiple randomizations
>>> x = torch.from_numpy(rng.uniform(low=0,high=1,size=(6,5,2)))
>>> kernel(x,x).shape
torch.Size([6, 5])
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
torch.Size([6, 5, 5])
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
torch.Size([6, 6, 5, 5])
Batch hyperparameters
>>> kernel = KernelSquaredExponential(
... d = 2,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,1],
... torchify = True)
>>> kernel(x,x).shape
torch.Size([4, 3, 6, 5])
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
torch.Size([4, 3, 6, 5, 5])
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
torch.Size([4, 3, 6, 6, 5, 5])
Source code in qmcpy/kernel/abstract_kernel.py
KernelRationalQuadratic
Bases: AbstractKernelScaleLengthscales
Rational Quadratic kernel
Examples:
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelRationalQuadratic(d=2)
>>> x = rng.uniform(low=0,high=1,size=(4,2))
>>> kernel(x[0],x[0]).item()
1.0
>>> kernel(x,x)
array([1., 1., 1., 1.])
>>> kernel(x[:,None,:],x[None,:,:])
array([[1. , 0.80831912, 0.94960504, 0.83683297],
[0.80831912, 1. , 0.75572321, 0.67824456],
[0.94960504, 0.75572321, 1. , 0.95707312],
[0.83683297, 0.67824456, 0.95707312, 1. ]])
Multiple randomizations
>>> x = rng.uniform(low=0,high=1,size=(6,5,2))
>>> kernel(x,x).shape
(6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(6, 5, 5)
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
(6, 6, 5, 5)
Batch hyperparameters
>>> kernel = KernelRationalQuadratic(
... d = 2,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,1])
>>> kernel(x,x).shape
(4, 3, 6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(4, 3, 6, 5, 5)
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
(4, 3, 6, 6, 5, 5)
PyTorch
>>> import torch
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelRationalQuadratic(d=2,torchify=True)
>>> x = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,2)))
>>> kernel(x[0],x[0]).item()
1.0
>>> kernel(x,x)
tensor([1., 1., 1., 1.], dtype=torch.float64, grad_fn=<MulBackward0>)
>>> kernel(x[:,None,:],x[None,:,:])
tensor([[1.0000, 0.8083, 0.9496, 0.8368],
[0.8083, 1.0000, 0.7557, 0.6782],
[0.9496, 0.7557, 1.0000, 0.9571],
[0.8368, 0.6782, 0.9571, 1.0000]], dtype=torch.float64,
grad_fn=<MulBackward0>)
Multiple randomizations
>>> x = torch.from_numpy(rng.uniform(low=0,high=1,size=(6,5,2)))
>>> kernel(x,x).shape
torch.Size([6, 5])
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
torch.Size([6, 5, 5])
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
torch.Size([6, 6, 5, 5])
Batch hyperparameters
>>> kernel = KernelRationalQuadratic(
... d = 2,
... shape_alpha = [4,3,1],
... shape_lengthscales = [3,1],
... torchify = True)
>>> kernel(x,x).shape
torch.Size([4, 3, 6, 5])
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
torch.Size([4, 3, 6, 5, 5])
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
torch.Size([4, 3, 6, 6, 5, 5])
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
d
|
int
|
Dimension. |
required |
scale
|
Union[ndarray, Tensor]
|
Scaling factor \(S\). |
1.0
|
lengthscales
|
Union[ndarray, Tensor]
|
Lengthscales \(\boldsymbol{\gamma}\). |
1.0
|
alpha
|
Union[ndarray, Tensor]
|
Scale mixture parameter \(\alpha\). |
1.0
|
shape_scale
|
list
|
Shape of |
[1]
|
shape_lengthscales
|
list
|
Shape of |
None
|
shape_alpha
|
list
|
Shape of |
[1]
|
tfs_scale
|
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)
|
tfs_lengthscales
|
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)
|
tfs_alpha
|
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)
|
torchify
|
bool
|
If |
False
|
requires_grad_scale
|
bool
|
If |
True
|
requires_grad_lengthscales
|
bool
|
If |
True
|
requires_grad_alpha
|
bool
|
If |
True
|
device
|
device
|
If |
'cpu'
|
compile_call
|
bool
|
If |
False
|
comiple_call_kwargs
|
dict
|
When |
{}
|
Source code in qmcpy/kernel/common_kernels.py
KernelMatern12
Bases: AbstractKernelScaleLengthscales
Matern kernel with \(\alpha=1/2\).
Examples:
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelMatern12(d=2)
>>> x = rng.uniform(low=0,high=1,size=(4,2))
>>> kernel(x[0],x[0]).item()
1.0
>>> kernel(x,x)
array([1., 1., 1., 1.])
>>> kernel(x[:,None,:],x[None,:,:])
array([[1. , 0.61448839, 0.79424131, 0.64302787],
[0.61448839, 1. , 0.56635268, 0.50219691],
[0.79424131, 0.56635268, 1. , 0.80913986],
[0.64302787, 0.50219691, 0.80913986, 1. ]])
Multiple randomizations
>>> x = rng.uniform(low=0,high=1,size=(6,5,2))
>>> kernel(x,x).shape
(6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(6, 5, 5)
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
(6, 6, 5, 5)
Batch hyperparameters
>>> kernel = KernelMatern12(
... d = 2,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,1])
>>> kernel(x,x).shape
(4, 3, 6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(4, 3, 6, 5, 5)
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
(4, 3, 6, 6, 5, 5)
PyTorch
>>> import torch
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelMatern12(d=2,torchify=True)
>>> x = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,2)))
>>> kernel(x[0],x[0]).item()
1.0
>>> kernel(x,x)
tensor([1., 1., 1., 1.], dtype=torch.float64, grad_fn=<MulBackward0>)
>>> kernel(x[:,None,:],x[None,:,:])
tensor([[1.0000, 0.6145, 0.7942, 0.6430],
[0.6145, 1.0000, 0.5664, 0.5022],
[0.7942, 0.5664, 1.0000, 0.8091],
[0.6430, 0.5022, 0.8091, 1.0000]], dtype=torch.float64,
grad_fn=<MulBackward0>)
Multiple randomizations
>>> x = torch.from_numpy(rng.uniform(low=0,high=1,size=(6,5,2)))
>>> kernel(x,x).shape
torch.Size([6, 5])
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
torch.Size([6, 5, 5])
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
torch.Size([6, 6, 5, 5])
Batch hyperparameters
>>> kernel = KernelMatern12(
... d = 2,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,1],
... torchify = True)
>>> kernel(x,x).shape
torch.Size([4, 3, 6, 5])
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
torch.Size([4, 3, 6, 5, 5])
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
torch.Size([4, 3, 6, 6, 5, 5])
Source code in qmcpy/kernel/abstract_kernel.py
KernelMatern32
Bases: AbstractKernelScaleLengthscales
Matern kernel with \(\alpha=3/2\).
Examples:
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelMatern32(d=2)
>>> x = rng.uniform(low=0,high=1,size=(4,2))
>>> kernel(x[0],x[0]).item()
1.0
>>> kernel(x,x)
array([1., 1., 1., 1.])
>>> kernel(x[:,None,:],x[None,:,:])
array([[1. , 0.79309639, 0.93871358, 0.82137958],
[0.79309639, 1. , 0.74137353, 0.66516872],
[0.93871358, 0.74137353, 1. , 0.9471166 ],
[0.82137958, 0.66516872, 0.9471166 , 1. ]])
Multiple randomizations
>>> x = rng.uniform(low=0,high=1,size=(6,5,2))
>>> kernel(x,x).shape
(6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(6, 5, 5)
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
(6, 6, 5, 5)
Batch hyperparameters
>>> kernel = KernelMatern32(
... d = 2,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,1])
>>> kernel(x,x).shape
(4, 3, 6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(4, 3, 6, 5, 5)
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
(4, 3, 6, 6, 5, 5)
PyTorch
>>> import torch
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelMatern32(d=2,torchify=True)
>>> x = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,2)))
>>> kernel(x[0],x[0]).item()
1.0
>>> kernel(x,x)
tensor([1., 1., 1., 1.], dtype=torch.float64, grad_fn=<MulBackward0>)
>>> kernel(x[:,None,:],x[None,:,:])
tensor([[1.0000, 0.7931, 0.9387, 0.8214],
[0.7931, 1.0000, 0.7414, 0.6652],
[0.9387, 0.7414, 1.0000, 0.9471],
[0.8214, 0.6652, 0.9471, 1.0000]], dtype=torch.float64,
grad_fn=<MulBackward0>)
Multiple randomizations
>>> x = torch.from_numpy(rng.uniform(low=0,high=1,size=(6,5,2)))
>>> kernel(x,x).shape
torch.Size([6, 5])
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
torch.Size([6, 5, 5])
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
torch.Size([6, 6, 5, 5])
Batch hyperparameters
>>> kernel = KernelMatern32(
... d = 2,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,1],
... torchify = True)
>>> kernel(x,x).shape
torch.Size([4, 3, 6, 5])
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
torch.Size([4, 3, 6, 5, 5])
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
torch.Size([4, 3, 6, 6, 5, 5])
Source code in qmcpy/kernel/abstract_kernel.py
KernelMatern52
Bases: AbstractKernelScaleLengthscales
Matern kernel with \(\alpha=5/2\).
Examples:
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelMatern52(d=2)
>>> x = rng.uniform(low=0,high=1,size=(4,2))
>>> kernel(x[0],x[0]).item()
1.0
>>> kernel(x,x)
array([1., 1., 1., 1.])
>>> kernel(x[:,None,:],x[None,:,:])
array([[1. , 0.83612941, 0.95801903, 0.861472 ],
[0.83612941, 1. , 0.78812397, 0.71396963],
[0.95801903, 0.78812397, 1. , 0.96425994],
[0.861472 , 0.71396963, 0.96425994, 1. ]])
Multiple randomizations
>>> x = rng.uniform(low=0,high=1,size=(6,5,2))
>>> kernel(x,x).shape
(6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(6, 5, 5)
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
(6, 6, 5, 5)
Batch hyperparameters
>>> kernel = KernelMatern52(
... d = 2,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,1])
>>> kernel(x,x).shape
(4, 3, 6, 5)
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
(4, 3, 6, 5, 5)
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
(4, 3, 6, 6, 5, 5)
PyTorch
>>> import torch
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kernel = KernelMatern52(d=2,torchify=True)
>>> x = torch.from_numpy(rng.uniform(low=0,high=1,size=(4,2)))
>>> kernel(x[0],x[0]).item()
1.0
>>> kernel(x,x)
tensor([1., 1., 1., 1.], dtype=torch.float64, grad_fn=<MulBackward0>)
>>> kernel(x[:,None,:],x[None,:,:])
tensor([[1.0000, 0.8361, 0.9580, 0.8615],
[0.8361, 1.0000, 0.7881, 0.7140],
[0.9580, 0.7881, 1.0000, 0.9643],
[0.8615, 0.7140, 0.9643, 1.0000]], dtype=torch.float64,
grad_fn=<MulBackward0>)
Multiple randomizations
>>> x = torch.from_numpy(rng.uniform(low=0,high=1,size=(6,5,2)))
>>> kernel(x,x).shape
torch.Size([6, 5])
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
torch.Size([6, 5, 5])
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
torch.Size([6, 6, 5, 5])
Batch hyperparameters
>>> kernel = KernelMatern52(
... d = 2,
... shape_scale = [4,3,1],
... shape_lengthscales = [3,1],
... torchify = True)
>>> kernel(x,x).shape
torch.Size([4, 3, 6, 5])
>>> kernel(x[:,:,None,:],x[:,None,:,:]).shape
torch.Size([4, 3, 6, 5, 5])
>>> kernel(x[:,None,:,None,:],x[None,:,None,:,:]).shape
torch.Size([4, 3, 6, 6, 5, 5])
Source code in qmcpy/kernel/abstract_kernel.py
KernelMultiTask
Bases: AbstractKernel
Multi-task kernel
parameterized for \(T\) tasks by a factor \(\mathsf{F} \in \mathbb{R}^{T \times r}\) and a diagonal \(\boldsymbol{v} \in \mathbb{R}^T\) so that
Examples:
>>> kmt = KernelMultiTask(KernelGaussian(d=2),num_tasks=3,diag=[1,2,3])
>>> x = np.random.rand(4,2)
>>> task = np.arange(3)
>>> kmt(task[1],task[1],x[0],x[0]).item()
3.0
>>> kmt(task,task,x[0],x[0])
array([2., 3., 4.])
>>> kmt(task[:,None],task[None,:],x[0],x[0]).shape
(3, 3)
>>> kmt(task[1],task[1],x,x,)
array([3., 3., 3., 3.])
>>> kmt(task,task,x[:3],x[:3])
array([2., 3., 4.])
>>> kmt(task[:,None],task[:,None],x,x).shape
(3, 4)
>>> v = kmt(task,task,x[:3,None,:],x[None,:3,:])
>>> v.shape
(3, 3)
>>> np.allclose(v,kmt.base_kernel(x[:3,None,:],x[None,:3,:])*kmt.taskmat[task,task])
True
>>> kmt(task[:,None,None],task[:,None,None],x[:,None,:],x[None,:,:]).shape
(3, 4, 4)
>>> kmt(task[:,None,None,None],task[None,:,None,None],x[:,None,:],x[None,:,:]).shape
(3, 3, 4, 4)
Batched inference
>>> kernel_base = KernelGaussian(d=10,shape_lengthscales=(5,1),shape_scale=(3,5,1))
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kmt = KernelMultiTask(kernel_base,
... num_tasks=4,
... shape_factor=(6,3,5,4,2),
... diag = rng.uniform(low=0,high=1,size=(3,5,4)))
>>> x = np.random.rand(8,10)
>>> task = np.arange(4)
>>> kmt(task[0],task[0],x[0],x[0]).shape
(6, 3, 5)
>>> kmt(task,task,x[0],x[0]).shape
(6, 3, 5, 4)
>>> kmt(task[0],task[0],x,x).shape
(6, 3, 5, 8)
>>> v = kmt(task,task,x[:4,None,:],x[None,:4,:])
>>> v.shape
(6, 3, 5, 4, 4)
>>> kmat_x = kmt.base_kernel(x[:4,None,:],x[None,:4,:])
>>> kmat_x.shape
(3, 5, 4, 4)
>>> kmat_tasks = kmt.taskmat[...,task,task]
>>> kmat_tasks.shape
(6, 3, 5, 4)
>>> np.allclose(v,kmat_tasks[...,None,:]*kmat_x)
True
>>> np.allclose(v,kmat_tasks[...,:,None]*kmat_x)
False
>>> kmt(task[:,None,None,None],task[None,:,None,None],x[:,None,:],x[None,:,:]).shape
(6, 3, 5, 4, 4, 8, 8)
>>> kmt(task[:,None],task[None,:],x[:,None,None,None,:],x[None,:,None,None,:]).shape
(6, 3, 5, 8, 8, 4, 4)
Integrals
>>> kernel = KernelGaussian(
... d = 2,
... scale = rng.uniform(low=0,high=1,size=(3,1)),
... lengthscales = rng.uniform(low=0,high=1,size=(1,2)))
>>> kmt = KernelMultiTask(
... base_kernel=kernel,
... num_tasks=5,
... diag = rng.uniform(low=0,high=1,size=(6,3,5)),
... factor = rng.uniform(low=0,high=1,size=(3,5,2)))
>>> task = np.arange(5)
>>> kmt.double_integral_01d(task0=task[0],task1=task[1]).shape
(6, 3)
>>> kmt.double_integral_01d(task0=task,task1=task).shape
(6, 3, 5)
>>> kmt.double_integral_01d(task0=task[:,None],task1=task[None,:]).shape
(6, 3, 5, 5)
>>> x = rng.uniform(low=0,high=1,size=(7,4,2))
>>> kmt.single_integral_01d(task0=task[0],task1=task[1],x=x).shape
(6, 3, 7, 4)
>>> kmt.single_integral_01d(task0=task[:,None,None],task1=task[:,None,None],x=x).shape
(6, 3, 5, 7, 4)
>>> kmt.single_integral_01d(task0=task[:,None,None,None],task1=task[None,:,None,None],x=x).shape
(6, 3, 5, 5, 7, 4)
Cholesky Construction
>>> kmt = KernelMultiTask(
... KernelGaussian(5),
... num_tasks = 3,
... method = "CHOLESKY",
... factor = 2,
... diag = 1.5,
... )
>>> kmt.taskmat
array([[ 2.25, 3. , 3. ],
[ 3. , 6.25, 7. ],
[ 3. , 7. , 10.25]])
>>> kmt = KernelMultiTask(
... KernelGaussian(5),
... num_tasks = 3,
... method = "CHOLESKY",
... factor = 2,
... diag = 1.5,
... shape_factor = [2,3*(1+3)//2-3],
... shape_diag = [3],
... )
>>> kmt.taskmat
array([[[ 2.25, 3. , 3. ],
[ 3. , 6.25, 7. ],
[ 3. , 7. , 10.25]],
[[ 2.25, 3. , 3. ],
[ 3. , 6.25, 7. ],
[ 3. , 7. , 10.25]]])
>>> kmt = KernelMultiTask(
... KernelGaussian(5),
... num_tasks = 3,
... method = "CHOLESKY",
... factor = 2,
... diag = 1.5,
... shape_factor = [3*(1+3)//2-3],
... shape_diag = [2,3],
... )
>>> kmt.taskmat
array([[[ 2.25, 3. , 3. ],
[ 3. , 6.25, 7. ],
[ 3. , 7. , 10.25]],
[[ 2.25, 3. , 3. ],
[ 3. , 6.25, 7. ],
[ 3. , 7. , 10.25]]])
>>> kmt = KernelMultiTask(
... KernelGaussian(5),
... num_tasks = 3,
... method = "CHOLESKY",
... factor = 2,
... diag = 1.5,
... shape_factor = [2,3*(1+3)//2-3],
... shape_diag = [2,3],
... )
>>> kmt.taskmat
array([[[ 2.25, 3. , 3. ],
[ 3. , 6.25, 7. ],
[ 3. , 7. , 10.25]],
[[ 2.25, 3. , 3. ],
[ 3. , 6.25, 7. ],
[ 3. , 7. , 10.25]]])
PyTorch
>>> import torch
>>> kmt = KernelMultiTask(KernelGaussian(d=2,torchify=True),num_tasks=3,diag=[1,2,3])
>>> x = torch.from_numpy(np.random.rand(4,2))
>>> task = np.arange(3)
>>> kmt(task[1],task[1],x[0],x[0]).item()
3.0
>>> kmt(task,task,x[0],x[0])
tensor([2., 3., 4.], dtype=torch.float64, grad_fn=<SelectBackward0>)
>>> kmt(task[:,None],task[None,:],x[0],x[0]).shape
torch.Size([3, 3])
>>> kmt(task[1],task[1],x,x)
tensor([3., 3., 3., 3.], dtype=torch.float64, grad_fn=<SelectBackward0>)
>>> kmt(task,task,x[:3],x[:3])
tensor([2., 3., 4.], dtype=torch.float64, grad_fn=<SelectBackward0>)
>>> kmt(task[:,None],task[:,None],x,x).shape
torch.Size([3, 4])
>>> v = kmt(task,task,x[:3,None,:],x[None,:3,:])
>>> v.shape
torch.Size([3, 3])
>>> torch.allclose(v,kmt.base_kernel(x[:3,None,:],x[None,:3,:])*kmt.taskmat[task,task])
True
>>> kmt(task[:,None,None],task[:,None,None],x[:,None,:],x[None,:,:]).shape
torch.Size([3, 4, 4])
>>> kmt(task[:,None,None,None],task[None,:,None,None],x[:,None,:],x[None,:,:]).shape
torch.Size([3, 3, 4, 4])
Batched inference
>>> kernel_base = KernelGaussian(d=10,shape_lengthscales=(5,1),shape_scale=(3,5,1),torchify=True)
>>> rng = np.random.Generator(np.random.PCG64(7))
>>> kmt = KernelMultiTask(kernel_base,
... num_tasks=4,
... shape_factor=(6,3,5,4,2),
... diag = rng.uniform(low=0,high=1,size=(3,5,4)))
>>> x = torch.from_numpy(np.random.rand(8,10))
>>> task = torch.arange(4)
>>> kmt(task[0],task[0],x[0],x[0]).shape
torch.Size([6, 3, 5])
>>> kmt(task,task,x[0],x[0]).shape
torch.Size([6, 3, 5, 4])
>>> kmt(task[0],task[0],x,x).shape
torch.Size([6, 3, 5, 8])
>>> v = kmt(task,task,x[:4,None,:],x[None,:4,:])
>>> v.shape
torch.Size([6, 3, 5, 4, 4])
>>> kmat_x = kmt.base_kernel(x[:4,None,:],x[None,:4,:])
>>> kmat_x.shape
torch.Size([3, 5, 4, 4])
>>> kmat_tasks = kmt.taskmat[...,task,task]
>>> kmat_tasks.shape
torch.Size([6, 3, 5, 4])
>>> torch.allclose(v,kmat_tasks[...,None,:]*kmat_x)
True
>>> torch.allclose(v,kmat_tasks[...,:,None]*kmat_x)
False
>>> kmt(task[:,None,None,None],task[None,:,None,None],x[:,None,:],x[None,:,:]).shape
torch.Size([6, 3, 5, 4, 4, 8, 8])
>>> kmt(task[:,None],task[None,:],x[:,None,None,None,:],x[None,:,None,None,:]).shape
torch.Size([6, 3, 5, 8, 8, 4, 4])
>>> kmt.factor.dtype
torch.float32
>>> kmt.diag.dtype
torch.float64
Integrals
>>> kernel = KernelGaussian(
... d = 2,
... torchify = True,
... scale = rng.uniform(low=0,high=1,size=(3,1)),
... lengthscales = rng.uniform(low=0,high=1,size=(1,2)))
>>> kmt = KernelMultiTask(
... base_kernel=kernel,
... num_tasks=5,
... diag = rng.uniform(low=0,high=1,size=(6,3,5)),
... factor = rng.uniform(low=0,high=1,size=(3,5,2)))
>>> task = torch.arange(5)
>>> kmt.double_integral_01d(task0=task[0],task1=task[1]).shape
torch.Size([6, 3])
>>> kmt.double_integral_01d(task0=task,task1=task).shape
torch.Size([6, 3, 5])
>>> kmt.double_integral_01d(task0=task[:,None],task1=task[None,:]).shape
torch.Size([6, 3, 5, 5])
>>> x = torch.from_numpy(rng.uniform(low=0,high=1,size=(7,4,2)))
>>> kmt.single_integral_01d(task0=task[0],task1=task[1],x=x).shape
torch.Size([6, 3, 7, 4])
>>> kmt.single_integral_01d(task0=task[:,None,None],task1=task[:,None,None],x=x).shape
torch.Size([6, 3, 5, 7, 4])
>>> kmt.single_integral_01d(task0=task[:,None,None,None],task1=task[None,:,None,None],x=x).shape
torch.Size([6, 3, 5, 5, 7, 4])
Cholesky Construction
>>> kmt = KernelMultiTask(
... KernelGaussian(5,torchify=True),
... num_tasks = 3,
... method = "CHOLESKY",
... factor = 2,
... diag = 1.5,
... )
>>> kmt.taskmat
tensor([[ 2.2500, 3.0000, 3.0000],
[ 3.0000, 6.2500, 7.0000],
[ 3.0000, 7.0000, 10.2500]], grad_fn=<ViewBackward0>)
>>> kmt = KernelMultiTask(
... KernelGaussian(5,torchify=True),
... num_tasks = 3,
... method = "CHOLESKY",
... factor = 2,
... diag = 1.5,
... shape_factor = [2,3*(1+3)//2-3],
... shape_diag = [3],
... )
>>> kmt.taskmat
tensor([[[ 2.2500, 3.0000, 3.0000],
[ 3.0000, 6.2500, 7.0000],
[ 3.0000, 7.0000, 10.2500]],
[[ 2.2500, 3.0000, 3.0000],
[ 3.0000, 6.2500, 7.0000],
[ 3.0000, 7.0000, 10.2500]]], grad_fn=<ViewBackward0>)
>>> kmt = KernelMultiTask(
... KernelGaussian(5,torchify=True),
... num_tasks = 3,
... method = "CHOLESKY",
... factor = 2,
... diag = 1.5,
... shape_factor = [3*(1+3)//2-3],
... shape_diag = [2,3],
... )
>>> kmt.taskmat
tensor([[[ 2.2500, 3.0000, 3.0000],
[ 3.0000, 6.2500, 7.0000],
[ 3.0000, 7.0000, 10.2500]],
[[ 2.2500, 3.0000, 3.0000],
[ 3.0000, 6.2500, 7.0000],
[ 3.0000, 7.0000, 10.2500]]], grad_fn=<ViewBackward0>)
>>> kmt = KernelMultiTask(
... KernelGaussian(5,torchify=True),
... num_tasks = 3,
... method = "CHOLESKY",
... factor = 2,
... diag = 1.5,
... shape_factor = [2,3*(1+3)//2-3],
... shape_diag = [2,3],
... )
>>> kmt.taskmat
tensor([[[ 2.2500, 3.0000, 3.0000],
[ 3.0000, 6.2500, 7.0000],
[ 3.0000, 7.0000, 10.2500]],
[[ 2.2500, 3.0000, 3.0000],
[ 3.0000, 6.2500, 7.0000],
[ 3.0000, 7.0000, 10.2500]]], grad_fn=<ViewBackward0>)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_kernel
|
AbstractKernel
|
\(K_{\mathrm{base}}\). |
required |
num_tasks
|
int
|
Number of tasks \(T>1\). |
required |
factor
|
Union[ndarray, Tensor]
|
Factor \(\mathsf{F}\). |
1.0
|
diag
|
Union[ndarray, Tensor]
|
Diagonal parameter \(\boldsymbol{v}\). |
1.0
|
shape_factor
|
list
|
Shape of |
None
|
shape_diag
|
list
|
Shape of |
None
|
tfs_factor
|
Tuple[callable, callable]
|
The first argument transforms to the raw value to be optimized; the second applies the inverse transform. |
(tf_identity, tf_identity)
|
tfs_diag
|
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_factor
|
bool
|
If |
True
|
requires_grad_diag
|
bool
|
If |
True
|
method
|
str
|
|
'LOW RANK'
|
Source code in qmcpy/kernel/multitask_kernel.py
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 | |
__call__
Evaluate the kernel with (optional) partial derivatives
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task0
|
Union[int, ndarray, Tensor]
|
First task indices \(i_0\). |
required |
task1
|
Union[int, ndarray, Tensor]
|
Second task indices \(i_1\). |
required |
x0
|
Union[ndarray, Tensor]
|
Shape |
required |
x1
|
Union[ndarray, Tensor]
|
Shape |
required |
beta0
|
Union[ndarray, Tensor]
|
Shape |
None
|
beta1
|
Union[ndarray, Tensor]
|
Shape |
None
|
c
|
Union[ndarray, Tensor]
|
Shape |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
k |
Union[ndarray, Tensor]
|
Kernel evaluations with batched shape, see the doctests for examples. |
Source code in qmcpy/kernel/multitask_kernel.py
single_integral_01d
Evaluate the integral of the kernel over the unit cube
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task0
|
Union[int, ndarray, Tensor]
|
First task indices \(i_0\). |
required |
task1
|
Union[int, ndarray, Tensor]
|
Second task indices \(i_1\). |
required |
x
|
Union[ndarray, Tensor]
|
Shape |
required |
Returns:
| Name | Type | Description |
|---|---|---|
tildek |
Union[ndarray, Tensor]
|
Shape |
Source code in qmcpy/kernel/multitask_kernel.py
double_integral_01d
Evaluate the integral of the kernel over the unit cube
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task0
|
Union[int, ndarray, Tensor]
|
First task indices \(i_0\). |
required |
task1
|
Union[int, ndarray, Tensor]
|
Second task indices \(i_1\). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
tildek |
Union[ndarray, Tensor]
|
Double integral kernel evaluations. |