Skip to content

Addition of discrepancy GP emulators#956

Open
cwlanyon wants to merge 3 commits intoalan-turing-institute:mainfrom
cwlanyon:main
Open

Addition of discrepancy GP emulators#956
cwlanyon wants to merge 3 commits intoalan-turing-institute:mainfrom
cwlanyon:main

Conversation

@cwlanyon
Copy link
Copy Markdown

Discrepancy Emulators are a class of GP emulators that perform transfer learning across a cohort of existing simulators/digital twins.

Suppose you have a cohort of computational digital twins, $f_1,...,f_N$, where each $f_n$ represents an individual real-world system, and for each $f_n$ you have a Gaussian process emulator, $g_n$. If we want to generate an emulator for a similar system $f_{N+1}$, rather than generating a brand new emulator we can instead emulate the discrepancy between $f_{N+1}$ and the existing cohort.

$$g_{N+1}(\theta) = \sum_{n=1}^N a g_n(\theta) +\delta(\theta)$$

where $a$ are some weights to learn and $\delta$ is the discrepancy, which we model as a GP with its own independent mean and covariance functions. If $f_{N+1}$ is sufficiently similar to the rest of the cohort it should require fewer observations to learn $\delta$ than to learn an independent emulator.

See: https://link.springer.com/article/10.1007/s10439-025-03890-0

To implement Discrepancy GPs in AutoEmulate I have amended autoemulate/autoemulate/emulators/gaussian_process/exact.py to include a DiscrepancyGaussianProcess class and a create_dgp_subclass function to mirror the functionality for creating Gaussian process emulators in AutoEmulate.

Added code for discrepancy GPs in GaussianProcess/exact. This includes code for new mean and covariance functions and a Discrepancy GP subclass and createDGPSubclass function.
@radka-j radka-j self-requested a review January 29, 2026 15:20
@radka-j
Copy link
Copy Markdown
Member

radka-j commented Feb 5, 2026

@cwlanyon thank you so much for opening this PR! I just wanted to let you know that reviewing it is on our TODO list but we are currently working towards a tight deadline on our project so we have not had the capacity. We hope to get to it very soon.

@cwlanyon
Copy link
Copy Markdown
Author

cwlanyon commented Feb 5, 2026

@radka-j

Hi Radka, no problem! I'll see if I can get pre-commit to work in the meantime. Hope your deadline goes ok!

@radka-j
Copy link
Copy Markdown
Member

radka-j commented Feb 13, 2026

@cwlanyon I had a look at the pre-commit issues and will add comments here highlighting what needs changing. I will look at the rest of the code in more detail early next week :)

Copy link
Copy Markdown
Member

@radka-j radka-j left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be all the pre-commit issues. As you can see, most of it is just enforcing strict stylistic guidelines (e.g., max line lengths, docstring conventions). There is absolutely no rush on addressing them before we do a more thorough review of the whole code but hopefully it's useful in explaining what kinds of things get picked up.

The main thing to go over are the unused method arguments and decide whether these should be removed or whether there are some possible future use cases or compatibility issues with the rest of the code base that mean we should keep them.

"""
Discrepancy Gaussian Process Emulator.

This class implements an exact Discrepancy Gaussian Process emulator using the GPyTorch library
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is too long (limit is 88 characters)

Suggested change
This class implements an exact Discrepancy Gaussian Process emulator using the GPyTorch library
This class implements an exact Discrepancy Gaussian Process emulator using the
GPyTorch library


This class implements an exact Discrepancy Gaussian Process emulator using the GPyTorch library

Discrepancy GPs are a transfer learning method that require a pre-existing cohort of emulators for similar systems.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line too long

Suggested change
Discrepancy GPs are a transfer learning method that require a pre-existing cohort of emulators for similar systems.
Discrepancy GPs are a transfer learning method that require a pre-existing cohort of
emulators for similar systems.

Comment on lines +709 to +713
likelihood_cls: type[MultitaskGaussianLikelihood] = MultitaskGaussianLikelihood,
mean_module_fn: MeanModuleFn = constant_mean,
covar_module_fn: CovarModuleFn = rbf_plus_constant,
fixed_mean_params: bool = False,
fixed_covar_params: bool = False,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Number of these parameters are not used anywhere. Can they be removed? If not (for compatibility reasons), they should be saved as class args within the init.

self.x_transform = StandardizeTransform() if standardize_x else None
self.y_transform = StandardizeTransform() if standardize_y else None

self.covar_module = covar_module # gpytorch.kernels.RBFKernel(ard_num_dims=n_features,batch_shape=num_tasks_torch)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long, can be fixed by moving comment above the line

Suggested change
self.covar_module = covar_module # gpytorch.kernels.RBFKernel(ard_num_dims=n_features,batch_shape=num_tasks_torch)
# gpytorch.kernels.RBFKernel(ard_num_dims=n_features,batch_shape=num_tasks_torch)
self.covar_module = covar_module


for i in range(
len(self.ref_model)
): # Iterate over ref_models to build additive kernel TODO: Put this loop inside of the aKernel function
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, this line is too long, try splitting over 2 lines

Suggested change
): # Iterate over ref_models to build additive kernel TODO: Put this loop inside of the aKernel function
): # Iterate over ref_models to build additive kernel
# TODO: Put this loop inside of the aKernel function

self.ref_model = ref_model
self.ref_likelihood = ref_likelihood

def forward(self, x1, x2, **params):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing docstring in public method

Comment on lines +869 to +871
"""
Custom mean for Discrepancy GPs.
"""
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One-line docstring should fit on one line

Suggested change
"""
Custom mean for Discrepancy GPs.
"""
"""Custom mean for Discrepancy GPs."""

Custom mean for Discrepancy GPs.
"""

def __init__(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arguments input_size, batch_shape and bias are not used in the method

ref_model,
ref_likelihood,
a,
batch_shape=torch.Size(),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

function calls (torch.Size()) should not be used in argument defaults

one way to get around this would be to set batch_shape=None as the default and then within the method do something like

if batch_shape is None:
    batch_shape=torch.Size()

self.ref_likelihood = ref_likelihood
self.mean_module = mean_module

def forward(self, x):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing docstring in public method

Copy link
Copy Markdown
Collaborator

@sgreenbury sgreenbury left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks very much @cwlanyon for the contribution - think this is looking great!

I've left some initial comments below that might relate to the solving issues raised by the pre-commit - happy to discuss if helpful on a call any changes for those as well and any next steps such as adding tests.

self.to(self.device)


class aKernel(gpytorch.kernels.Kernel):
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this class could be given a more descriptive name and be CapWords?

length_prior=None,
length_constraint=None,
**kwargs,
):
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to add a docstring here for the init?

Comment on lines +835 to +837
a,
ref_model,
ref_likelihood,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If possible it would be great to add type hints for these parameters. This might also help solve any issues raised with pyright in the pre-commit.

Comment on lines +875 to +880
input_size,
mean_module,
ref_model,
ref_likelihood,
a,
batch_shape=torch.Size(),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned above, it would be great to add type hints in the function signatures.

self.ref_model = ref_model
self.ref_likelihood = ref_likelihood

def forward(self, x1, x2, **params):
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are **params needed in the signature here - perhaps they can be removed?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noting if could remove .ipynb_checkpoints before the final merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants