# Modelling a NeuralODE with external excitation using DiffEqFlux.jl

Hello everyone,

following this (https://julialang.org/blog/2019/01/fluxdiffeq/) introduction to DiffEqFlux.jl I’ve set up a slightly modified example (I’m using a different diff. equation). My code works fine and I’m quite happy with the results.
However, for later usage I need to train the neural network with an excitation signal and not just from initial conditions. I figured out how to define an ODEProblem for a given excitation but I’m failing to do the same for my NeuralODE.

Hence my question, how can I modify my working code such that the NN is excited by an external signal? I.e. using the function linear_pendulum_excited and pass the excitation also to the NN.

I am aware of a rather similar question by Volker (Fitting a dynamic system with an exogenous input (nonhomogenous neural ode) via DiffEqFlux). Here the problem is defined by using the conventional ODEProblem instead of NeuralODE which confused me quite a bit. Can I use NeuralODE or do I have to change my code?

Thank you very much in advance!

Please find my code below:

``````using DifferentialEquations
using Plots
using Flux, DiffEqFlux

function linear_pendulum(du,u,p,t)
x, y = u
α = p[1]
du[1] = dx = y
du[2] = dy = -x - α*y
end

function linear_pendulum_excited(du,u,p,t)
x, y = u
α = p[1]
du[1] = dx = y
du[2] = dy = -x - α*y + ex(t)
end

neuralODE = True

if neuralODE
# Create excitation signal
amp = 2
freq = 1
ex(t) = amp*sin(freq*t)
# Create a reference solution
u0 = [-1,2]
datasize = 500
tspan = (0.0, 30)
time = range(tspan[1],tspan[2],length=datasize)
p = [0.5]

ode = ODEProblem(linear_pendulum, u0, tspan, p)
ref = Array(solve(ode,Tsit5(),saveat=time))

# Build simple NN to approximate the ODE
dudt = Chain(Dense(2,10,tanh), Dense(10,2))

# Define the neural ODE problem
n_ode = NeuralODE(dudt,tspan,Tsit5(),saveat=time,reltol=1e-7,abstol=1e-9)
ps = Flux.params(n_ode)

# Define prediction step as one whole run of neural ODE problem
function predict_n_ode()
n_ode(u0)
end

# Loss function defined as elementwise distance bewteen pred. and ref.
loss_n_ode() = sum(abs2,ref .- predict_n_ode())

# Optimization part of the code
data = Iterators.repeated((), 100)
opt = ADAM(0.05)

# Callback function to observe training --> plotting
cb = function ()
display(loss_n_ode())
# plot current prediction against data
cur_pred = predict_n_ode()
pl = plot(time,ref[2,:],label="data")
plot!(pl,time,cur_pred[2,:],label="prediction")
display(plot(pl))
end

# Display the ODE with the initial parameter values.
cb()

# Start the training
Flux.train!(loss_n_ode, ps, data, opt, cb = cb)
end
``````

See https://diffeqflux.sciml.ai/dev/examples/exogenous_input/ . `NeuralODE` is a simplified interface for a specific problem, the Neural ODE, which doesn’t include an exogeneous input. So if you want to have inputs and all of that, you need to define the ODE with embedded neural networks.

1 Like