1
- # Neural Ordinary Differential Equations with sciml_train
1
+ # Neural Ordinary Differential Equations with GalacticOptim.jl
2
2
3
3
We can use DiffEqFlux.jl to define, solve, and train neural ordinary
4
4
differential equations. A neural ODE is an ODE where a neural network defines
5
5
its derivative function. Thus for example, with the multilayer perceptron neural
6
- network ` Chain(Dense(2, 50, tanh), Dense(50, 2)) ` ,
6
+ network ` Chain(Dense(2, 50, tanh), Dense(50, 2)) ` , we obtain the following results.
7
7
8
8
## Copy-Pasteable Code
9
9
10
- Before getting to the explanation, here's some code to start with. We will follow
11
- wil a full explanation of the definition and training process:
10
+ Before getting to the explanation, here's some code to start with. We will
11
+ follow a full explanation of the definition and training process:
12
12
13
13
``` julia
14
- using DiffEqFlux, OrdinaryDiffEq, Flux, Optim, Plots
14
+ using DiffEqFlux, OrdinaryDiffEq, Flux, Optim, Plots, GalacticOptim
15
15
16
16
u0 = Float32[2.0 ; 0.0 ]
17
17
datasize = 30
@@ -52,15 +52,24 @@ callback = function (p, l, pred; doplot = true)
52
52
return false
53
53
end
54
54
55
- result_neuralode = DiffEqFlux. sciml_train (loss_neuralode, prob_neuralode. p,
56
- ADAM (0.05 ), cb = callback,
57
- maxiters = 300 )
55
+ # use GalacticOptim.jl to solve the problem
56
+ adtype = GalacticOptim. AutoZygote ()
57
+
58
+ optf = GalacticOptim. OptimizationFunction ((x, p) -> loss_neuralode (x), adtype)
59
+ optfunc = GalacticOptim. instantiate_function (optf, prob_neuralode. p, adtype, nothing )
60
+ optprob = GalacticOptim. OptimizationProblem (optfunc, prob_neuralode. p)
61
+
62
+ result_neuralode = GalacticOptim. solve (optprob,
63
+ ADAM (0.05 ),
64
+ cb = callback,
65
+ maxiters = 300 )
66
+
67
+ optprob2 = remake (optprob,u0 = result_neuralode. minimizer)
58
68
59
- result_neuralode2 = DiffEqFlux. sciml_train (loss_neuralode,
60
- result_neuralode. minimizer,
61
- LBFGS (),
62
- cb = callback,
63
- allow_f_increases = false )
69
+ result_neuralode2 = GalacticOptim. solve (optprob2,
70
+ LBFGS (),
71
+ cb = callback,
72
+ allow_f_increases = false )
64
73
```
65
74
66
75
![ Neural ODE] ( https://user-images.githubusercontent.com/1814174/88589293-e8207f80-d026-11ea-86e2-8a3feb8252ca.gif )
@@ -147,15 +156,25 @@ We then train the neural network to learn the ODE.
147
156
Here we showcase starting the optimization with ` ADAM ` to more quickly find a
148
157
minimum, and then honing in on the minimum by using ` LBFGS ` . By using the two
149
158
together, we are able to fit the neural ODE in 9 seconds! (Note, the timing
150
- commented out the plotting).
159
+ commented out the plotting). You can easily incorporate the procedure below to
160
+ set up custom optimization problems. For more information on the usage of
161
+ [ GalacticOptim.jl] ( https://github.com/SciML/GalacticOptim.jl ) , please consult
162
+ [ this] ( https://galacticoptim.sciml.ai/stable/ ) documentation.
151
163
152
164
``` julia
153
165
# Train using the ADAM optimizer
154
- result_neuralode = DiffEqFlux. sciml_train (loss_neuralode, prob_neuralode. p,
155
- ADAM (0.05 ), cb = callback,
156
- maxiters = 300 )
166
+ adtype = GalacticOptim. AutoZygote ()
157
167
158
- * Status: failure (reached maximum number of iterations)
168
+ optf = GalacticOptim. OptimizationFunction ((x, p) -> loss_neuralode (x), adtype)
169
+ optfunc = GalacticOptim. instantiate_function (optf, prob_neuralode. p, adtype, nothing )
170
+ optprob = GalacticOptim. OptimizationProblem (optfunc, prob_neuralode. p)
171
+
172
+ result_neuralode = GalacticOptim. solve (optprob,
173
+ ADAM (0.05 ),
174
+ cb = callback,
175
+ maxiters = 300 )
176
+ # output
177
+ * Status: success
159
178
160
179
* Candidate solution
161
180
Minimizer: [4.38e-01 , - 6.02e-01 , 4.98e-01 , ... ]
@@ -164,19 +183,6 @@ result_neuralode = DiffEqFlux.sciml_train(loss_neuralode, prob_neuralode.p,
164
183
* Found with
165
184
Algorithm: ADAM
166
185
Initial Point: [- 3.02e-02 , - 5.40e-02 , 2.78e-01 , ... ]
167
-
168
- * Convergence measures
169
- | x - x' | = NaN ≰ 0.0e+00
170
- | x - x' | / | x' | = NaN ≰ 0.0e+00
171
- | f (x) - f (x' )| = NaN ≰ 0.0e+00
172
- | f (x) - f (x' )| / | f (x' )| = NaN ≰ 0.0e+00
173
- | g (x)| = NaN ≰ 0.0e+00
174
-
175
- * Work counters
176
- Seconds run: 5 (vs limit Inf )
177
- Iterations: 300
178
- f (x) calls: 300
179
- ∇f (x) calls: 300
180
186
```
181
187
182
188
We then complete the training using a different optimizer starting from where
@@ -185,12 +191,13 @@ halt when near the minimum.
185
191
186
192
``` julia
187
193
# Retrain using the LBFGS optimizer
188
- result_neuralode2 = DiffEqFlux. sciml_train (loss_neuralode,
189
- result_neuralode. minimizer,
190
- LBFGS (),
191
- cb = callback,
192
- allow_f_increases = false )
194
+ optprob2 = remake (optprob,u0 = result_neuralode. minimizer)
193
195
196
+ result_neuralode2 = GalacticOptim. solve (optprob2,
197
+ LBFGS (),
198
+ cb = callback,
199
+ allow_f_increases = false )
200
+ # output
194
201
* Status: success
195
202
196
203
* Candidate solution
@@ -239,10 +246,10 @@ my_neural_ode_prob = solve(prob, Tsit5(), args...; kwargs...)
239
246
240
247
and then one would use ` solve ` for the prediction like in other tutorials.
241
248
242
- In total, the from scratch form looks like:
249
+ In total, the ' from- scratch' form looks like:
243
250
244
251
``` julia
245
- using DiffEqFlux, OrdinaryDiffEq, Flux, Optim, Plots
252
+ using DiffEqFlux, OrdinaryDiffEq, Flux, Optim, Plots, GalacticOptim
246
253
247
254
u0 = Float32[2.0 ; 0.0 ]
248
255
datasize = 30
@@ -260,13 +267,10 @@ ode_data = Array(solve(prob_trueode, Tsit5(), saveat = tsteps))
260
267
dudt2 = FastChain ((x, p) -> x.^ 3 ,
261
268
FastDense (2 , 50 , tanh),
262
269
FastDense (50 , 2 ))
263
- neural_ode_f (u,p,t) = dudt2 (u,p)
264
- pinit = initial_params (dudt2)
265
- prob = ODEProblem (neural_ode_f, u0, tspan, pinit)
270
+ prob_neuralode = NeuralODE (dudt2, tspan, Tsit5 (), saveat = tsteps)
266
271
267
272
function predict_neuralode (p)
268
- tmp_prob = remake (prob,p= p)
269
- Array (solve (tmp_prob,Tsit5 (),saveat= tsteps))
273
+ Array (prob_neuralode (u0, p))
270
274
end
271
275
272
276
function loss_neuralode (p)
@@ -286,13 +290,21 @@ callback = function (p, l, pred; doplot = true)
286
290
return false
287
291
end
288
292
289
- result_neuralode = DiffEqFlux. sciml_train (loss_neuralode, pinit,
290
- ADAM (0.05 ), cb = callback,
291
- maxiters = 300 )
293
+ adtype = GalacticOptim. AutoZygote ()
294
+
295
+ optf = GalacticOptim. OptimizationFunction ((x, p) -> loss_neuralode (x), adtype)
296
+ optfunc = GalacticOptim. instantiate_function (optf, prob_neuralode. p, adtype, nothing )
297
+ optprob = GalacticOptim. OptimizationProblem (optfunc, prob_neuralode. p)
298
+
299
+ result_neuralode = GalacticOptim. solve (optprob,
300
+ ADAM (0.05 ),
301
+ cb = callback,
302
+ maxiters = 300 )
303
+
304
+ optprob2 = remake (optprob,u0 = result_neuralode. minimizer)
292
305
293
- result_neuralode2 = DiffEqFlux. sciml_train (loss_neuralode,
294
- result_neuralode. minimizer,
295
- LBFGS (),
296
- cb = callback,
297
- allow_f_increases = false )
306
+ result_neuralode2 = GalacticOptim. solve (optprob2,
307
+ LBFGS (),
308
+ cb = callback,
309
+ allow_f_increases = false )
298
310
```
0 commit comments