使用DiffEqFlux预测ODE参数

问题描述 投票:2回答:1

我正在尝试构建一个神经网络,该神经网络将采用ODE系统的解决方案并预测系统的参数。我正在使用Julia,尤其是DiffEqFlux包。网络的结构是将几个简单的Dense层链接在一起,它们预测一些中间参数(在这种情况下,是一些化学反应自由能),然后馈入一些确定性(非训练)层,这些层将这些参数转换为方程组中的那些(在这种情况下,是反应速率常数)。我从这里尝试了两种不同的方法:

  1. 将ODE链直接求解为网络的最后一层。在这种情况下,损失函数只是将输入与输出进行比较。

  2. 在损耗函数中具有ODE求解,因此网络输出仅是参数。

但是,在任何情况下我都无法使Flux.train!实际运行。

第一个选项的一个愚蠢的小例子,给出了与我相同的错误(我尝试使尽可能多的东西与我的实际情况平行,即求解器等,尽管我确实省略了中间确定性层,因为它们似乎无济于事)如下所示。

using Flux, DiffEqFlux, DifferentialEquations

# let's use Chris' favorite example, Lotka-Volterra
function lotka_volterra(du,u,p,t)
  x, y = u
  α, β, δ, γ = p
  du[1] = dx = α*x - β*x*y
  du[2] = dy = -δ*y + γ*x*y
end
u0 = [1.0,1.0]
tspan = (0.0,10.0)

# generate a couple sets of solutions to train on
training_params = [[1.5,1.0,3.0,1.0], [1.4,1.1,3.1,0.9]]
training_sols = [solve(ODEProblem(lotka_volterra, u0, tspan, tp)).u[end] for tp in training_params]

model = Chain(Dense(2,3), Dense(3,4), p -> diffeq_adjoint(p, ODEProblem(lotka_volterra, u0, tspan, p), Rodas4())[:,end])

# in this case we just want outputs to match inputs
# (actual parameters we're after are outputs of next-to-last layer)
training_data = zip(training_sols, training_sols)

# mean squared error loss
loss(x,y) = Flux.mse(model(x), y)

p = Flux.params(model[1:2])

Flux.train!(loss, p, training_data, ADAM(0.001))
# gives TypeError: in typeassert, expected Float64, got ForwardDiff.Dual{Nothing, Float64, 8}

[我已经尝试了所有三个求解器层,diffeq_adjointdiffeq_rddiffeq_fd,但它们都不起作用,但是所有这些都给出了我在解析时遇到的不同错误。

对于另一个选项(我实际上更喜欢,但是无论哪种方式都可以),只需将模型和损失函数定义替换为:

model = Chain(Dense(2,3), Dense(3,4))

function loss(x,y)
   p = model(x)
   sol = diffeq_adjoint(p, ODEProblem(lotka_volterra, u0, tspan, p), Rodas4())[:,end]
   Flux.mse(sol, y)
end

与上面引发相同的错误。

我已经对此进行了整整一周的黑客入侵,并完全陷入困境;有什么想法吗?

neural-network julia ode differentialequations.jl flux-machine-learning
1个回答
0
投票

[您正在碰到https://github.com/JuliaDiffEq/DiffEqFlux.jl/issues/31,即Jacobian的前向模式AD现在无法与Flux.jl配合使用。要解决此问题,请改用Rodas4(autodiff=false)

© www.soinside.com 2019 - 2024. All rights reserved.