Search code examples
juliadifferentialequations.jl

Sciml conflict using DiffEqFlux


I'm getting an error using sciml to train a DiffEqFlux tutorial. I used the same exact code with some modifications last summer with no problems but can't seem to find a solution. I am using Julia v.1.7.1

using DiffEqFlux, OrdinaryDiffEq, Flux, Optim, Plots


u0 = Float32[2.0; 0.0]
datasize = 30
tspan = (0.0f0, 1.5f0)
tsteps = range(tspan[1], tspan[2], length = datasize)

function trueODEfunc(du, u, p, t)
    true_A = [-0.1 2.0; -2.0 -0.1]
    du .= ((u.^3)'true_A)'
end

prob_trueode = ODEProblem(trueODEfunc, u0, tspan)
ode_data = Array(solve(prob_trueode, Tsit5(), saveat = tsteps))

dudt2 = FastChain((x, p) -> x.^3,
                  FastDense(2, 50, tanh),
                  FastDense(50, 2))

prob_neuralode = NeuralODE(dudt2, tspan, Tsit5(), saveat = tsteps)

function predict_neuralode(p)
  Array(prob_neuralode(u0, p))
end

function loss_neuralode(p)
    pred = predict_neuralode(p)
    loss = sum(abs2, ode_data .- pred)
    return loss, pred
end

# Callback function to observe training
list_plots = []
iter = 0
callback = function ( l, pred; doplot = false)
  global list_plots, iter

  if iter == 0
    list_plots = []
  end
  iter += 1

  display(l)

  # plot current prediction against data
  plt = scatter(tsteps, ode_data[1,:], label = "data")
  scatter!(plt, tsteps, pred[1,:], label = "prediction")
  push!(list_plots, plt)
  if doplot
    display(plot(plt))
  end

  return false
end

result_neuralode = DiffEqFlux.sciml_train(loss_neuralode, prob_neuralode.p,
                                          ADAM(0.05), cb = callback,
                                          maxiters = 300)

With the error being:

MethodError: no method matching (OptimizationFunction{false, GalacticOptim.AutoZygote, OptimizationFunction{true, GalacticOptim.AutoZygote, DiffEqFlux.var"#84#89"{typeof(loss_neuralode)}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, GalacticOptim.var"#268#278"{GalacticOptim.var"#267#277"{OptimizationFunction{true, GalacticOptim.AutoZygote, DiffEqFlux.var"#84#89"{typeof(loss_neuralode)}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Nothing}}, GalacticOptim.var"#271#281"{GalacticOptim.var"#267#277"{OptimizationFunction{true, GalacticOptim.AutoZygote, DiffEqFlux.var"#84#89"{typeof(loss_neuralode)}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Nothing}}, GalacticOptim.var"#276#286", Nothing, Nothing, Nothing})(::OptimizationFunction{true, GalacticOptim.AutoZygote, DiffEqFlux.var"#84#89"{typeof(loss_neuralode)}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, ::GalacticOptim.AutoZygote, ::GalacticOptim.var"#268#278"{GalacticOptim.var"#267#277"{OptimizationFunction{true, GalacticOptim.AutoZygote, DiffEqFlux.var"#84#89"{typeof(loss_neuralode)}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Nothing}}, ::GalacticOptim.var"#271#281"{GalacticOptim.var"#267#277"{OptimizationFunction{true, GalacticOptim.AutoZygote, DiffEqFlux.var"#84#89"{typeof(loss_neuralode)}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Nothing}}, ::GalacticOptim.var"#276#286", ::Nothing, ::Nothing, ::Nothing)

Stacktrace:
 [1] instantiate_function(f::Function, x::Vector{Float32}, ::GalacticOptim.AutoZygote, p::Nothing, num_cons::Int64)
   @ GalacticOptim C:\Users\User 1\.julia\packages\GalacticOptim\fow0r\src\function\zygote.jl:40
 [2] instantiate_function(f::Function, x::Vector{Float32}, ::GalacticOptim.AutoZygote, p::Nothing)
   @ GalacticOptim C:\Users\User 1\.julia\packages\GalacticOptim\fow0r\src\function\zygote.jl:4
 [3] sciml_train(::typeof(loss_neuralode), ::Vector{Float32}, ::ADAM, ::Nothing; lower_bounds::Nothing, upper_bounds::Nothing, maxiters::Int64, kwargs::Base.Pairs{Symbol, var"#43#45", Tuple{Symbol}, NamedTuple{(:cb,), Tuple{var"#43#45"}}})
   @ DiffEqFlux C:\Users\User 1\.julia\packages\DiffEqFlux\gH716\src\train.jl:87

I'm not sure if it could be the specific version of Julia that I'm using. This is directly from a tutorial at https://docs.juliahub.com/DiffEqFlux/BdO4p/1.13.0/examples/LV-ODE/

Any thoughts?


Solution

  • The docs example link you have shared is of v1.13 while currently we're at v1.48 for DiffEqFlux. Since then there have been many breaking changes in DiffEqFlux and its dependencies. Specifically, FastChain, FastDense have been deprecated in favour of Lux.jl. sciml_train is deprecated to use Optimization.jl(previously GalacticOptim.jl) directly.

    I would recommend you to first run ]up in the julia repl. That should update your environment.

    Then after adding any required libraries you should be able to run this updated example:

    using Lux, DiffEqFlux, DifferentialEquations, Optimization, OptimizationOptimJL, Random, Plots
    
    rng = Random.default_rng()
    u0 = Float32[2.0; 0.0]
    datasize = 30
    tspan = (0.0f0, 1.5f0)
    tsteps = range(tspan[1], tspan[2], length = datasize)
    
    function trueODEfunc(du, u, p, t)
        true_A = [-0.1 2.0; -2.0 -0.1]
        du .= ((u.^3)'true_A)'
    end
    
    prob_trueode = ODEProblem(trueODEfunc, u0, tspan)
    ode_data = Array(solve(prob_trueode, Tsit5(), saveat = tsteps))
    
    dudt2 = Lux.Chain(ActivationFunction(x -> x.^3),
                      Lux.Dense(2, 50, tanh),
                      Lux.Dense(50, 2))
    p, st = Lux.setup(rng, dudt2)
    prob_neuralode = NeuralODE(dudt2, tspan, Tsit5(), saveat = tsteps)
    
    function predict_neuralode(p)
      Array(prob_neuralode(u0, p, st)[1])
    end
    
    function loss_neuralode(p)
        pred = predict_neuralode(p)
        loss = sum(abs2, ode_data .- pred)
        return loss, pred
    end
    
    callback = function (p, l, pred; doplot = true)
      display(l)
      # plot current prediction against data
      plt = scatter(tsteps, ode_data[1,:], label = "data")
      scatter!(plt, tsteps, pred[1,:], label = "prediction")
      if doplot
        display(plot(plt))
      end
      return false
    end
    
    # use Optimization.jl to solve the problem
    adtype = Optimization.AutoZygote()
    
    optf = Optimization.OptimizationFunction((x, p) -> loss_neuralode(x), adtype)
    optprob = Optimization.OptimizationProblem(optf, Lux.ComponentArray(p))
    
    result_neuralode = Optimization.solve(optprob,
                                           ADAM(0.05),
                                           callback = callback,
                                           maxiters = 300)
    
    optprob2 = remake(optprob,u0 = result_neuralode.u)
    
    result_neuralode2 = Optimization.solve(optprob2,
                                            LBFGS(),
                                            allow_f_increases = false)
    

    which will also be available in the docs soon.