Я пытаюсь построить нейронную сеть, которая будет принимать решения для системы ODE и прогнозировать параметры системы. Я использую Джулию и, в частности, пакет 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
Выдается та же ошибка, что и выше.
Я взломал это для Овея уже неделю, и я в полном недоумении;есть идеи?