Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Optimization improvements #2221

Merged
merged 48 commits into from
Jun 1, 2024
Merged

Optimization improvements #2221

merged 48 commits into from
Jun 1, 2024

Conversation

mhauru
Copy link
Member

@mhauru mhauru commented May 10, 2024

Implementation of the work started in #2214. Work in progress. Needs

  • More and better tests.
  • A general clean-up.
  • Docstrings all over.
  • Taking care of the TODOs littered around.

@torfjelde

Closes #2227

@mhauru
Copy link
Member Author

mhauru commented May 15, 2024

This is at a stage where getting a review would be good. Please be pedantic and show no mercy, I need to learn the ways of the project. Some questions I've been wondering about myself:

  1. Functions names, especially exported ones. estimate_mode and link were two that I hesitated on.
  2. What's the convention for when to use implicit and explicit imports? I see a lot of source files mixing the two.
  3. Do we want to keep using ModeResult? That's the type that OptimInterface.jl returns its results in. I made Optimization.jl return the same type for compatibility, but would probably have designed the return type differently if given free rein.
  4. I've copied over tests from OptimInterface.jl's tests with minimal adaptation, resulting in some overlap. If the whole Optim.jl interface is on its way out though, might be worth leaving the overlap there, so that one can delete the OptimInterface.jl tests and not lose anything significant.
  5. Depending on what we do with ModeResult and OptimInterface.jl tests, I might split off some of the tests to a new file of tests just for OptimizationCore.jl.

@mhauru mhauru marked this pull request as ready for review May 15, 2024 16:04
@mhauru mhauru requested a review from torfjelde May 16, 2024 08:39
@torfjelde
Copy link
Member

Having a look now:)

Copy link
Member

@torfjelde torfjelde left a comment

Choose a reason for hiding this comment

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

Alrighty, here comes comments! 😬

Do let me know if anything is unclear, as there are quite a few of them.

I think going forward I'll try to keep the reviews a bit "themed" so that there isn't too much feedback at once, but we instead can do several iterations. But given that I'm not feeling 100%, I figured I'd do as much reviewing as possible when I'm feeling okay-ish.

Overall, I also have a few comments:

  1. See https://docs.julialang.org/en/v1/manual/documentation/#Writing-Documentation for official docs on docstrings 👍
  2. Though I can see that the ModeEstimationProblem is in a way a nice abstraction, now that we're going to depend fully on Optimization.jl, it seems a bit overkill in terms of what is needed. IIUC it's only really used in estimate_mode, and so can't we just put all this functionailty in estimate_mode directly? IMO this will make the code a more readable and easier to follow, as it just becomes "1) set up SciMLBase.OptimizationProblem, 2) solve it, and 3) convert into human readable format".
  3. I'd recommend merging the files OptimisationCore.jl and Optimisation.jl into a single one. Moreover, in particular for the sake of reviewing, try to avoid copy-pasting code form existing files to other files before the majority of the reviewing has been done, as it makes it very difficult to see exactly what is new code and what is simply moved code.

Hope this is helpful!

src/optimisation/Optimisation.jl Outdated Show resolved Hide resolved
src/optimisation/Optimisation.jl Outdated Show resolved Hide resolved
src/optimisation/Optimisation.jl Outdated Show resolved Hide resolved
src/optimisation/OptimisationCore.jl Outdated Show resolved Hide resolved
src/optimisation/OptimisationCore.jl Outdated Show resolved Hide resolved
src/optimisation/Optimisation.jl Outdated Show resolved Hide resolved
src/optimisation/Optimisation.jl Outdated Show resolved Hide resolved
src/optimisation/Optimisation.jl Outdated Show resolved Hide resolved
src/optimisation/Optimisation.jl Outdated Show resolved Hide resolved
src/optimisation/Optimisation.jl Outdated Show resolved Hide resolved
@mhauru
Copy link
Member Author

mhauru commented May 16, 2024

Thanks! I'll just leave comments now an get to fixing things later. Might take until Monday, tomorrow is quite full of other stuff.

Though I can see that the ModeEstimationProblem is in a way a nice abstraction, now that we're going to depend fully on Optimization.jl, it seems a bit overkill in terms of what is needed. IIUC it's only really used in estimate_mode, and so can't we just put all this functionailty in estimate_mode directly? IMO this will make the code a more readable and easier to follow, as it just becomes "1) set up SciMLBase.OptimizationProblem, 2) solve it, and 3) convert into human readable format".

We can put all of it in estimate_mode, yes, though I would at least keep some subfunctions to separate concerns. I do find the abstraction clarifies it for me. The main reason for the struct was that whether the objective function and the initial value (and correspondingly the returned solution) have been transformed to unconstrained space or not need to go hand in hand. The initial value is a bit nasty in that it's just a vector of numbers, that carries no information about the space it lives in. By putting it all in one struct you have to try harder to accidentally end up in a situation where you run an unconstrained space optimisation with the constrained space initial values, or some other ill combination of things.

I'd recommend merging the files OptimisationCore.jl and Optimisation.jl into a single one. Moreover, in particular for the sake of reviewing, try to avoid copy-pasting code form existing files to other files before the majority of the reviewing has been done, as it makes it very difficult to see exactly what is new code and what is simply moved code.

Fair point about copy-paste, sorry about that. I would usually make moving and editing separate commits, but this time the code went through a liquefy-and-reassemble stage in the beginning, and the first few commits do a bit of everything.

@torfjelde
Copy link
Member

We can put all of it in estimate_mode, yes, though I would at least keep some subfunctions to separate concerns. I do find the abstraction clarifies it for me

I can see that; as I said, I think they make sense. But it does add quite a bit of an overhead for a uninitiated reader who just wants to see what's up.

he main reason for the struct was that whether the objective function and the initial value (and correspondingly the returned solution) have been transformed to unconstrained space or not need to go hand in hand.

Makes a lot of sense! But I think after one of the changes suggested, this shouldn't really be a worry anymore.

Specifically, you can just do the following once:

    ld = p.log_density
    varinfo = DynamicPPL.link(
        DynamicPPL.unflatten(ld.varinfo, copy(p.init_value))
        ld.model
    )
    ld = Accessors.@set ld.varinfo = varinfo

if we need to work in unconstrained space, and then use

    varinfo_new = DynamicPPL.unflatten(varinfo, solution.u)
    # `getparams` performs the invlinking, if needed, etc.
    vns_vals_iter = getparams(prob.model, varinfo_new)
    syms = map(Symbol  first, vns_vals_iter)
    vals = map(last, vns_vals_iter)
    return ModeResult(
        NamedArray(vals, syms),
        solution,
        -solution.objective,
        prob.log_density
    )

(copy-paste from inline comments above) once you need to convert to a ModeResult. With this, there shouldn't be any other handling of unconstrained, etc.

Does that make sense?

Fair point about copy-paste, sorry about that. I would usually make moving and editing separate commits, but this time the code went through a liquefy-and-reassemble stage in the beginning, and the first few commits do a bit of everything.

No worries:) I also should have mentioned this before, and I every much know what you mean:)

@yebai yebai mentioned this pull request May 18, 2024
@coveralls
Copy link

coveralls commented May 22, 2024

Pull Request Test Coverage Report for Build 9221611696

Details

  • 0 of 120 (0.0%) changed or added relevant lines in 2 files are covered.
  • 5 unchanged lines in 2 files lost coverage.
  • Overall coverage remained the same at 0.0%

Changes Missing Coverage Covered Lines Changed/Added Lines %
ext/TuringOptimExt.jl 0 20 0.0%
src/optimisation/Optimisation.jl 0 100 0.0%
Files with Coverage Reduction New Missed Lines %
ext/TuringOptimExt.jl 2 0.0%
src/optimisation/Optimisation.jl 3 0.0%
Totals Coverage Status
Change from base Build 9141965383: 0.0%
Covered Lines: 0
Relevant Lines: 1501

💛 - Coveralls

Project.toml Outdated Show resolved Hide resolved
Co-authored-by: Hong Ge <3279477+yebai@users.noreply.github.com>
Copy link
Member

@torfjelde torfjelde left a comment

Choose a reason for hiding this comment

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

miiiinor final comments, but looking really good now:)

src/optimisation/Optimisation.jl Outdated Show resolved Hide resolved
src/optimisation/Optimisation.jl Outdated Show resolved Hide resolved
src/optimisation/Optimisation.jl Show resolved Hide resolved
Copy link
Member

@yebai yebai left a comment

Choose a reason for hiding this comment

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

Looks good — feel free to merge!

Copy link
Member

@torfjelde torfjelde left a comment

Choose a reason for hiding this comment

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

Fantastic stuff @mhauru 👏 I'm very happy about this change and you've done really great here:)

And sorry about the delayed reply; had a busy week with presentations, as you know.

Feel free to merge (and we can bump the Project.toml afterwards to avoid having to re-run tests)

@yebai yebai merged commit aa13e0c into master Jun 1, 2024
11 checks passed
@yebai yebai deleted the mhauru/optimization-improvements branch June 1, 2024 09:37
@yebai yebai mentioned this pull request Jun 1, 2024
yebai added a commit that referenced this pull request Jun 3, 2024
* Update README.md

* Export adtype `AutoTapir` (#2236)

* Export adtype `AutoTapir`

* Update Project.toml

* Fix missing AutoTapir  (#2242)

* Update Essential.jl

* Update Project.toml

* Drop support for ADTypes 0.2 (#2243)

ADTypes 0.2 doesn't support AutoTapir yet.

* Optimization improvements (#2221)

* initial work on interface

* Improving the Optimization.jl interface, work in progress

* More work on Optimization.jl, still in progress

* Add docstrings to Optimisation.jl

* Fix OptimizationOptimJL version constraint

* Clean up optimisation TODO notes

* Relax OptimizationOptimJL version constraints

* Simplify optimization imports

* Remove commented out code

* Small improvements all over in optimisation

* Clean up of Optimisation tests

* Add a test for OptimizationBBO

* Add tests using OptimizationNLopt

* Rename/move the optimisation test files

The files for Optimisaton.jl and OptimInterface.jl were in the wrong
folders: One in `test/optimisation` the other in `test/ext`, but the
wrong way around.

* Relax compat bounds on OptimizationBBO and OptimizationNLopt

* Split a testset to test/optimisation/OptimisationCore.jl

* Import AbstractADType from ADTypes, not SciMLBase

* Fix Optimization.jl depwarning

* Fix seeds in more tests

* Merge OptimizationCore into Optimization

* In optimisation, rename init_value to initial_params

* Optimisation docstring improvements

* Code style adjustments in optimisation

* Qualify references in optimisation

* Simplify creation of ModeResults

* Qualified references in optimization tests

* Enforce line length in optimization

* Simplify optimisation exports

* Enforce line legth in Optim.jl interface

* Refactor away ModeEstimationProblem

* Style and docstring improvements for optimisation

* Add := test to optimisation tests.

* Clarify comment

* Simplify generate_initial_params

* Fix doc references

* Rename testsets

* Refactor check_success

* Make initial_params a kwarg

* Remove unnecessary type constrain on kwarg

* Fix broken reference in tests

* Fix bug in generate_initial_params

* Fix qualified references in optimisation tests

* Add hasstats checks to optimisation tests

* Extend OptimizationOptimJL compat to 0.3

Co-authored-by: Hong Ge <3279477+yebai@users.noreply.github.com>

* Change some `import`s to `using`

Co-authored-by: Tor Erlend Fjelde <tor.erlend95@gmail.com>

* Change <keyword arguments> to kwargs... in docstrings

* Add a two-argument method to OptimLogDensity as callable

---------

Co-authored-by: Tor Erlend Fjelde <tor.erlend95@gmail.com>
Co-authored-by: Hong Ge <3279477+yebai@users.noreply.github.com>

* Update Project.toml

* CompatHelper: bump compat for OptimizationOptimJL to 0.3 for package test, (keep existing compat) (#2246)

Co-authored-by: CompatHelper Julia <compathelper_noreply@julialang.org>

---------

Co-authored-by: Markus Hauru <markus@mhauru.org>
Co-authored-by: Tor Erlend Fjelde <tor.erlend95@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: CompatHelper Julia <compathelper_noreply@julialang.org>
mhauru added a commit that referenced this pull request Jun 5, 2024
* Remove unused test util function

* Refactoring ad and optiminterface tests to modules

* Add SelectiveTests.jl

* Rework tests CI GA

* Switch test CI on Mac back to x64

* Remove coverage from CI. Improve matrix.

* Wrap all tests in modules.

* Remove unused test utils

* Remove GA workflows for DynamicHMC and Numerical

* Rename TuringCI GA to Tests

* Fix test_args passing in CI

* Fix for CI test matrix

* Fixes to various test files

* Add container.jl to test suite

* Fix spacing around * in test includes

* Split ad.jl and abstractmcmc.jl tests to separate CI jobs

* Alphabetise imports in tests

* In tests, use import X over using X: X

* Add missing imports to abstractmcmc.jl tests

* Add some missing imports to tests

* Merge ad_utils.jl to ad.jl in tests

* Merge testing_functions.jl into mh.jl in tests

* Simplify test_utils

Turn all of them into modules or merge them into other files that used
to `include` them.

* Add missing import to numerical_tests.jl

* Update Project.toml (#2244)

* Update README.md

* Export adtype `AutoTapir` (#2236)

* Export adtype `AutoTapir`

* Update Project.toml

* Fix missing AutoTapir  (#2242)

* Update Essential.jl

* Update Project.toml

* Drop support for ADTypes 0.2 (#2243)

ADTypes 0.2 doesn't support AutoTapir yet.

* Optimization improvements (#2221)

* initial work on interface

* Improving the Optimization.jl interface, work in progress

* More work on Optimization.jl, still in progress

* Add docstrings to Optimisation.jl

* Fix OptimizationOptimJL version constraint

* Clean up optimisation TODO notes

* Relax OptimizationOptimJL version constraints

* Simplify optimization imports

* Remove commented out code

* Small improvements all over in optimisation

* Clean up of Optimisation tests

* Add a test for OptimizationBBO

* Add tests using OptimizationNLopt

* Rename/move the optimisation test files

The files for Optimisaton.jl and OptimInterface.jl were in the wrong
folders: One in `test/optimisation` the other in `test/ext`, but the
wrong way around.

* Relax compat bounds on OptimizationBBO and OptimizationNLopt

* Split a testset to test/optimisation/OptimisationCore.jl

* Import AbstractADType from ADTypes, not SciMLBase

* Fix Optimization.jl depwarning

* Fix seeds in more tests

* Merge OptimizationCore into Optimization

* In optimisation, rename init_value to initial_params

* Optimisation docstring improvements

* Code style adjustments in optimisation

* Qualify references in optimisation

* Simplify creation of ModeResults

* Qualified references in optimization tests

* Enforce line length in optimization

* Simplify optimisation exports

* Enforce line legth in Optim.jl interface

* Refactor away ModeEstimationProblem

* Style and docstring improvements for optimisation

* Add := test to optimisation tests.

* Clarify comment

* Simplify generate_initial_params

* Fix doc references

* Rename testsets

* Refactor check_success

* Make initial_params a kwarg

* Remove unnecessary type constrain on kwarg

* Fix broken reference in tests

* Fix bug in generate_initial_params

* Fix qualified references in optimisation tests

* Add hasstats checks to optimisation tests

* Extend OptimizationOptimJL compat to 0.3

Co-authored-by: Hong Ge <3279477+yebai@users.noreply.github.com>

* Change some `import`s to `using`

Co-authored-by: Tor Erlend Fjelde <tor.erlend95@gmail.com>

* Change <keyword arguments> to kwargs... in docstrings

* Add a two-argument method to OptimLogDensity as callable

---------

Co-authored-by: Tor Erlend Fjelde <tor.erlend95@gmail.com>
Co-authored-by: Hong Ge <3279477+yebai@users.noreply.github.com>

* Update Project.toml

* CompatHelper: bump compat for OptimizationOptimJL to 0.3 for package test, (keep existing compat) (#2246)

Co-authored-by: CompatHelper Julia <compathelper_noreply@julialang.org>

---------

Co-authored-by: Markus Hauru <markus@mhauru.org>
Co-authored-by: Tor Erlend Fjelde <tor.erlend95@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: CompatHelper Julia <compathelper_noreply@julialang.org>

* Set fail-fast: false for CI test matrix

* Add a step to print matrix variables to tests Action

* Fix typo in tests Action

* ADTypes v0.2 compatibility for test restructuring (#2253)

* Restore compat with ADTypes v0.2. Make AutoTapir export conditional.

* Fix AutoTapir export in Essential.jl

---------

Co-authored-by: Hong Ge <3279477+yebai@users.noreply.github.com>
Co-authored-by: Tor Erlend Fjelde <tor.erlend95@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: CompatHelper Julia <compathelper_noreply@julialang.org>
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.

4 participants