Hi everyone,
I have to infer some parameters (~ 10^4, forget for now about the possiblity of doing this) of interactions strength for a ~ 90 variables network of ODEs whose interactions links I know beforehand. I wanted to do this through NeuralPDE, but before I wanted to be able to reproduce the existing examples. My constraint is that I have to be able to define the variables and parameters as vectors since first, they are many, and second they may change in the future.
I am having problem implementing a NNODE parameter inference for a system of ODEs through an ODEsystem instance by using vectors for parameters, variables and equations. The code is the following:
using ModelingToolkit, NeuralPDE, OrdinaryDiffEq, Lux, Random, OptimizationOptimJL, LineSearches, Plots
@independent_variables t
@parameters p[1:4]
@variables (u(t))[1:2]
D = Differential(t)
#Define equations
eqs = Vector{Equation}(undef,2)
eqs[1] = D(u[1]) ~ p[1] * u[1] - p[2] * u[2] * u[1];
eqs[2] = D(u[2]) ~ -p[3] * u[2] + p[4] * u[2] * u[1];
#Define time span, initial conditions and ODESystem
tspan = (0.0, 5.0)
u0 = [5.0, 5.0]
@named sys = ODESystem(eqs,t)
#Define parameters
true_p = [1.5, 1.0, 3.0, 1.0]
#Assign initial conditions and parameters
init_conds = Vector{Pair{Num, Int64}}(undef,2);
init_conds[1] = u[1] => u0[1];
init_conds[2] = u[2] => u0[2];
init_params = Vector{Pair{Num, Float64}}(undef,4);
init_params[1] = p[1] => true_p[1];
init_params[2] = p[2] => true_p[2];
init_params[3] = p[3] => true_p[3];
init_params[4] = p[4] => true_p[4];;
#Create ODEProblem
sys = structural_simplify(sys);
prob = ODEProblem(sys,init_conds,tspan,init_params)
#Create true data to be fitted to
prob_data = remake(prob, p = true_p)
sol_data = solve(prob_data, Tsit5(), saveat = 0.01)
t_ = sol_data.t
u_ = reduce(hcat, sol_data.u)
#Create NN
rng = Random.default_rng()
Random.seed!(rng, 0)
n = 15
chain = Chain(Dense(1, n, Ļ), Dense(n, n, Ļ), Dense(n, n, Ļ), Dense(n, 2))
ps, st = Lux.setup(rng, chain) |> f64
#Define loss function
additional_loss(phi, Īø) = sum(abs2, phi(t_, Īø) .- u_) / size(u_, 2)
#Define optimizer and alg function
opt = LBFGS(linesearch = BackTracking())
alg = NNODE(chain, opt, ps; strategy = WeightedIntervalTraining([0.7, 0.2, 0.1], 500),
param_estim = true, additional_loss)
#Minimize
sol = solve(prob, alg, verbose = true, abstol = 1e-8, maxiters = 5000, saveat = t_)
Parameters, variables and equations are introduced as vectors because thatās how I have to initialize them for the larger system in the future. The error I get is the following:
AssertionError: The NNODE solver only supports out-of-place ODE definitions, i.e. du=f(u,p,t).
I encountered this error also when trying to implement the NeuralPDE optimization throgh a function to pass to ODEProblem when this function modified the differential in place. In order to avoid this, I just initialize an empty array in the function and filled it with the corresponding gradients for the dynamics, but then NNODE complains that I am changing variables in place and as such cannot do gradient calculations.
How to avoid an in-place implementation of an ODEsystem? And isnāt there a direct, simple way to just initialize a system through indexing in a vector for parameters, variables and equations? For now I still havenāt found a convenient and relatively easy way of doing this, and I donāt see how someone could do otherwise for very large systems.
Thank you very much.