我正在尝试构建一个神经网络,它将接受 ODE 系统的解决方案并预测系统的参数。我正在使用 Julia,尤其是DiffEqFlux包。网络的结构是几个简单的Dense
层链接在一起,预测一些中间参数(在这种情况下,一些化学反应自由能),然后输入一些确定性(非训练)层,将这些参数转换为进入方程组(在这种情况下,反应速率常数)。我从这里尝试了两种不同的方法:
将 ODE 求解直接链接到网络的最后一层。在这种情况下,损失函数只是将输入与输出进行比较。
让 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_adjoint
和diffeq_rd
,diffeq_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
抛出与上面相同的错误。
我已经破解了一个多星期了,完全被难住了;有任何想法吗?