0
# GP Arithmetic and Transformations
1
2
Mathematical operations for combining and transforming Gaussian processes. This includes arithmetic operations like addition and multiplication, input transformations such as shifting and stretching, differentiation, and dimension selection for multi-dimensional inputs.
3
4
## Capabilities
5
6
### GP Arithmetic Operations
7
8
Combine Gaussian processes using arithmetic operations. Addition creates independent sums while multiplication can represent products of functions or scaling operations.
9
10
```python { .api }
11
class GP:
12
def __add__(self, other):
13
"""
14
Add GP with another GP, function, or scalar.
15
16
Parameters:
17
- other: GP, function, or numeric value
18
19
Returns:
20
- GP: Sum of the processes
21
"""
22
23
def __mul__(self, other):
24
"""
25
Multiply GP by another GP, function, or scalar.
26
27
Parameters:
28
- other: GP, function, or numeric value
29
30
Returns:
31
- GP: Product/scaled process
32
"""
33
34
def __radd__(self, other):
35
"""Right addition (other + self)."""
36
37
def __rmul__(self, other):
38
"""Right multiplication (other * self)."""
39
40
def __neg__(self):
41
"""Negation (-self)."""
42
43
def __sub__(self, other):
44
"""Subtraction (self - other)."""
45
46
def __rsub__(self, other):
47
"""Right subtraction (other - self)."""
48
```
49
50
### Input Transformations
51
52
Transform the input space of Gaussian processes through shifting, stretching, or arbitrary transformations. These operations modify how the GP responds to input coordinates.
53
54
```python { .api }
55
class GP:
56
def shift(self, shift):
57
"""
58
Shift GP inputs by constant offset.
59
60
Parameters:
61
- shift: Shift amount (scalar or vector)
62
63
Returns:
64
- GP: Shifted process
65
"""
66
67
def stretch(self, stretch):
68
"""
69
Stretch GP inputs by scaling factor.
70
71
Parameters:
72
- stretch: Stretch factor (scalar or vector)
73
74
Returns:
75
- GP: Stretched process
76
"""
77
78
def transform(self, f):
79
"""
80
Apply arbitrary transformation to GP inputs.
81
82
Parameters:
83
- f: Transformation function
84
85
Returns:
86
- GP: Transformed process
87
"""
88
```
89
90
### Dimension Selection
91
92
Select specific dimensions from multi-dimensional input spaces, enabling creation of lower-dimensional views of higher-dimensional processes.
93
94
```python { .api }
95
class GP:
96
def select(self, *dims):
97
"""
98
Select input dimensions from multi-dimensional GP.
99
100
Parameters:
101
- *dims: Dimension indices to select
102
103
Returns:
104
- GP: Process with selected dimensions
105
"""
106
```
107
108
### Differentiation
109
110
Compute derivatives of Gaussian processes either analytically (when supported by the kernel) or through finite difference approximations.
111
112
```python { .api }
113
class GP:
114
def diff(self, dim=0):
115
"""
116
Differentiate GP with respect to specified dimension.
117
118
Parameters:
119
- dim: Dimension to differentiate along (default: 0)
120
121
Returns:
122
- GP: Differentiated process
123
"""
124
125
def diff_approx(self, deriv=1, order=6):
126
"""
127
Approximate derivative using finite differences.
128
129
Parameters:
130
- deriv: Derivative order (default: 1)
131
- order: Finite difference order (default: 6)
132
133
Returns:
134
- GP: Approximately differentiated process
135
"""
136
```
137
138
### Cross Products
139
140
Create Cartesian products of multiple Gaussian processes, useful for multi-output modeling and vector-valued processes.
141
142
```python { .api }
143
def cross(*ps) -> GP:
144
"""
145
Construct Cartesian product of processes.
146
147
Parameters:
148
- *ps: Gaussian processes to combine
149
150
Returns:
151
- GP: Cross product process
152
"""
153
```
154
155
## Usage Examples
156
157
### Basic Arithmetic Operations
158
159
```python
160
import stheno
161
import numpy as np
162
163
# Create base processes
164
gp1 = stheno.GP(kernel=stheno.EQ())
165
gp2 = stheno.GP(kernel=stheno.Matern52())
166
167
# Addition
168
sum_gp = gp1 + gp2
169
sum_gp = gp1 + np.sin # Add a function
170
sum_gp = gp1 + 2.5 # Add a constant
171
172
# Multiplication
173
scaled_gp = 2.0 * gp1 # Scale by constant
174
product_gp = gp1 * gp2 # Product of processes
175
modulated_gp = gp1 * np.cos # Modulate by function
176
177
# Other operations
178
neg_gp = -gp1 # Negation
179
diff_gp = gp1 - gp2 # Subtraction
180
```
181
182
### Input Transformations
183
184
```python
185
# Create base GP
186
gp = stheno.GP(kernel=stheno.EQ())
187
188
# Shift inputs
189
shifted_gp = gp.shift(1.0) # Shift by constant
190
shifted_gp = gp.shift([1.0, 2.0]) # Shift each dimension
191
192
# Stretch inputs
193
stretched_gp = gp.stretch(2.0) # Stretch by factor
194
stretched_gp = gp.stretch([2.0, 0.5]) # Different stretch per dimension
195
196
# Custom transformation
197
def custom_transform(x):
198
return x**2 # Square the inputs
199
200
transformed_gp = gp.transform(custom_transform)
201
202
# Combined transformations
203
complex_gp = gp.shift(1.0).stretch(2.0).transform(np.log)
204
```
205
206
### Dimension Selection
207
208
```python
209
# Create 3D GP
210
gp_3d = stheno.GP(kernel=stheno.EQ())
211
212
# Select specific dimensions
213
gp_x = gp_3d.select(0) # Only x dimension
214
gp_xy = gp_3d.select(0, 1) # x and y dimensions
215
gp_xz = gp_3d.select(0, 2) # x and z dimensions
216
217
# Use for evaluation
218
x_3d = np.random.randn(50, 3) # 3D inputs
219
x_2d = x_3d[:, [0, 1]] # 2D projection
220
221
fdd_3d = gp_3d(x_3d)
222
fdd_2d = gp_xy(x_2d) # Equivalent to gp_3d.select(0,1)(x_2d)
223
```
224
225
### Differentiation
226
227
```python
228
# Create smooth GP
229
gp = stheno.GP(kernel=stheno.EQ())
230
231
# Analytical differentiation
232
dgp_dx = gp.diff(dim=0) # First derivative w.r.t. dimension 0
233
234
# Second derivative
235
d2gp_dx2 = gp.diff(dim=0).diff(dim=0)
236
237
# Mixed partial derivatives (for multi-dimensional inputs)
238
gp_2d = stheno.GP(kernel=stheno.EQ())
239
dgp_dx = gp_2d.diff(dim=0) # ∂f/∂x
240
dgp_dy = gp_2d.diff(dim=1) # ∂f/∂y
241
d2gp_dxdy = gp_2d.diff(dim=0).diff(dim=1) # ∂²f/∂x∂y
242
243
# Approximate differentiation
244
approx_deriv = gp.diff_approx(deriv=1, order=6) # First derivative
245
approx_deriv2 = gp.diff_approx(deriv=2, order=8) # Second derivative
246
```
247
248
### Cross Products for Multi-Output GPs
249
250
```python
251
# Create individual processes
252
temp_gp = stheno.GP(kernel=stheno.EQ(), name="temperature")
253
pressure_gp = stheno.GP(kernel=stheno.Matern52(), name="pressure")
254
humidity_gp = stheno.GP(kernel=stheno.Linear(), name="humidity")
255
256
# Create multi-output process
257
multi_output_gp = stheno.cross(temp_gp, pressure_gp, humidity_gp)
258
259
# Evaluate at same input points
260
x = np.linspace(0, 10, 100)
261
multi_fdd = multi_output_gp(x)
262
263
# Sample from multi-output process
264
samples = multi_fdd.sample() # Shape: (300, 1) for 3 outputs × 100 points
265
```
266
267
### Complex Compositions
268
269
```python
270
# Build complex GP through composition
271
base_gp = stheno.GP(kernel=stheno.EQ())
272
273
# Create trend + seasonal + noise model
274
trend = stheno.GP(kernel=stheno.Linear()).stretch(10.0)
275
seasonal = (stheno.GP(kernel=stheno.EQ()) * np.sin).stretch(0.5)
276
noise = 0.1 * stheno.GP(kernel=stheno.Delta())
277
278
complex_model = trend + seasonal + noise
279
280
# Transform for non-stationary behavior
281
nonstationary = base_gp.transform(lambda x: x**0.5).stretch(2.0).shift(1.0)
282
```