Hi all, I’m new to julia and ML, so maybe it’s something obvious, but I’m a bit lost now.
I would like to optimize a large set of parameters (N ODE’s with N > 2k) to fit to data. From reading the documentation of DiffEqFlux, it seems that adjoint sensitivity would be the most appropiate way. However, the back-propagation doesn’t seem to work (“no method matching back!(::Float64)”). Maybe the ‘tracked’ got lost somewhere? The problem is similar when using diffeq_rd(), where I get: “Not implemented: convert tracked Tracker.TrackedReal{Float64} to tracked Float64” and can’t resolve that with using collect() in the ODEs (as suggested in other threads).
Here’s an example for diffeq_adjoint, with the error on the last line.
using Random, Distributions, DifferentialEquations, Flux, DiffEqFlux
function duL(du,u,p,t)
du[1:N] = p[1:N] .* (u[N+1] .- u[1:N])
du[N+1] = p[N+1] .* (1-u[N+1]) .+ p[N+2] .* sum(p[1:N].*d[1:N].*(u[1:N].-u[N+1]))
end
N = 10 # goal: N = 3000-7000
Random.seed!(123)
p = zeros(N+2); # init parameter array
p[1:N] = 1 ./ (rand(Gamma(3,3),N)) # distribution of individual rates
p[N+1:end] = [.5 ; 8.0] # 2 global parameters
u0 = zeros(N+1,1); # inital state
const d = ones(N,1) ./ N # weights, fixed (experimental data)
tspan = (0.0,21.0) # total time range
te = [5.0,14.0,21.0] # times for experimental data
prob = ODEProblem(duL,u0,tspan,p)
sol = solve(prob,Tsit5(),saveat=te)
u_data = deepcopy(sol.u) # "experimental data" (with some noise)
for n=1:length(te)
u_data[n] .+= 0.005 .* randn(size(u_data[n]))
end
# starting parameters near solution
p0 = p.* (1.0 .+ 0.1 .* randn(size(p)))
p0 = param(p0)
predict_adj() = collect(diffeq_adjoint(p0,prob,Tsit5(),saveat=te))
function loss_adj()
loss_tot = 0.0
for n=1:length(te)
S = predict_adj()
loss_tot += sum(abs2,u_data[n].-S[n])
end
loss_tot
end
params = Flux.Params([p0])
data = Iterators.repeated((), 100)
opt = ADAM(0.1)
cb() = display(loss_adj())
Flux.train!(loss_adj, params, data, opt, cb = cb)