torchsde icon indicating copy to clipboard operation
torchsde copied to clipboard

>0.2.0 feature list

Open patrick-kidger opened this issue 3 years ago • 3 comments

Creating a list of potential features that may be nice to have, but aren't necessarily a priority right now.

  • [x] Double backward w/ adjoint (#49)
  • [x] Stratonovich adjoint support for additive/scalar/diagonal noise.
  • [x] Continuous integration.
  • [x] Fix speed performance regression (compared to v0.1.1, the CPU-only example is 3 times as slow as before for v0.2.1) (#86)
  • [ ] autogenerated documentation
  • [ ] Add Milstein for general noise, using Levy area approximation.
  • [x] Allow an f_and_g function on SDEs, that computes drift+diffusion simultaneously. (#84)

Tests:

  • [ ] Write tests for full Levy area.
  • [ ] Write tests for sdeint actually approximating the analytical solution...
  • [ ] Write tests that logqp is computing the thing it's supposed to compute.
  • [ ] Fix BI doesn't pass tests when alpha=1e-2 issue. Very likely, something is wrong.

Maybe?

  • [ ] Derivative-using Stratonovich Milstein w/ scalar noise doesn't look like it's getting the right weak/strong convergence behaviour. (Curved line on log-log plot).
  • [ ] Use batch-vjp to compute dg_ga, if and when batch-vjp ever becomes available.
  • [ ] Add static tensors as an input to sdeint, sdeint_adjoint
  • [ ] C++ BInterval/BPath (to discuss) (If we do this, then #54 is relevant)

patrick-kidger avatar Sep 04 '20 16:09 patrick-kidger

My number one desired feature is antithetic sampling as an option for sdeint. It's pretty cumbersome to achieve this without editing the package by changing the BrownianInterval's W.

jparkhill avatar Aug 12 '21 19:08 jparkhill

I've not filled in every detail, but I'd have thought something like this should work:

class AntitheticBrownian(BaseBrownian):
   def __init__(self, bm):
       self.bm = bm

    def __call__(self, ta, tb):
        return -self.bm(ta, tb)

bm = BrownianInterval(...)
ys = torchsde(bm=bm, ...)

abm = AntitheticBrownian(bm)
ays = torchsde(bm=abm, ...)

ys = torch.cat([ys, ays])

Does this approach fail / am I missing something / are you trying to achieve something beyond this?

patrick-kidger avatar Aug 12 '21 19:08 patrick-kidger

Does work, but it's still much uglier than it needs to be vs sdeint(...,antithetic=True). For innumerable financial applications of this library, this type of option is... priceless ;p Here's a filled in version in case anyone else is following along:

ts = tch.linspace(0,1.,365)
ntraj = 1000
bm = torchsde.BrownianInterval(ts[0], ts[-1], size=(ntraj,sde.brownian_size), levy_area_approximation='space-time')
ys_ = torchsde.sdeint(sde,sde.y0(ntraj=ntraj), ts, bm=bm)
class AntitheticBrownian(torchsde.BrownianInterval):
    def __init__(self, t0, t1, size, bm):
        super(AntitheticBrownian, self).__init__(t0,t1,size, levy_area_approximation='space-time')
        self.bm = bm
    def __call__(self, ta, tb=None, return_U=False, return_A=False):
        Z = self.bm(ta, tb, return_U, return_A)
        if return_U:
            if return_A:
                return -Z[0], Z[1], Z[2]
            else:
                return -Z[0], Z[1]
        else:
            if return_A:
                return -Z[0], Z[1]
            else:
                return -Z
abm = AntitheticBrownian(ts[0], ts[-1], (ntraj,sde.brownian_size), bm)
ays = torchsde.sdeint(sde,sde.y0(ntraj=ntraj), ts, bm=abm)
ys = torch.cat([ys_, ays],1)```

jparkhill avatar Aug 12 '21 20:08 jparkhill