Migrating ML-GPR from 0.x to 1.0#

Version 1.0 replaces the GPy/paramz implementation of ML-GPR with GPyTorch. This change gives ML-GPR a maintained, differentiable Torch backend and makes gradient-based inference such as MAP/Laplace and NUTS possible. It affects only ML-GPR; the power-spectrum and data-cube APIs are not part of this migration.

The high-level API is unchanged#

If ML-GPR is run from a TOML configuration, no Python-code migration is normally required. The main imports and workflow remain:

from ps_eor.ml_gpr import MLGPRConfigFile, MLGPRForegroundFitter

config = MLGPRConfigFile.load_with_defaults("ml_gpr.toml")
fitter = MLGPRForegroundFitter(config)
noise_for_fit = fitter.process_noise_cube(noise_cube)
result = fitter.run(data_cube, noise_for_fit)

Existing kernel type names in TOML, including MRBF, MMat32, MMat52, MExponential, MCosine, and MRatQuad, are retained. The Running an ML-GPR fit and Building the covariance model pages describe the current configuration interface.

Advanced API changes#

Code that directly built kernels, manipulated GPy parameters, or instantiated samplers must be updated. The monolithic ps_eor.ml_gpr module is now a package with explicit submodules:

0.x object or pattern

1.0 replacement

MRBF, MMat32, MMat52, MExponential, MCosine, MRatQuad

UVScaledKernel with family set to "rbf", "matern32", "matern52", "exponential", "cosine", or "ratquad".

MWhiteHeteroscedastic

WhiteHeteroscedasticKernel.

GPy kernel addition and multiplication

kernel_a + kernel_b and kernel_a * kernel_b, or combine_kernels().

GPy/paramz priors and constraints

set_free(name, prior) and set_fixed(name, value) with priors from ps_eor.ml_gpr.priors.

Objects imported from the old monolithic module

Import from ps_eor.ml_gpr.kernels, ps_eor.ml_gpr.multidata, ps_eor.ml_gpr.regressor, or ps_eor.ml_gpr.samplers as appropriate.

MLGPRForegroundFitter.run_optimizer()

Select sampler_method = "map" and call run(). For direct use, instantiate MAPOptimizer.

For example, an explicitly constructed 1.0 model looks like:

from ps_eor.ml_gpr.kernels import UVScaledKernel, WhiteHeteroscedasticKernel
from ps_eor.ml_gpr.priors import Log10UniformPrior, UniformPrior
from ps_eor.ml_gpr.regressor import MultiGPRegressor
from ps_eor.ml_gpr.samplers import MCMCSampler

foreground = UVScaledKernel(
    family="rbf", variance=1.0, lengthscale=10.0, use_uv_ps=False
)
foreground.set_free("variance", Log10UniformPrior(-2, 1), log_scale=True)
foreground.set_free("lengthscale", UniformPrior(5, 100))
foreground.set_fixed("var_alpha", 0)
foreground.set_fixed("ls_alpha", 0)

noise = WhiteHeteroscedasticKernel(alpha=1.0)
noise.set_free("alpha", UniformPrior(0.5, 2.0))

gp = MultiGPRegressor(multi_data, {"fg": foreground, "noise": noise})
result = MCMCSampler(gp, n_walkers=50).run(n_steps=500, n_burn=300)

Here multi_data is a MultiData instance. See Choosing an inference method and the Tutorial notebooks for complete runnable examples.

VAE kernels#

VAEKernTorch is now constructed directly from a trained VAEFitter. The fitter supplies the decoder, wavenumber grid, latent dimensionality, and preprocessing, replacing the GPy wrapper used in 0.x.

Saved results and trained VAEs#

Results written by save() in 0.x can be loaded by load() in 1.0. This includes the saved configuration, input and noise cubes, MCMC or nested samples, and the parameter ordering needed to use those samples with the new GPyTorch model. Legacy complex NoiseStdCube files are converted to the current full-complex standard-deviation convention while loading.

Trained VAE fitters saved by 0.x are also supported. The 1.0 loader restores the former module paths while unpickling them, so they can still be referenced by fitter_filename and used by VAEKernTorch. As before, the path stored in the configuration must point to an accessible fitter file; update the path when moving an analysis between systems.