Closed gdalle closed 6 months ago
These are at the core of DifferentiationInterface.
Each backend needs to implement either a pushforward!
, pullback!
or both.
(1.1) Mutation of tangent
pushforward!(dy, backend, f, x, dx) -> (y, dy)
pullback!(dx, backend, f, x, dy) -> (y, dx)
pushforward
abstraction fully cover ForwardDiff and FiniteDiff/erences?(1.2) Mutation of primal and tangent
pushforward!(y, dy, backend, f!, x, dx) -> (y, dy)
pullback!(y, dx, backend, f!, x, dy) -> (y, dx)
These are "obtained for free" using (1) as a fallback.
pushforward(backend, f, x, dx) -> (y, dy)
pullback(backend, f, x, dy) -> (y, dx)
The call order can be reversed ((1) calling (2)) in case mutation is not supported.
These look like a duplicate of (1), but are central to reverse-mode AD systems like Zygote to avoid redundant forward passes. However, they are seemingly irrelevant to Enzyme, which DifferentiationInterface wants to fully support.
pullback_function(backend, f, x, dy) -> (y, f_pb)
Jacobians are "obtained for free" using (1) and (2) as fallbacks.
For $f: \mathbb{R}^n \rightarrow \mathbb{R}^m$ the corresponding $m\times n$ Jacobian can be constructed column-wise via $n$ calls to pushforward
or row-wise via $m$ calls to pullback
value_and_jacobian
and jacobian
via multiple dispatch on ForwardBackend
(pushforward
) or ReverseBackend
(pullback
)EnzymeForwardBackend
and EnzymeReverseBackend
?value_and_jacobian!
and jacobian!
via fallback to pushforward!
and pullback!
Gradients are a special case of the Jacobian for $m=1$ and require $n$ calls to pushforward
or one call to pullback
value_and_gradient
and gradient
via multiple dispatch on ForwardBackend
(pushforward
) or ReverseBackend
(pullback
)value_and_gradient!
and gradient!
via fallback to pushforward!
and pullback!
Regarding (3), it looks like Enzyme supports "reverse pass punctions" via ReverseModeSplit
and autodiff_deferred_thunk
/ autodiff_thunk
.
CC @wsmoses
I think this can largely be considered closed by #23 and should be replaced by more specific issues.
f(x::Array) -> y::Array
as right now (more or less)f!(y::Array, x::Array) -> z::Nothing
as in ForwardDifff!(y::Array, x::Array) -> z::Union{Number,Nothing}
as in Enzyme