MOOGP - Multi-Output Orthogonal Gaussian Process
moogp emulates vector-valued (multi-output) functions with a multi-output
orthogonal Gaussian process. It models the p outputs as a linear combination
of q shared latent GPs, plus a regression trend g(x) that the latent
kernels are orthogonalized against. Fitting the trend separately keeps its
coefficients interpretable and improves extrapolation.
Table of Contents
Installation
moogp is on PyPI and requires Python 3.11 or above:
pip install moogp
Its only runtime dependencies are numpy, scipy, and autograd.
Test suite
A set of tests is provided to verify that moogp is installed correctly:
$ python
>>> import moogp
>>> moogp.__version__
<version string>
>>> moogp.test()
Or run pytest directly:
pytest src/moogp/tests
Basic Usage
import numpy as np
from moogp.model import MOOGP
from moogp import evaluation # optional evaluation module
# Generate fifty 2-dimensional inputs and 4-dimensional outputs.
x = np.random.randn(50, 2)
y = np.random.randn(50, 4)
data = {"X": x, "Y": y}
# Trend g(x) = [1, x1, x2] (intercept + linear effects), with 3 latent GPs.
model = MOOGP(terms=[None, 1, 2], q=3)
model.fit(data)
# Prediction: mean and standard deviation on the original output scale.
mean, std = model.predict(x, return_std=True)
rmse = evaluation.rmse(y, mean)
coverage, _ = evaluation.intervalstats(y, mean, std ** 2)
print(f"RMSE: {rmse}")
print(f"Coverage: {coverage}")
The MOOGP Class
MOOGP(terms, q=None, Psi=None, *,
var_threshold=None, orthogonal=True, learn_Psi=False,
sigma_eps2=None, learn_sigma_eps=None, diag_error_structure=None,
standardize_x="unitcube", standardize_y="zscore")
| Argument | Default | Purpose |
|---|---|---|
terms |
— | Basis for the trend g(x) (section). |
q |
None |
Number of latent GPs (q ≤ p); defaults to full rank p when neither q nor var_threshold is given (section). |
Psi |
None |
(p, q) array or None; Initial / fixed mixing matrix. If learn_Psi=False, this must be provided. If learn_Psi=True, it's used for shape (section). |
var_threshold |
None |
Pick q automatically to capture this fraction of output variance; mutually exclusive with q (section). |
orthogonal |
True |
Orthogonalize the kernel against g(x); False is a standard squared exponential kernel. |
sigma_eps2 |
None |
Fixed per-output noise variances, shape (p,) (section). |
learn_sigma_eps |
auto | Learn the noise; defaults to True when sigma_eps2 is not given. |
diag_error_structure |
None |
Group outputs that share one noise variance (section). |
standardize_x |
"unitcube" |
Map inputs to [-1, 1] internally (section). |
standardize_y |
"zscore" |
Center and scale outputs internally. |
learn_Psi |
False |
Learn the mixing matrix instead of deriving it from the data (section). |
Advanced Usage
Specifying the trend with terms
terms lists the columns of the trend g(x). Each entry is None for an
intercept, an int j for the main effect of input j, or a tuple for an
interaction:
terms = [None, 1, 2, 3] # g(x) = [1, x1, x2, x3]
terms = [None, 1, 2, (1, 2)] # g(x) = [1, x1, x2, x1 * x2]
Choosing q
There are two ways that the number of latent components q can be explicitly specified upon intializing a MOOGP instance:
q=5: Five latent components will be used.qmust be less than or equal to the output dimensionpvar_threshold = 0.99: Include q latent components such that 99% of the output variance are explained, using a singular value decomposition.
Note: Only one of the options should be provided at a time.
model_q = MOOGP(terms=[None, 1, 2], q=5)
model_var = MOOGP(terms=[None, 1, 2], var_threshold=0.99)
Measurement noise and diag_error_structure
There is one variance term per output. By default it is learned, but you can also fix it to known values:
MOOGP(terms, q) # learn the noise (default)
MOOGP(terms, q, sigma_eps2=[10.0, 1.0, 0.05]) # fixed, known noise
Variances can also be shared across outputs. For example, take six outputs where the first two are measured precisely and the remaining four are noisy:
import numpy as np
n = 100
x = np.linspace(0.0, 1.0, n).reshape(-1, 1)
Y = np.column_stack([
np.sin(x), np.cos(x), # low-noise outputs
np.sin(x/2), np.cos(x/2), np.sin(x/3), np.cos(x/3), # high-noise outputs
])
Y[:, :2] += np.random.normal(0, 1e-3, size=(n, 2))
Y[:, 2:] += np.random.normal(0, 1e-1, size=(n, 4))
Pass diag_error_structure as the list of group sizes (which must sum to p). The
following groups the first 2 and the remaining 4 outputs, fitting two noise
variances:
model = MOOGP(terms=[None, 1], q=4, diag_error_structure=[2, 4])
model.fit({"X": x, "Y": Y})
Standardization
By default the model rescales data internally:
standardize_x="unitcube"maps each input to[-1, 1]standardize_y="zscore"centers/scales each output;"robust"uses median/MAD.
Set either to False if your data is already on the right scale. Predictions are
always returned on the original output scale.
Optimizer control and tolerance
The default optimization parameters for LBFGS-B are shown below and can be tuned via optimizer_opts:
model.fit(data, optimizer_opts={"maxiter": 500, "ftol": 1e-9, "gtol": 1e-6})
Start with a relatively low value for maxiter and increase if better performance is needed.
Kernel and mixing-matrix options
orthogonal=True(default) orthogonalizes the latent kernels against the trend so the GP residual carries no signal the trend already explains;Falsegives a conventional multi-output GP.- The mixing matrix
Psiis derived from the data by default. Pass a(p, q)array to fix it, or setlearn_Psi=Trueto learn it during fitting:
# Default: Psi is derived from data -- much faster with large n and p
model = MOOGP(terms=[None, 1, 2], q=3)
model.fit(data)
# Fix Psi to a known (p, q) mixing matrix (here p = 4 outputs, q = 3 latent GPs).
Psi = np.random.randn(4, 3)
model = MOOGP(terms=[None, 1, 2], q=3, Psi=Psi)
model.fit(data)
# Or learn Psi during fitting.
model = MOOGP(terms=[None, 1, 2], q=3, learn_Psi=True)
model.fit(data)
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file moogp-1.0.0.tar.gz.
File metadata
- Download URL: moogp-1.0.0.tar.gz
- Upload date:
- Size: 67.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8e9a7eda8d5a8ebfabc8d886fb7cf5afacfc170b43aea3d00a73292144dbae3c
|
|
| MD5 |
b994d57fc8d29d4f2ec0cb914b5084d8
|
|
| BLAKE2b-256 |
3cdc3bea980e69f0d7fed2f5c7aea8f026d0ab0e73dc23ec38a910223e3616ea
|
File details
Details for the file moogp-1.0.0-py3-none-any.whl.
File metadata
- Download URL: moogp-1.0.0-py3-none-any.whl
- Upload date:
- Size: 72.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c3b9d74f06e14fd65f2047bc3ce97c1008c757a69fa1efc2cb9dd5f20e8f6e5b
|
|
| MD5 |
be1ef264080dfc983d83938c99166929
|
|
| BLAKE2b-256 |
cbb4780ceb1b5ef26445999791c0cf84e2029e2b104bda72a1d3d5fe1775c360
|