如何训练神经 ODE 来预测 Julia 中的 Lotka Volterra 时间序列?
How to train a Neural ODE to predict Lotka Voltera Time Series in Julia?
我想分离生成时间序列数据的 ODE 和嵌入 ODE 中的神经网络,后者试图学习此数据的结构。换句话说,我想复制 https://julialang.org/blog/2019/01/fluxdiffeq/ 中提供的时间序列外推示例,但具有不同的基础函数,即我正在使用 Lotka-Voltera 生成数据。
我在 Julia 中的工作流程如下(请注意,我对 Julia 比较陌生,但我希望它很清楚。):
train_size = 32
tspan_train = (0.0f0,4.00f0)
u0 = [1.0,1.0]
p = [1.5,1.0,3.0,1.0]
function lotka_volterra(du,u,p,t)
x, y = u
α, β, δ, γ = p
du[1] = dx = α*x - β*x*y
du[2] = dy = -δ*y + γ*x*y
end
t_train = range(tspan_train[1],tspan_train[2],length = train_size)
prob = ODEProblem(lotka_volterra, u0, tspan_train,p)
ode_data_train = Array(solve(prob, Tsit5(),saveat=t_train))
function create_neural_ode(solver, tspan, t_saveat)
dudt = Chain(
Dense(2,50,tanh),
Dense(50,2))
ps = Flux.params(dudt)
n_ode = NeuralODE(dudt, tspan, solver, saveat = t_saveat, reltol=1e-7, abstol=1e-9)
n_ode
end
function predict_n_ode(ps)
n_ode(u0,ps)
end
function loss_n_ode(ps)
pred = predict_n_ode(ps)
loss = sum(abs2, ode_data_train .- pred)
loss,pred
end
n_ode = create_neural_ode(Tsit5(), tspan_train, t_train)
final_p = Any[]
losses = []
cb = function(p,loss,pred)
display(loss)
display(p)
push!(final_p, copy(p))
push!(losses,loss)
pl = scatter(t_train, ode_data_train[1,:],label="data")
scatter!(pl,t_train,pred[1,:],label="prediction")
display(plot(pl))
end
sol = DiffEqFlux.sciml_train!(loss_n_ode, n_ode.p, ADAM(0.05), cb = cb, maxiters = 100)
# Plot and save training results
x = 1:100
plot_to_save = plot(x,losses,title=solver_name,label="loss")
plot(x,losses,title=solver_name, label="loss")
xlabel!("Epochs")
但是我可以观察到我的 NN 没有学到太多东西,它停滞不前,使用 Euler 和 Tsit5 时损失保持在 155 左右,使用 RK4 时表现更好(损失 142)。
如果有人指出我在实施过程中是否存在错误或者这种行为是否在预料之中,我将不胜感激。
将 maxiters =
的数量增加到 300 有助于实现更好的拟合,但训练极不稳定。
我想分离生成时间序列数据的 ODE 和嵌入 ODE 中的神经网络,后者试图学习此数据的结构。换句话说,我想复制 https://julialang.org/blog/2019/01/fluxdiffeq/ 中提供的时间序列外推示例,但具有不同的基础函数,即我正在使用 Lotka-Voltera 生成数据。
我在 Julia 中的工作流程如下(请注意,我对 Julia 比较陌生,但我希望它很清楚。):
train_size = 32
tspan_train = (0.0f0,4.00f0)
u0 = [1.0,1.0]
p = [1.5,1.0,3.0,1.0]
function lotka_volterra(du,u,p,t)
x, y = u
α, β, δ, γ = p
du[1] = dx = α*x - β*x*y
du[2] = dy = -δ*y + γ*x*y
end
t_train = range(tspan_train[1],tspan_train[2],length = train_size)
prob = ODEProblem(lotka_volterra, u0, tspan_train,p)
ode_data_train = Array(solve(prob, Tsit5(),saveat=t_train))
function create_neural_ode(solver, tspan, t_saveat)
dudt = Chain(
Dense(2,50,tanh),
Dense(50,2))
ps = Flux.params(dudt)
n_ode = NeuralODE(dudt, tspan, solver, saveat = t_saveat, reltol=1e-7, abstol=1e-9)
n_ode
end
function predict_n_ode(ps)
n_ode(u0,ps)
end
function loss_n_ode(ps)
pred = predict_n_ode(ps)
loss = sum(abs2, ode_data_train .- pred)
loss,pred
end
n_ode = create_neural_ode(Tsit5(), tspan_train, t_train)
final_p = Any[]
losses = []
cb = function(p,loss,pred)
display(loss)
display(p)
push!(final_p, copy(p))
push!(losses,loss)
pl = scatter(t_train, ode_data_train[1,:],label="data")
scatter!(pl,t_train,pred[1,:],label="prediction")
display(plot(pl))
end
sol = DiffEqFlux.sciml_train!(loss_n_ode, n_ode.p, ADAM(0.05), cb = cb, maxiters = 100)
# Plot and save training results
x = 1:100
plot_to_save = plot(x,losses,title=solver_name,label="loss")
plot(x,losses,title=solver_name, label="loss")
xlabel!("Epochs")
但是我可以观察到我的 NN 没有学到太多东西,它停滞不前,使用 Euler 和 Tsit5 时损失保持在 155 左右,使用 RK4 时表现更好(损失 142)。
如果有人指出我在实施过程中是否存在错误或者这种行为是否在预料之中,我将不胜感激。
将 maxiters =
的数量增加到 300 有助于实现更好的拟合,但训练极不稳定。