Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Provide interface to the inference package EP-BOLFI #585

Open
YannickNoelStephanKuhn opened this issue Dec 6, 2024 · 11 comments · May be fixed by #666
Open

Provide interface to the inference package EP-BOLFI #585

YannickNoelStephanKuhn opened this issue Dec 6, 2024 · 11 comments · May be fixed by #666
Labels
enhancement New feature or request

Comments

@YannickNoelStephanKuhn
Copy link

Feature description

Makes EP-BOLFI available, an optimizer developed specifically for difficulties that are common with battery parameterization, such as, but not limited to:

  • noisy data,
  • incomplete models,
  • interdependent model parameters, and
  • ill-posed parameterizations.

Motivation

While EP-BOLFI, as in EP plus BOLFI, is expected to be superseded by its implementation within SOBER, its own interface here will serve as the basis of benchmarking the two against each other. Additionally, there are a lot of "self-driving" features within EP-BOLFI, the library, that make week-long runs on HPC resources viable. Finally, it might be the case that EP-BOLFI, the library, works better with limited resources, e.g., your decade-old work laptop.

Possible implementation

I would extend BaseOptimiser in a minimal fashion, rather than the way it is done for AdamWImpl. While EP-BOLFI internally has a lot of similar structure to what is shown in AdamWImpl, it would require a complete refactor of EP-BOLFI to expose it in this manner.
I will also have to extend OptimisationResult to a BayesOptimisationResult to catch parameter correlations and general uncertainty information. I would give it its own file, but I'm open to other suggestions.
Next, I need to figure out how to deal with the features in EP as a cost function and the Likelihoods involved as per pybop.costs. I'm unsure whether this is necessary; if so, this requires a minor refactor of EP-BOLFI.
Optionally, I would look into the way probabilistic Parameters are handled right now, checking if they can handle inherent parameter uncertainties that EP-BOLFI was designed to handle. These are not parameters to fit, but parameters that would be randomly generated in each model evaluation during optimization.
Finally, there may need to be some additional plotting routines for the BayesOptimisationResult.

Additional context

I've been asked to provide an interface to EP-BOLFI in the past, and I'm happy to finally have the resources to oblige.
This will also help me with addressing the SOBER and BASQ interfaces mentioned in #228 afterwards, as I can practice a Bayesian Optimizer interface with something I'm more intimately familiar with.

@YannickNoelStephanKuhn YannickNoelStephanKuhn added the enhancement New feature or request label Dec 6, 2024
@BradyPlanden
Copy link
Member

Hi Yannick,

Thanks for opening this issue. This sounds like a reasonable path forward, feel free to ping me as you go through the process of integrating the cost/likelihood and parameters. If you can structure this functionality within the experimental directory (see #481) for the initial landing, we can move it outside once it's stabilised. Cheers!

@YannickNoelStephanKuhn
Copy link
Author

Hi Brady,
will do, thanks for the offer. For the time being, I will just document my progress here.
As a first step, I drafted how PyBOP might handle multivariate distributions; the multivariate priors are drafted in YannickNoelStephanKuhn@15e75fc and the multivariate parameters are drafted in YannickNoelStephanKuhn@6ef018a.
While not strictly necessary, it enables a technique common in Bayesian Optimisation: re-using a Posterior as a Prior for further refinement.

@YannickNoelStephanKuhn
Copy link
Author

Drafted a minimal EP-BOLFI interface in YannickNoelStephanKuhn@20dd5a6.
It translates PyBOP input -> EP-BOLFI routine -> PyBOP output, but does not integrate the sampling in any way with PyBOP. I will also have to check if it works out to keep parameter transformations on the PyBOP side, or if I have to move them over to EP-BOLFI.
Posteriors are tacked onto a BayesianOptimisationResult, handled via the BasePrior object type.
The Likelihood is available via the bolfi_posterior attribute; I could wrap that within a BaseMetaLikelihood, but it is a result, not an input like the other PyBOP Likelihoods.

@YannickNoelStephanKuhn
Copy link
Author

YannickNoelStephanKuhn commented Jan 16, 2025

@BradyPlanden

Hi Brady,
I wrote up a minimal almost-working EP-BOLFI integration, see this commit: YannickNoelStephanKuhn@fbe288e
Almost-working, because the test_ep_bolfi.py errors out with no 'Negative electrode active material volume fraction' parameter in the Marquis2019 or Chen2020 datasets. I'm not sure whether I somehow have a broken PyBaMM installation or if the test script has some other glaring issue.

Other things I would like to talk about:

  • I figured out how PyBOP could handle multivariate parameters, but we have to agree if that solution is elegant enough. There are some points where PyBOP is engineered around a collection of univariate parameters, which I had to circumvent.
  • I also added example costs in line with how EP-BOLFI would be usually used: costs that compare parameters of fit functions. I heavily import from my ep_bolfi library here to make the experimental implementations more concise, and because of licensing issues. If you could do without the self-adapting fit functions, a simple inverse function fit without the ep_bolfi import would suffice.

@YannickNoelStephanKuhn
Copy link
Author

Everything works now: YannickNoelStephanKuhn@e543f05

To put a bow on it, I will figure out a nice plotting routine for Bayesian results. If the two points mentioned above are okay with you, I would open a pull request after.

@YannickNoelStephanKuhn
Copy link
Author

I implemented a predictive posterior visualization; if that term is unfamiliar, it boils down to plotting model evaluations of random variates drawn from the posterior parameter distribution. YannickNoelStephanKuhn@0aa55b3

It also shows how I work around the parallelization issue in #642 right now; with lots of copy.deepcopys of the problem. See specifically pybop/experimental/plot_bayes.py.

@YannickNoelStephanKuhn
Copy link
Author

YannickNoelStephanKuhn commented Jan 31, 2025

I rewrote the EP-BOLFI example YannickNoelStephanKuhn@ced4cb5 using the parallelization fix #645.

@YannickNoelStephanKuhn
Copy link
Author

@BradyPlanden

Hi Brady,

I'm currently writing some cost functions that more closely resemble the type of optimization EP-BOLFI was made for: viewing the data through the lens of fit functions.

My current implementation is here: https://github.com/YannickNoelStephanKuhn/PyBOP/blob/8decfd6f534885b5c6e42d7d04cd2490928e1ade/pybop/experimental/parameterized_costs.py
The issue I have is that the y passed to calls to the cost functions only includes "Voltage [V]" evaluations, even though the additional_variables in the FittingProblem are set to ["Time [s]"]. I tried to look where it comes from, but I do not understand where the y = self.DeferredPrediction gets set to the value the compute method gets.

Could you please show me where this happens?

@NicolaCourtier
Copy link
Member

Hi @YannickNoelStephanKuhn, maybe I can help here, but I'll refer back to this version before #635. The DeferredPrediction class is used to signify when a prediction y or gradient dy has not yet been calculated (but is expected). For costs that use the same prediction, y is computed before the cost evaluation (using the same y). Otherwise it is calculatd during cost.compute (different y). In my experience, the time domain data can be accessed through cost.problem.domain_data and so does not need to be passed through the prediction y. Would that work in your case?

@YannickNoelStephanKuhn
Copy link
Author

Hi @NicolaCourtier , thanks, that worked perfectly. The example now works as per YannickNoelStephanKuhn@d9d855b.

What are the next steps? Brady wanted me to put the files into an experimental folder until it has "stabilised". The EP-BOLFI integration itself is stable now, I would say, so should I see how they could be incorporated into the actual codebase, or would one of you like to handle that?

@BradyPlanden
Copy link
Member

Hi @YannickNoelStephanKuhn - excellent, thanks for getting this into a good place. If you can open a PR into develop for these changes, we can start the review process! At the moment, having this land in the experimental directory makes the most sense, not because EP-BOLFI is unstable, but because its support in PyBOP is new and untested. We can then work towards integrating it into the main codebase after it's first PyBOP release, so we can get feedback from users and developers.

@YannickNoelStephanKuhn YannickNoelStephanKuhn linked a pull request Feb 11, 2025 that will close this issue
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants