inlab-geo / cofi

Common Framework for Inference
https://cofi.readthedocs.io/en/latest/
BSD 2-Clause "Simplified" License
17 stars 4 forks source link

Parameterisation Class #154

Closed auggiemarignier closed 11 months ago

auggiemarignier commented 1 year ago

@jwhhh @fmagrini it looks like we both have a problem with integrating something that's parameterisation-specific into cofi. Here are a couple things to think about.

jwhhh commented 1 year ago

It makes sense to have a general Parameterisation class and inherit it with TransD1D (or Voronoi1D?) and OverComplete. There will be common functionalities like plotting, and conversion to/from a model vector.

For OverComplete, is it possible to think of it as a composition of two different kinds of parameterisations? Like Cosine1D and Pixel1D, and operator functions that can add them up. I don't remember the details of overcomplete tomography so not sure about the feasibility of this.

I'm thinking for a certain subclass of Parameterisation, there are these ways to categorise them and we can implement with MixIn classes:

All these utilities for Parameterisation and its subclasses are going to sit inside cofi.utils. You are right that they are in principle something we expect the users to define, so they don't really belong in CoFI's core. But they are here to save users' time to reinvent the wheels so we'd like to include them in a separate "utility" module.

These are just initial ideas. Thoughts?

auggiemarignier commented 1 year ago

I haven't heard of Mixin before but a quick google makes it look interesting.

Ok so to use the parameterisation the user would do something like

from cofi.utils.parameterisation import Cosine2D

...

def obective(x,...):
    ...
    return norm(data - ForwardModel(Cosine2D(x)))
auggiemarignier commented 1 year ago

I'm happy to start looking into implementing this because I can't really progress on my DCIP example without it

auggiemarignier commented 1 year ago

Looking a bit more into the utils that are already implemented (e.g. LpNormRegularization) we could follow a similar pattern. Regularisation gets integrated with BaseProblem.set_regularisation, so we could create BaseProblem.set_parameterisation which would then under the hood autoupdate the BaseProblem.forward (and/or objective, data_misfit etc) to call forward(Parameterisation(model)). Not sure how though.

jwhhh commented 1 year ago

Yes it would make sense to do this.

Alternatively, I was also thinking about something like:

my_parameterization = cofi.utils.OverComplete(*args)
my_initial_model = my_parameterization.to_model_vector()

my_problem = cofi.BaseProblem()
my_problem.set_initial_model(my_initial_model)
my_problem.set_forward(lambda m: my_fwd(my_parameterization(m)))

So that the users have more control and responsibility for handling parameterizations. In the end it's only a utility. There might be some points that I haven't thought of yet (especially with how we'll handle trans-d, but that's out of the scope for now) and I'm happy with either way for now.

msambridge commented 1 year ago

I suggest we have a discussion on this in the All-hands meeting?