Pytrees
jax.readthedocs.io
jax.readthedocs.io
As an example: if you want to implement logistic regression in JAX, you need to optimize the weights. This is easy enough since this can be modeled as a single value, a matrix of weights. If you want to model a 2 layer MLP, now you have to use 2 matrices of weights (at least). You could treat this as two parameters to your function (which makes the derivative more complicated to manage) or you could concatenate the weights and split them up, etc. Annoying, but managable.
When you get to something like a diffusion model you now need to manage parameters for a variety of different, quite complex, models. It really helps if you can keep track of all these parameters in whatever data structure you like, but also trivially just call "grad" with regard to these and get your models derivative with respect to its parameters.
Pytrees make this incredibly simple, and is a major quality of life improvement in automatic differentiation.
It provides similar functionality but is standalone and does not depend on JAX, TF or anything else.
I believe JAX has a utility for this somewhere, can’t quite remember what this is called.
I typically think of JAX as quite restrictive — but I think the reality is that the only real limit on expressivity is that you can’t dynamically allocate inside of unbounded control flow (e.g. creating new allocations inside of a while loop).
(Although technically that works by tracing and extracting all constants from the jaxpr, rather than introspecting the function's closure cells -- it sounds like your trick is the latter.)
When you discuss dynamic allocation, I'm guessing you're mainly referring to not being able to backprop through `jax.lax.while_loop`. If so, you might find `equinox.internal.while_loop` interesting, which is an unbounded while loop that you can backprop through! The secret sauce is to use a treeverse-style checkpointing scheme.
https://github.com/patrick-kidger/equinox/blob/f95a8ba13fb35...
https://github.com/patrick-kidger/equinox
(Now on 1.1k stars so it's achieved some popularity!)
This makes model-building elegant (IMO), without any new abstractions to learn. Quite a PyTorch-like experience overall.
And if you're doing implicit methods, then you may be interested to hear that today's release of Diffrax now includes IMEX solvers! Sil3, KenCarp3, KenCarp4, KenCarp5.
Something really annoying about this system is that for a non-negligible portion of the parameter space, an adaptive step solver would fail and give up at some point during the integration because the step size converges to zero. This was preventing me from doing large parameter searches. Now, because diffrax makes it easy to specify the step size controller, I first try to solve the system with a PID step size control, and if this fails, I rerun it with small fixed steps, which is slower but always goes through the end. This guarantees that I will always get a complete solution, and that it will still be fast in 95% of cases, which is really a huge improvement.
Using Numba to jit compile the rhs might speed things up in the non-diffrax version.
Does the LSODA solver not take a minimum time step parameter? Setting that to your small fixed step might also help.