Skip to content

Commit 296d33f

Browse files
Update sensitivity.md
1 parent 51b39c0 commit 296d33f

File tree

1 file changed

+108
-15
lines changed

1 file changed

+108
-15
lines changed

docs/src/analysis/sensitivity.md

+108-15
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,58 @@ is the vector of sensitivities. Since this ODE is dependent on the values of the
222222
independent variables themselves, this ODE is computed simultaneously with the
223223
actual ODE system.
224224

225+
Note that the Jacobian-vector product:
226+
227+
```math
228+
\frac{\partial f}{\partial u}\frac{\partial u}{\partial p_{j}}
229+
```
230+
231+
can be computed without forming the Jacobian. With finite differences, this through using the following
232+
formula for the directional derivative:
233+
234+
```math
235+
Jv \approx \frac{f(x+v \epsilon) - f(x)}{\epsilon}
236+
```
237+
238+
or by using a dual number with a single partial dimension, ``d = x + v \epsilon`` we get that
239+
240+
```math
241+
f(d) = f(x) + Jv \epsilon
242+
```
243+
244+
as a fast way to calcuate ``Jv``. Thus, except when a sufficiently good function for `J` is given
245+
by the user, the Jacobian is never formed. For more details, consult the
246+
[MIT 18.337 lecture notes on forward mode AD](https://mitmath.github.io/18337/lecture9/autodiff_dimensions).
247+
248+
#### Syntax
249+
250+
`ODELocalSensitivityProblem` is similar to an `ODEProblem`:
251+
252+
```julia
253+
function ODELocalSensitivityProblem(f::DiffEqBase.AbstractODEFunction,u0,
254+
tspan,p=nothing,
255+
SensitivityAlg();
256+
kwargs...)
257+
```
258+
259+
The `SensitivityAlg` is used to mirror the definition of the derivative options seen generally
260+
throughout OrdinaryDiffEq.jl. The keyword options on the `SensitivityAlg` are as follows:
261+
262+
* `autojacvec`: Calculate Jacobian-vector (local sensitivity analysis) product
263+
via automatic differentiation with special seeding to avoid building the Jacobian.
264+
Default is `true`. If `autodiff=false`, it will use the Jacobian-free forward
265+
differencing approximation. If `false`, the Jacobian will prefer to use any
266+
`f.jac` function provided by the user. If none is provided by the user, then it
267+
will fall back to automatic or finite differentiation, though this choice is
268+
not recommended.
269+
* `autodiff`: Use automatic differentiation in the internal sensitivity algorithm
270+
computations. Default is `true`.
271+
* `chunk_size`: Chunk size for forward mode differentiation. Default is `0` for
272+
automatic chunk size choice. Only used when `autojacvec=false`.
273+
* `diff_type`: Choice of differencing used to build the Jacobian when `autojacvec=false`
274+
and `autodiff=false`. Defaults to `Val{:central}` for central differencing with
275+
DiffEqDiffTools.jl.
276+
225277
#### Example solving an ODELocalSensitivityProblem
226278

227279
To define a sensitivity problem, simply use the `ODELocalSensitivityProblem` type
@@ -384,6 +436,17 @@ g_{y}(t_{i})=2\left(\tilde{u}(t_{i})-u(t_{i},p)\right)
384436
Thus the adjoint solution is given by integrating between the integrals and
385437
applying the jump function ``g_y`` at every data point.
386438

439+
We note that
440+
441+
```math
442+
\lambda^{\star}(t)f_{u}(t)
443+
```
444+
445+
is a vector-transpose Jacobian product, also known as a `vjp`, which can be efficiently computed
446+
using the pullback of backpropogation on the user function `f` with a forward pass at `u` with a
447+
pullback vector ``\lambda^{\star}``. For more information, consult the
448+
[MIT 18.337 lecture notes on reverse mode AD](https://mitmath.github.io/18337/lecture10/estimation_identification)
449+
387450
#### Syntax
388451

389452
There are two forms. For discrete adjoints, the form is:
@@ -428,10 +491,10 @@ s = adjoint_sensitivities(sol,alg,g,nothing;kwargs...)
428491

429492
then it will be computed automatically using ForwardDiff or finite
430493
differencing, depending on the `autodiff` setting in the `SensitivityAlg`.
431-
Note that the keyword arguments are passed
432-
to the internal ODE solver for solving the adjoint problem. Two special keyword
433-
arguments are `iabstol` and `ireltol` which are the tolerances for the internal
434-
quadrature via QuadGK for the resulting functional.
494+
Note that the keyword arguments are passed to the internal ODE solver for
495+
solving the adjoint problem. Two special keyword arguments are `iabstol` and
496+
`ireltol` which are the tolerances for the internal quadrature via QuadGK for
497+
the resulting functional.
435498

436499
#### Options
437500

@@ -453,19 +516,49 @@ res = adjoint_sensitivities(sol,Vern9(),dg,t,reltol=1e-8,
453516
its higher order interpolation then this is by default disabled.
454517
* `quad`: Use Gauss-Kronrod quadrature to integrate the adjoint sensitivity
455518
integral. Disabling it can decrease memory usage but increase computation
456-
time. Default is `true`.
519+
time, since post-solution quadrature can be more accurate with less points
520+
using the continuous function. Default is `true`.
457521
* `backsolve`: Solve the differential equation backward to get the past values.
458-
Note that for chaotic or non-reversible systems, enabling this option can
459-
lead to wildly incorrect results. Enabling it can decrease memory usage but
460-
increase computation time. When it is set to `true`, `quad` will be
461-
automatically set to `false`. Default is `false`.
522+
Note that for chaotic or non-reversible systems, such as though that solve to
523+
a steady state, enabling this option can lead to wildly incorrect results.
524+
Enabling it can decrease memory usage but increase computation time. When it
525+
is set to `true`, `quad` will be automatically set to `false`. Default is `false`.
462526
* `autodiff`: Use automatic differentiation in the internal sensitivity algorithm
463-
computations. Default is `true`.
464-
* `chunk_size`: Chunk size for forward mode differentiation. Default is `0` for
465-
automatic.
466-
* `autojacvec`: Calculate Jacobian-vector (local sensitivity analysis) or
467-
vector-Jacobian (adjoint sensitivity analysis) product via automatic
468-
differentiation with special seeding. Default is `true` if `autodiff` is true.
527+
computations. This is the only option that is passed, this will flip `autojacvec`
528+
to false, since that requires reverse-mode AD, and thus finite differencing for the
529+
full Jacobian will be used. Default is `true`.
530+
* `chunk_size`: Chunk size for forward mode differentiation if full Jacobians are
531+
built (`autojacvec=false` and `autodiff=true`). Default is `0` for automatic
532+
choice of chunk size.
533+
* `autojacvec`: Calculate the vector-Jacobian (adjoint sensitivity analysis) product
534+
via automatic differentiation with special seeding. Due to being a `vjp` function,
535+
this option requires using automatic differentiation, currently implemented with
536+
Tracker.jl. Default is `true` if `autodiff` is true, and otherwise is false. If
537+
`autojacvec=false`, then a full Jacobian has to be computed, and this will default
538+
to using a `f.jac` function provided by the user from the problem of the forward pass.
539+
Otherwise, if `autodiff=true` then it will use forward-mode AD for the Jacobian, otherwise
540+
it will fall back to using a numerical approximation to the Jacobian.
541+
542+
A way to understand these options at a higher level is as follows:
543+
544+
* For the choice of the overall sensitivity calculation algorithm, using interpolation is
545+
preferred if the `sol` is continuous. Otherwise it will use checkpointed adjoints by default
546+
if the user passes in a `sol` without a good interpolation. Using `backsolve` is unstable
547+
except in specific conditions, and thus is only used when chosen by the user.
548+
* In any of these cases `quad=false` is the default, which enlarges the ODE system to calculate
549+
the integral simultaniously to the ODE solution. This reduces the memory cost, though in some
550+
cases solving the reverse problem with a continuous solution and then using QuadGK.jl to
551+
perform the quadrature can use less reverse-pass points and thus decrease the computation
552+
time, though this is rare when the number of parameters is large.
553+
* Using automatic differentiation everywhere is the preferred default. This means the `vjp`
554+
will be performed using reverse-mode AD with Tracker.jl and no Jacobian will be formed.
555+
If `autodiff=false`, then `autojacvec=false` is set since it assumes that user function
556+
is not compatible with any automatic differentiation. In this case, if a user-defined
557+
Jacobian function exists, this will be used. Otherwise this means that the
558+
`vjp` will be computed by forming the Jacobian with finite differences and then doing
559+
the matrix-vector product. As an intermediate option, one can set `autodiff=true` with
560+
`autojacvec=false` to compute the Jacobian with forward-mode AD and then perform the
561+
vector-Jacobian product using that matrix.
469562

470563
#### Example discrete adjoints on a cost function
471564

0 commit comments

Comments
 (0)