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

Euler-Heun method #39

Merged
merged 7 commits into from
Sep 1, 2020
Merged

Euler-Heun method #39

merged 7 commits into from
Sep 1, 2020

Conversation

mtsokol
Copy link
Contributor

@mtsokol mtsokol commented Aug 24, 2020

Hi!
Just euler-heun method.
Tried to run it but it hangs on BrownianInterval so related to #36

@mtsokol
Copy link
Contributor Author

mtsokol commented Aug 25, 2020

@patrick-kidger Hi! Just rebased - now it all works:

Copy link
Collaborator

@patrick-kidger patrick-kidger left a comment

Choose a reason for hiding this comment

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

Other than the minor comments, LGTM. Thanks for implementing.
The fix for BrownianInterval is now in dev so you should be able to run the diagnostics. What do they look like?
EDIT: looks like we crossed paths. What do the diagnostics look like for different noise types?

torchsde/_core/methods/euler_heun.py Outdated Show resolved Hide resolved
torchsde/_core/methods/euler_heun.py Outdated Show resolved Hide resolved
@mtsokol
Copy link
Contributor Author

mtsokol commented Aug 25, 2020

@patrick-kidger I've rewritten stratonovich diagnostics to scalar noise type (found one issue). Should I commit those files also? (it's basically copy paste of diagonal except for problem) Or only post plots here?
(and the same question regarding additive noise type)

@patrick-kidger
Copy link
Collaborator

As you've got them, let's include the files as well. We'll probably be interested in running those later too.
(In fact the diagnostics all share a lot of common code that should be factored out somewhere, but that's not super important now.)

@mtsokol
Copy link
Contributor Author

mtsokol commented Aug 25, 2020

Ok, I included stratonovich diagnostics for additive and scalar.
For both basic plots look OK.

Rates plots look like this:

  • scalar
  • additive [EDIT](changed back to Ex3)

There's an issue with milstein solver - for scalar noise dimensions does not conform to compute Y_prime as g it's one additional dimension bigger (included fix but it's a quick one just to make it pass).

And looking at rates milstein for additive it's wrong but haven't figured it out yet. Btw both grad-free and default use gdg_prod_default - according to comment grad_free path isn't ready yet, right?

torchsde/_core/methods/euler_heun.py Show resolved Hide resolved
torchsde/_core/methods/milstein.py Outdated Show resolved Hide resolved
tests/problems.py Outdated Show resolved Hide resolved
@lxuechen
Copy link
Collaborator

So for additive noise SDEs, the diffusion doesn't depend on the state. So the Ito interpretation is the same as the Strat interpretation, and the Milstein schemes should all have the same strong order as the Euler scheme.

@mtsokol
Copy link
Contributor Author

mtsokol commented Aug 26, 2020

Thanks for review - now I got it. Updated plots above - now it all looks right.

if sde.noise_type == NOISE_TYPES.additive:
self.strong_order = 1.0
else:
self.strong_order = 1.0
Copy link
Collaborator

Choose a reason for hiding this comment

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

The above if statement is superfluous. Also, the strong order should be 0.5 for general noise.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, sorry for that, fixed.
Also I've started working on a benchmark from [19] from the paper ("Smoking adjoints"). For now I've tried to follow exactly their formulas and they use Euler solver in log form - I need to compute g there but for adjoint_sdeint it fails as it's not supported due to efficiency. What can I do about it? Can g somehow be computed for adjoint_sdeint? (I've also tried to make it as a field in sde and access it from _base_sde from solver but as in forward it's wrapped: ForwardSDE(base_sde) in backward I think it's AdjointSDE(ForwardSDE(base_sde)))

Copy link
Collaborator

Choose a reason for hiding this comment

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

So back when that paper was written, "adjoint" meant "backprop through the solver".
These days, confusingly, we've appropriated the term to mean "don't backprop through the solver, and solve a differential equation instead".
As a result that paper is basically just about the now well-understood advantages of using backpropgation over forward-mode differentiation. (At least in this context.)

So they don't actually use the adjoint SDE at all, and what they do is equivalent to just using our sdeint in the normal way.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I got it while reading the paper. What I'm trying is to extend that benchmark from "smoking adjoints" with stochastic adjoint from here so I want to do it forward vs sdeint vs adjoint_sdeint.
And due to the fact that in custom log_euler solver that I created I'm using g the described error occurs.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure what your distinction between forward and sdeint is.

You shouldn't need to create a custom solver I don't think - IIRC in that paper they use an SDE to model log-rates; solve that with Euler--Maruyama; take an exponential if you want the rates themselves.

Likewise, you shouldn't need to use g in the adjoint: the standard EM scheme only needs g_prod.

Does that make sense / am I understanding you correctly? If not perhaps can you provide some references to where in the SA paper you're looking? (There's a couple copies of that paper out there, I tend to look at this one - https://www0.gsb.columbia.edu/faculty/pglasserman/Other/RiskJan2006.pdf)

Copy link
Contributor Author

@mtsokol mtsokol Aug 27, 2020

Choose a reason for hiding this comment

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

Yeah I was reading exactly that one.

By forward method I mean computing dV/dS with (sdeint(S+h) - sdeint(S-h)) / 2h, by sdeint ("adjoint" in "smoking adjoints", "backprop through the solver" here 😄) dV/dS is sol = sdeint(S); torch.grad(sol, S) and last one adjoint_sdeint - dV/dS is sol = adjoint_sdeint(S); torch.grad(sol, S). (I hope I didn't mess it up). Also I've got PoC and they yield same gradient result.

Code is similar to this (as forward vs sdeint): https://github.com/mgroncki/AdjointMonteCarlo/blob/master/PlainVanillaOption/blackMC.cpp

Thanks for help! I will try it that way. To explain myself the log-Euler solver was used in paper and also in references in Monte Carlo Methods In Financial Engineering (page 398) directly for that model.

Copy link
Contributor Author

@mtsokol mtsokol Aug 27, 2020

Choose a reason for hiding this comment

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

But I think I need a bit more time to fully figure all these methods out on paper.
The chapter 7. of that book also makes comparison of two methods: the finite-difference approach defined as (Y(S+h) - Y(S-h)) / 2h and pathwise mehtod (which is the one compared in "smoking adjoints").

@patrick-kidger
Copy link
Collaborator

This LGTM. @lxuechen happy for me to pull the squash+merge trigger?

diagnostics/stratonovich_additive.py Show resolved Hide resolved
diagnostics/stratonovich_additive.py Outdated Show resolved Hide resolved
diagnostics/stratonovich_additive.py Outdated Show resolved Hide resolved
diagnostics/stratonovich_additive.py Outdated Show resolved Hide resolved
diagnostics/stratonovich_additive.py Outdated Show resolved Hide resolved
diagnostics/stratonovich_additive.py Outdated Show resolved Hide resolved
diagnostics/stratonovich_additive.py Outdated Show resolved Hide resolved
diagnostics/stratonovich_additive.py Outdated Show resolved Hide resolved
diagnostics/stratonovich_additive.py Outdated Show resolved Hide resolved
@lxuechen
Copy link
Collaborator

The code in general is okay. I'd recommend using a linter with the character limits and blank line between imports/functions enforced.

Thanks again for the putting in the effort in implementing these methods.

@mtsokol
Copy link
Contributor Author

mtsokol commented Aug 31, 2020

Thanks for review! My main PL is Scala and python integration in my VS code barely works but I will setup that linter options to avoid those comments in the future.

@mtsokol
Copy link
Contributor Author

mtsokol commented Aug 31, 2020

Just one moment - milstein naming should be fixed also in diagonal and scalar files.

@mtsokol
Copy link
Contributor Author

mtsokol commented Aug 31, 2020

@lxuechen OK, now it's ready.

@lxuechen lxuechen merged commit 16389a6 into google-research:dev Sep 1, 2020
@mtsokol
Copy link
Contributor Author

mtsokol commented Sep 1, 2020

P.S. (asking out of curiosity) Do you have a roadmap for merging dev into master and cutting new release?

@patrick-kidger patrick-kidger mentioned this pull request Sep 1, 2020
9 tasks
@patrick-kidger
Copy link
Collaborator

@mtsokol
Loosely speaking yes, although @lxuechen and I haven't fixed things in detail.

I think we'd like to tick off the remaining things in #15. Fortunately, I think we've now done all the complicated ones, and it's mostly just grunt work remaining.
My hope is for a new release this month. (I'm only speaking personally there; Chen and I haven't discussed release schedules yet.)

@lxuechen
Copy link
Collaborator

lxuechen commented Sep 1, 2020

@mtsokol @patrick-kidger

I agree mostly with Patrick. Aside from the technical problems in #15, on a high level, I think the most crucial missing things are

  • documentation (docstring, README, additional doc site generated from docstring?)
  • tests, tests, and tests
  • benchmarks
  • continuous integration
  • backward comp fixes

I think we should be able to pull off another release in this month, if things go well. Though, I also think we shouldn't rush things by too much and only merge when we're genuinely ready.

lxuechen added a commit that referenced this pull request Oct 22, 2020
* Added BrownianInterval

* Unified base solvers

* Updated solvers to use interval interface

* Unified solvers.

* Required Python 3.6. Bumped version.

* Updated benchmarks. Fixed several bugs.

* Tweaked BrownianInterval to accept queries outside its range

* tweaked benchmark

* Added midpoint. Tweaked and fixed things.

* Tided up adjoint.

* Bye bye Python 2; fixes #14.

* tweaks from feedback

* Fix typing.

* changed version

* Rename.

* refactored settings up a level. Fixed bug in BTree.

* fixed bug with non-srk methods

* Fixed? srk noise

* Fixed SRK properly, hopefully

* fixed mistake in adjoint

* Fix broken tests and refresh documentation.

* Output type annotation.

* Rename to reverse bm.

* Fix typo.

* minor refactors in response to feedback

* Tided solvers a little further.

* Fixed strong order for midpoint

* removed unused code

* Dev kidger2 (#19)

* Many fixes.

Updated diagnostics.
Removed trapezoidal_approx
Fixed error messages for wrong methods etc.
Can now call BrownianInterval with a single value.
Fixed bug in BrownianInterval that it was always returning 0!
There's now a 2-part way of getting levy area: it has to be set as
available during __init__, and then specified that it's wanted during
__call__. This allows one to create general Brownian motions that can be
used in multiple solvers, and have each solver call just the bits it
wants.
Bugfix spacetime -> space-time
Improved checking in check_contract
Various minor tidy-ups
Can use Brownian* with any Levy area sufficient for the solver, rather
than just the minimum the solver needs.
Fixed using bm=None in sdeint and sdeint_adjoint, so that it creates an
appropriate BrownianInterval. This also makes method='srk' easy.

* Fixed ReverseBrownian

* bugfix for midpoint

* Tided base SDE classes slightly.

* spacetime->space-time; small tidy up; fix latent_sde.py example

* Add efficient gdg_jvp term for log-ODE schemes. (#20)

* Add efficient jvp for general noise and refactor surrounding.

* Add test for gdg_jvp.

* Simplify requires grad logic.

* Add more rigorous numerical tests.

* Fix all issues

* Heun's method (#24)

* Implemented Heun method

* Refactor after review

* Added docstring

* Updated heun docstring

* BrownianInterval tests + bugfixes (#28)

* In progress commit on branch dev-kidger3.

* Added tests+bugfixes for BrownianInterval

* fixed typo in docstring

* Corrections from review

* Refactor tests for

* Refactor tests for BrownianInterval.

* Refactor tests for Brownian path and Brownian tree.

* use default CPU

* Remove loop.

Co-authored-by: Xuechen Li <12689993+lxuechen@users.noreply.github.com>

* bumped numpy version (#32)

* Milstein (Strat), Milstein grad-free (Ito + Strat) (#31)

* Added milstein_grad_free, milstein_strat and milstein_strat_grad_free

* Refactor after first review

* Changes after second review

* Formatted imports

* Changed used Ex. Reversed g_prod

* Add support for Stratonovich adjoint (#21)

* Add efficient jvp for general noise and refactor surrounding.

* Add test for gdg_jvp.

* Simplify requires grad logic.

* Add more rigorous numerical tests.

* Minor refactor.

* Simplify adjoints.

* Add general noise version.

* Refactor adjoint code.

* Fix new interface.

* Add adjoint method checking.

* Fix bug in not indexing the dict.

* Fix broken tests for sdeint.

* Fix bug in selection.

* Fix flatten bug in adjoint.

* Fix zero filling bug in jvp.

* Fix bug.

* Refactor.

* Simplify tuple logic in modified Brownian.

* Remove np.searchsorted in BrownianPath.

* Make init more consistent.

* Replace np.searchsorted with bisect for speed; also fixes #29.

* Prepare levy area support for BrownianPath.

* Use torch.Generator to move to torch 1.6.0.

* Prepare space-time Levy area support for BrownianPath.

* Enable all levy area approximations for BrownianPath.

* Fix for test_sdeint.

* Fix all broken tests; all tests pass.

* Add numerical test for gradient using midpoint method for Strat.

* Support float/int time list.

* Fixes from comments.

* Additional fixes from comments.

* Fix documentation.

* Remove to for BrownianPath.

* Fix insert.

* Use none for default levy area.

* Refactor check tensor info to reduce boilerplate.

* Add a todo regarding get noise.

* Remove type checks in adjoint.

* Fixes from comments.

* Added BrownianReturn (#34)

* Added BrownianReturn

* Update utils.py

* Binterval improvements (#35)

* Tweaked to not hang on adaptive solvers.

* Updated adaptive fix

* Several fixes for tests and adjoint.

Removed some broken tests.
Added error-raising `g` to the adjoint SDE.
Fixed Milstein for adjoint.
Fixed running adjoint at all.

* fixed bug in SRK

* tided up BInterval

* variable name tweak

* Improved heuristic for BrownianInterval's dependency tree. (#40)

* [On dev branch] Tuple rewrite (#37)

* Rename plot folders from diagnostics.

* Complete tuple rewrite.

* Remove inaccurate comments.

* Minor fixes.

* Fixes.

* Remove comment.

* Fix docstring.

* Fix noise type for problem.

* Binterval recursion fix (#42)

* Improved heuristic for BrownianInterval's dependency tree.

* Inlined the recursive code to reduce number of stack frames

* Add version number.

Co-authored-by: Xuechen <12689993+lxuechen@users.noreply.github.com>

* Refactor.

* Euler-Heun method (#39)

* Implemented euler-heun

* After refactor

* Applied refactor. Added more diagnostics

* Refactor after review

* Corrected order

* Formatting

* Formatting

* BInterval - U fix (#44)

* Improved heuristic for BrownianInterval's dependency tree.

* fixed H aggregation

* Added consistency test

* test fixes

* put seed back

* from comments

* Add log-ODE scheme and simplify typing. (#43)

* Add log-ODE scheme and simplify typing.

* Register log-ODE method.

* Refactor diagnostics and examples.

* Refactor plotting.

* Move btree profile to benchmarks.

* Refactor all ito diagnostics.

* Refactor.

* Split imports.

* Refactor the Stratonovich diagnostics.

* Fix documentation.

* Minor typing fix.

* Remove redundant imports.

* Fixes from comment.

* Simplify.

* Simplify.

* Fix typo caused bug.

* Fix directory issue.

* Fix order issue.

* Change back weak order.

* Fix test problem.

* Add weak order inspection.

* Bugfixes for log-ODE (#45)

* fixed rate diagnostics

* tweak

* adjusted test_strat

* fixed logODE default.

* Fix typo.

Co-authored-by: Xuechen Li <12689993+lxuechen@users.noreply.github.com>

* Default to loop-based. Fixes #46.

* Minor tweak of settings.

* Fix directory structure.

* Speed up experiments.

* Cycle through the possible line styles.

Co-authored-by: Patrick Kidger <33688385+patrick-kidger@users.noreply.github.com>

* Simplify and fix documentation.

* Minor fixes.

- Simplify strong order assignment for euler.
- Fix bug with "space_time".

* Simplify strong order assignment for euler.

* Fix bug with space-time naming.

* Make tensors for grad for adjoint specifiable. (#52)

* Copy of #55 | Created pyproject.toml (#56)

* Skip tests if the optional C++ implementations don't compile; fixes #51.

* Create pyproject.toml

* Version add 1.6.0 and up

Co-authored-by: Xuechen <12689993+lxuechen@users.noreply.github.com>

* Latent experiment (#48)

* Latent experiment

* Refactor after review

* Fixed y0

* Added stable div

* Minor refactor

* Simplify latent sde even further.

* Added double adjoint (#49)

* Added double adjoint

* tweaks

* Updated adjoint tests

* Dev adjoint double test (#57)

* Add gradgrad check for adjoint.

* Relax tolerance.

* Refactor numerical tests.

* Remove unused import.

* Fix bug.

* Fixes from comments.

* Rename for consistency.

* Refactor comment.

* Minor refactor.

* Add adjoint support for general/scalar noise in the Ito case. (#58)

* adjusted requires_grad

Co-authored-by: Xuechen Li <12689993+lxuechen@users.noreply.github.com>

* Dev minor (#63)

* Add requirements and update latent sde.

* Fix requirements.

* Fix.

* Update documentation.

* Use split to speed things up slightly.

* Remove jit standalone.

* Enable no value arguments.

* Fix bug in args.

* Dev adjoint strat (#67)

* Remove logqp test.

* Tide examples.

* Refactor to class attribute.

* Fix gradcheck.

* Reenable adjoints.

* Typo.

* Simplify tests

* Deprecate this test.

* Add back f ito and strat.

* Simplify.

* Skip more.

* Simplify.

* Disable adaptive.

* Refactor due to change of problems.

* Reduce problem size to prevent general noise test case run for ever.

* Continuous Integration.  (#68)

* Skip tests if the optional C++ implementations don't compile; fixes #51.

* Continuous integration.

* Fix os.

* Install package before test.

* Add torch to dependency list.

* Reduce trials.

* Restrict max number of parallel runs.

* Add scipy.

* Fixes from comment.

* Reduce frequency.

* Fixes.

* Make sure run installed package.

* Add check version on pr towards master.

* Separate with blank lines.

* Loosen tolerance.

* Add badge.

* Brownian unification (#61)

* Added tol. Reduced number of generator creations. Spawn keys now of
finite length. Tidied code.

* Added BrownianPath and BrownianTree as BrownianInterval wrappers

* added trampolining

* Made Path and Tree wrappers on Interval.

* Updated tests. Fixed BrownianTree determinism. Allowed cache_size=0

* done benchmarks. Fixed adjoint bug. Removed C++ from setup.py

* fixes for benchmark

* added base brownian

* BrownianPath/Tree now with the same interface as before

* BInterval(shape->size), changed BPath and BTree to composition-over-inheritance.

* tweaks

* Fixes for CI. (#69)

* Fixes for CI.

* Tweaks to support windows.

* Patch for windows.

* Update patch for windows.

* Fix flaky tests of BInterval.

* Add fail-fast: false (#72)

* Dev methods fixes (#73)

* Fixed adaptivity checks. Improved default method selection.

* Fixes+updated sdeint tests

* adjoint method fixes

* Fixed for Py3.6

* assert->ValueError; tweaks

* Dev logqp (#75)

* Simplify.

* Add stable div utility.

* Deprecate.

* Refactor problems.

* Sync adjoint tests.

* Fix style.

* Fix import style.

* Add h to test problems.

* Add logqp.

* Logqp backwards compatibility.

* Add type annotation.

* Better documentation.

* Fixes.

* Fix notebook. (#74)

* Fix notebook.

* Remove trivial stuff.

* Fixes from comments.

* Fixes.

* More fixes.

* Outputs.

* Clean up.

* Fixes.

* fixed BInterval flakiness+slowness (#76)

* Added documentation (#71)

* Added documentation

* tweaks

* Fix significance level.

* Fix check version.

* Skip confirmation.

* Fix indentation errors.

* Update README.md

Co-authored-by: Patrick Kidger <33688385+patrick-kidger@users.noreply.github.com>
Co-authored-by: Mateusz Sokół <8431159+mtsokol@users.noreply.github.com>
Co-authored-by: Sayantan Das <36279638+ucalyptus@users.noreply.github.com>
@mtsokol mtsokol deleted the dev-euler-heun branch September 22, 2023 12:30
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.

None yet

3 participants