|
1 | 1 | """ |
2 | | - DeepEquilibriumSolution(z_star, u₀, residual, jacobian_loss, nfe, solution) |
| 2 | + DeepEquilibriumSolution(z_star, u0, residual, jacobian_loss, nfe, original) |
3 | 3 |
|
4 | | -Stores the solution of a DeepEquilibriumNetwork and its variants. |
| 4 | +Stores the solution data produced by a [`DeepEquilibriumNetwork`](@ref) and its variants. |
5 | 5 |
|
6 | 6 | ## Fields |
7 | 7 |
|
8 | | - - `z_star`: Steady-State or the value reached due to maxiters |
9 | | - - `u0`: Initial Condition |
10 | | - - `residual`: Difference of the ``z^*`` and ``f(z^*, x)`` |
11 | | - - `jacobian_loss`: Jacobian Stabilization Loss (see individual networks to see how it |
12 | | - can be computed) |
13 | | - - `nfe`: Number of Function Evaluations |
14 | | - - `original`: Original Internal Solution |
| 8 | + - `z_star`: Steady state, or the final iterate reached when the solver stops. |
| 9 | + - `u0`: Initial condition used by the equilibrium solve. |
| 10 | + - `residual`: Difference between ``z^*`` and ``f(z^*, x)``. |
| 11 | + - `jacobian_loss`: Jacobian stabilization loss. |
| 12 | + - `nfe`: Number of function evaluations. |
| 13 | + - `original`: Original solver solution object. |
15 | 14 | """ |
16 | 15 | struct DeepEquilibriumSolution # This is intentionally left untyped to allow updating `st` |
17 | 16 | z_star |
@@ -72,6 +71,54 @@ function Base.show(io::IO, sol::DeepEquilibriumSolution) |
72 | 71 | end |
73 | 72 |
|
74 | 73 | # Core Model |
| 74 | +""" |
| 75 | + DeepEquilibriumNetwork(model, solver; init = missing, jacobian_regularization = nothing, |
| 76 | + problem_type::Type = SteadyStateProblem{false}, kwargs...) |
| 77 | +
|
| 78 | +Deep Equilibrium Network as proposed in [baideep2019](@cite) and [pal2022mixing](@cite). |
| 79 | +
|
| 80 | +## Arguments |
| 81 | +
|
| 82 | + - `model`: Lux layer defining the equilibrium map. |
| 83 | + - `solver`: Solver for the equilibrium problem. ODE solvers and nonlinear solvers are |
| 84 | + both supported. |
| 85 | +
|
| 86 | +## Keywords |
| 87 | +
|
| 88 | + - `init`: Initial condition layer for the equilibrium problem. If `nothing`, the initial |
| 89 | + condition is set to `zero(x)`. If `missing`, it is set to `WrappedFunction(zero)`. |
| 90 | + Otherwise, pass a Lux layer called as `init(x, ps, st)`. |
| 91 | + - `jacobian_regularization`: Jacobian stabilization backend. Supported values are |
| 92 | + `nothing`, `AutoForwardDiff`, `AutoFiniteDiff`, and `AutoZygote`. |
| 93 | + - `problem_type`: Equilibrium problem type. Use `ODEProblem` to construct an ODE-based |
| 94 | + network; defaults to `SteadyStateProblem`. |
| 95 | + - `kwargs`: Additional keyword arguments passed to `SciMLBase.solve`. |
| 96 | +
|
| 97 | +## Returns |
| 98 | +
|
| 99 | +Returns a Lux layer. Calling the layer returns the model output and a state whose `solution` |
| 100 | +field contains a [`DeepEquilibriumSolution`](@ref). |
| 101 | +
|
| 102 | +## Example |
| 103 | +
|
| 104 | +```jldoctest |
| 105 | +julia> using DeepEquilibriumNetworks, Lux, SteadyStateDiffEq, Random |
| 106 | +
|
| 107 | +julia> model = DeepEquilibriumNetwork( |
| 108 | + Parallel(+, Dense(2, 2; use_bias=false), Dense(2, 2; use_bias=false)), |
| 109 | + SSRootfind(); verbose=false); |
| 110 | +
|
| 111 | +julia> rng = Xoshiro(0); |
| 112 | +
|
| 113 | +julia> ps, st = Lux.setup(rng, model); |
| 114 | +
|
| 115 | +julia> size(first(model(ones(Float32, 2, 1), ps, st))) |
| 116 | +(2, 1) |
| 117 | +``` |
| 118 | +
|
| 119 | +See also: [`SkipDeepEquilibriumNetwork`](@ref), [`MultiScaleDeepEquilibriumNetwork`](@ref), |
| 120 | +[`MultiScaleSkipDeepEquilibriumNetwork`](@ref). |
| 121 | +""" |
75 | 122 | @concrete struct DeepEquilibriumNetwork <: AbstractLuxContainerLayer{(:model, :init)} |
76 | 123 | init |
77 | 124 | model |
@@ -161,51 +208,6 @@ function (deq::DEQ)(x, ps, st::NamedTuple, ::Val{false}) |
161 | 208 | end |
162 | 209 |
|
163 | 210 | ## Constructors |
164 | | -""" |
165 | | - DeepEquilibriumNetwork(model, solver; init = missing, jacobian_regularization=nothing, |
166 | | - problem_type::Type=SteadyStateProblem{false}, kwargs...) |
167 | | -
|
168 | | -Deep Equilibrium Network as proposed in [baideep2019](@cite) and [pal2022mixing](@cite). |
169 | | -
|
170 | | -## Arguments |
171 | | -
|
172 | | - - `model`: Neural Network. |
173 | | - - `solver`: Solver for the rootfinding problem. ODE Solvers and Nonlinear Solvers are both |
174 | | - supported. |
175 | | -
|
176 | | -## Keyword Arguments |
177 | | -
|
178 | | - - `init`: Initial Condition for the rootfinding problem. If `nothing`, the initial |
179 | | - condition is set to `zero(x)`. If `missing`, the initial condition is set to |
180 | | - `WrappedFunction(zero)`. In other cases the initial condition is set to |
181 | | - `init(x, ps, st)`. |
182 | | - - `jacobian_regularization`: Must be one of `nothing`, `AutoForwardDiff`, `AutoFiniteDiff` |
183 | | - or `AutoZygote`. |
184 | | - - `problem_type`: Provides a way to simulate a Vanilla Neural ODE by setting the |
185 | | - `problem_type` to `ODEProblem`. By default, the problem type is set to |
186 | | - `SteadyStateProblem`. |
187 | | - - `kwargs`: Additional Parameters that are directly passed to `SciMLBase.solve`. |
188 | | -
|
189 | | -## Example |
190 | | -
|
191 | | -```jldoctest |
192 | | -julia> using DeepEquilibriumNetworks, Lux, SteadyStateDiffEq, Random |
193 | | -
|
194 | | -julia> model = DeepEquilibriumNetwork( |
195 | | - Parallel(+, Dense(2, 2; use_bias=false), Dense(2, 2; use_bias=false)), |
196 | | - SSRootfind(); verbose=false); |
197 | | -
|
198 | | -julia> rng = Xoshiro(0); |
199 | | -
|
200 | | -julia> ps, st = Lux.setup(rng, model); |
201 | | -
|
202 | | -julia> size(first(model(ones(Float32, 2, 1), ps, st))) |
203 | | -(2, 1) |
204 | | -``` |
205 | | -
|
206 | | -See also: [`SkipDeepEquilibriumNetwork`](@ref), [`MultiScaleDeepEquilibriumNetwork`](@ref), |
207 | | -[`MultiScaleSkipDeepEquilibriumNetwork`](@ref). |
208 | | -""" |
209 | 211 | function DeepEquilibriumNetwork( |
210 | 212 | model, solver; init = missing, jacobian_regularization = nothing, |
211 | 213 | problem_type::Type = SteadyStateProblem{false}, kwargs... |
|
226 | 228 | """ |
227 | 229 | SkipDeepEquilibriumNetwork(model, [init=nothing,] solver; kwargs...) |
228 | 230 |
|
229 | | -Skip Deep Equilibrium Network as proposed in [pal2022mixing](@cite). Alias which creates |
230 | | -a [`DeepEquilibriumNetwork`](@ref) with `init` kwarg set to passed value. |
| 231 | +Skip Deep Equilibrium Network as proposed in [pal2022mixing](@cite). |
| 232 | +
|
| 233 | +This is a convenience constructor for [`DeepEquilibriumNetwork`](@ref) that forwards `init` |
| 234 | +through the `init` keyword argument. If `init` is omitted, the initial condition is |
| 235 | +`nothing`. |
| 236 | +
|
| 237 | +## Arguments |
| 238 | +
|
| 239 | + - `model`: Lux layer defining the equilibrium map. |
| 240 | + - `init`: Optional Lux layer used to construct the initial condition. |
| 241 | + - `solver`: Solver for the equilibrium problem. |
| 242 | +
|
| 243 | +## Returns |
| 244 | +
|
| 245 | +Returns a [`DeepEquilibriumNetwork`](@ref). |
| 246 | +
|
| 247 | +## Example |
| 248 | +
|
| 249 | +```jldoctest |
| 250 | +julia> using DeepEquilibriumNetworks, Lux, SteadyStateDiffEq, Random |
| 251 | +
|
| 252 | +julia> model = SkipDeepEquilibriumNetwork( |
| 253 | + Parallel(+, Dense(2, 2; use_bias=false), Dense(2, 2; use_bias=false)), |
| 254 | + SSRootfind(); verbose=false); |
| 255 | +
|
| 256 | +julia> ps, st = Lux.setup(Xoshiro(0), model); |
| 257 | +
|
| 258 | +julia> size(first(model(ones(Float32, 2, 1), ps, st))) |
| 259 | +(2, 1) |
| 260 | +``` |
231 | 261 | """ |
232 | 262 | function SkipDeepEquilibriumNetwork(model, init, solver; kwargs...) |
233 | 263 | return DeepEquilibriumNetwork(model, solver; init, kwargs...) |
@@ -312,6 +342,19 @@ Skip Multi Scale Deep Equilibrium Network as proposed in [pal2022mixing](@cite). |
312 | 342 | creates a [`MultiScaleDeepEquilibriumNetwork`](@ref) with `init` kwarg set to passed value. |
313 | 343 |
|
314 | 344 | If `init` is not passed, it creates a MultiScale Regularized Deep Equilibrium Network. |
| 345 | +
|
| 346 | +## Arguments |
| 347 | +
|
| 348 | + - `main_layers`: Tuple of Lux layers, one per scale. |
| 349 | + - `mapping_layers`: Matrix of Lux layers mapping between scales. |
| 350 | + - `post_fuse_layer`: Optional tuple of Lux layers applied after scale fusion. |
| 351 | + - `init`: Optional tuple of Lux layers used to construct the initial conditions. |
| 352 | + - `solver`: Solver for the equilibrium problem. |
| 353 | + - `scales`: Output shape for each scale. |
| 354 | +
|
| 355 | +## Returns |
| 356 | +
|
| 357 | +Returns a [`MultiScaleDeepEquilibriumNetwork`](@ref). |
315 | 358 | """ |
316 | 359 | function MultiScaleSkipDeepEquilibriumNetwork( |
317 | 360 | main_layers::Tuple, mapping_layers::Matrix, |
|
335 | 378 | """ |
336 | 379 | MultiScaleNeuralODE(args...; kwargs...) |
337 | 380 |
|
338 | | -Same arguments as [`MultiScaleDeepEquilibriumNetwork`](@ref) but sets `problem_type` to |
| 381 | +Construct a multi-scale neural ODE with the same arguments as |
| 382 | +[`MultiScaleDeepEquilibriumNetwork`](@ref). |
| 383 | +
|
| 384 | +This forwards all positional and keyword arguments to |
| 385 | +[`MultiScaleDeepEquilibriumNetwork`](@ref), while setting `problem_type` to |
339 | 386 | `ODEProblem{false}`. |
| 387 | +
|
| 388 | +## Returns |
| 389 | +
|
| 390 | +Returns a [`MultiScaleDeepEquilibriumNetwork`](@ref) configured with ODE dynamics. |
340 | 391 | """ |
341 | 392 | function MultiScaleNeuralODE(args...; kwargs...) |
342 | 393 | return MultiScaleDeepEquilibriumNetwork(args...; kwargs..., problem_type = ODEProblem{false}) |
|
0 commit comments