Added tutorials on PDEs - #276
Conversation
This is a proof of concept on how to use dynestyx to solve inverse problems involving time dependent PDEs. Discretization is done manually using a finite difference scheme, yielding an ODE for which the dynestyx machinery can be applied.
|
Thanks Matthieu, this looks great!!
I don't want to put the cart before the horse -- but do you think we can package at least a few discretization schemes automatically (and/or, are there libraries we can import to do this)? It would be wonderful to have something like
I'm curious why you say this is much slower (I'd expect it to be faster actually, though somewhat-negligibly-so). I think this is an interesting and valuable example where reparameterization is really necessary, though. But the corresponding loc-scale reparameterization is also possible for the from numpyro.distributions.transforms import LowerCholeskyAffine
from numpyro.infer.reparam import TransformReparam
# define the initial condition a function of mu and x.
initial_condition = lambda mu : jnp.exp(- (x - mu)**2/(2*0.1**2)) * jnp.sin(jnp.pi*x)
ic_noise = 1e-2 # the noise on the initial condition
obs_noise = 1e-2 # the noise on the observations
def heat_equation_model(mu=None, obs_times=None, obs_values=None, predict_times=None):
mu = numpyro.sample("mu", dist.Uniform(0, 1), obs=mu)
# Create the dynamical model with sampled mu
# Reparameterize the initial condition
standard_x0 = dist.MultivariateNormal(
loc=jnp.zeros(n_interior),
scale_tril=jnp.eye(n_interior),
)
initial_distribution = dist.TransformedDistribution(
standard_x0,
LowerCholeskyAffine(
loc=initial_condition(mu),
scale_tril=ic_noise * jnp.eye(n_interior),
),
)
dynamics = DynamicalModel(
initial_condition=initial_distribution,
state_evolution=ContinuousTimeStateEvolution(
drift=lambda x, u, t: A @ x,
),
observation_model=LinearGaussianObservation(
H=jnp.eye(n_interior), R=obs_noise**2 * jnp.eye(n_interior)
),
)
return dsx.sample("f", dynamics, obs_times=obs_times, obs_values=obs_values, predict_times=predict_times)This gets pretty similar results (and similar timing, if not slower) on my machine to the existing results. Some other comments:
|
Removed html animations to reduce filesize. Changed the reparametrization to use MultivariateNormal (more in line with other tutorials). Renamed notebooks.
|
Re: adding discretization schemes. This would be very interesting and there are several candidate packages in the jax ecosystem we could consider. I have now changed the reparametrization to use I have removed the Regarding naming schemes, did you mean the names of the notebooks themselves? If so then fixed. Time discretization: I used the ImplicitEuler which requires an adaptive time step. Nonetheless, I reduced to dt = 1e-2 and reduced the tolerance so hopefully it runs a bit faster. Right now it takes 2-3 minutes to run each mcmc on my machine. If this is too slow, I will reduce the space discretization. |
Cool! Looking forward to chatting more about this!
Cool! And ah okay, yeah that makes sense.
Thanks!
Yep!
Well, this is true, but I think this actually points to some places we should improve cd_dynamax/our integration, which hasn't really been built around ODEs at all. For example, the solver is non-configurable for the Kalman filter (which, tbh, feels more just like a bug on our end). The EnKF, on the other hand, will always solve as an SDE, which is rather wasteful here. More stuff to talk about when we meet, I suppose :) |
|
Interesting, great work!
Overall this seems great to me---I'd be down to just add these directly to our Deep Dives + Examples and merge this PR; then do further iterations after our discussion next week. @DanWaxman what say you? |
|
I’d prefer the solver thing gets fixed first, or at least commented on in the notebook, I think gives potentially the wrong conclusion (or maybe the right conclusion for the wrong reason). Other than that I’m happy… it becomes another thing we need to update in #255, but at this point, c’est la vie. |
|
I'd prefer to fast-track this PR and add a short comment in the notebooks explaining that the FilterConfig has a solver associated with it (and note that that the ContinuousKF has a fixed solver that cannot be changed, pending #278).
For the ContinuousTimeEnKF, @MatthieuDarcy you could specify the solver there if you want. Indeed, it is unfortunate that CD-Dynamax is solving an ODE (zero diffusion) using an SDE solver (it is expecting the general case). When #226 lands, these should be mostly fixed (would be nice for that PR to discretize ODEs as mappings of diracs by the way). |
|
Thanks for the informative discussion, I wasn't aware of some of these subtleties. I added a note on the use of the The notebook on the linear heat equation is unchanged. |
|
|
Regarding the reparametrization, I'm no expert on MCMC but my understanding is that this is a common issue in hierarchical Bayesian models. My understanding is that here Regarding defining things using LTI since the beginning, my issue was that LTI implicitly assumes everything is an SDE, hence you cannot run ImplicitEuler. Later on, I have to define LTI because KF assumes that the dynamics are linear SDEs. I have now written a small paragraph pointing this out as well as the fact that the KF solver cannot be customized. However I agree that regenerating the data is not necessary and I have removed that part. |
1. Simplified some elements (no more generating the data twice) 2. Added a short explanation about the current limitations of the KF filter (SDE definition and default solver).
|
Ahhh, I think I understand, thanks for the explanation! You're saying that MCMC over p(mu, u_0 | Y) is a funnel with bad geometry, whereas (mu, eps_0 | Y) has better geometry?
Otherwise, I think I'm happy with it for now. @DanWaxman are you ok with merging this? |
Yeah. The MCMC gets stuck near This may also pop up other places -- it could be worth it to make a little helper for what I suggested above (or try to contribute some multivariate normal reparameterization to
In principle, yes -- though these tutorials need to be linked in the |
Mind creating a short issue about this? |
|
Added a comment explaining this and highlighting that this is not an issue when running the KF. |
DanWaxman
left a comment
There was a problem hiding this comment.
I moved things to deep_dives/, fixed some capitalization, and added a hyperlink for when the heat equation notebook is referenced. Otherwise, looks good to me, thanks again @MatthieuDarcy ! Looking forward to chatting more about this.
This is a proof of concept on how to use dynestyx to solve inverse problems involving time dependent PDEs.
Discretization is done manually using a finite difference scheme, yielding an ODE for which the dynestyx machinery can be applied.
Limitations:
In the heat equation initial value inference problem, I wasn't able to use the usual dist.MultivariateNormal when using MCMC directly on the solver. Instead, I had to use a clunky dist.Normal(initial_condition(mu), ic_noise).to_event(1) combined with a reparametrization to ensure that MCMC worked at all. This is not in line with the usual dynestyx syntax and is much slower.