# Using UODE in Lotka-Volterra for multiple species

**URL:** <https://discourse.julialang.org/t/using-uode-in-lotka-volterra-for-multiple-species/100146>\
**Category:** Modelling & Simulations\
**Created:** [June 10, 2023, 5:21pm UTC](https://discourse.julialang.org/t/using-uode-in-lotka-volterra-for-multiple-species/100146 "2023-06-10T17:21:14Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![James\_Fernandez](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/james_fernandez/32/50665_2.png) [@James\_Fernandez](https://discourse.julialang.org/u/James_Fernandez)\
**Post date:** [June 10, 2023, 5:21pm UTC](https://discourse.julialang.org/t/using-uode-in-lotka-volterra-for-multiple-species/100146/1 "2023-06-10T17:21:14Z")

</div>

Hello everyone,

I am brand new to `Julia`, `machine learning` and `sciML` so forgive me if I still don’t have the technical jargon.

I have read through [Automatically Discover Missing Physics by Embedding Machine Learning into Differential Equations · Overview of Julia's SciML](https://docs.sciml.ai/Overview/stable/showcase/missing_physics/) and would like to ask a question regarding UODE’s which I would like to apply to the Lotka-Volterra [predator-prey] system.

In the tutorial, the data is generated for an initial condition `u0 = 5.0f0 * rand(rng, 2)` and a set of parameters \alpha, \beta, \gamma, \delta `= [1.3, 0.9, 0.8, 1.8]`.

Latter we assume only partial knowledge of the physics and try to capture what the physics is missing with a neural network.

\left\{\begin{matrix} \frac{\mathrm{d} x}{\mathrm{d} t}=\alpha x + NN\_1 \\ \frac{\mathrm{d} y}{\mathrm{d} t}=\delta y + NN\_2 \end{matrix}\right.

Now, my question.

Let us assume that I have data on several types of [predator-prey] populations.

`[wolf-rabit]`, `[cat-mouse]`, `[human-mamuth] `  
A similar approach to generate the data can be used as in the example.

```julia
function lotka!(du, u, p, t)

α, β, γ, δ = p

du[1] = α * u[1] - β * u[2] * u[1]

du[2] = γ * u[1] * u[2] - δ * u[2]

end

# Define the experimental parameter

t_true= LinRange(0.0,5.0,300)

tspan = (0.0, 5.0)

u0_wolf_rabit = 5.0f0 * rand(rng, 2)

p_wolf_rabit = [1.3, 0.9, 0.8, 1.8]

prob_wolf_rabit = ODEProblem(lotka!, u0_wolf_rabit, tspan, p_wolf_rabit)

solution_wolf_rabit = solve(prob_wolf_rabit, Vern7(), abstol = 1e-12, reltol = 1e-12, saveat = t_true)

u0_cat_mouse = 4.0f0 * rand(rng, 2)

p_cat_mouse = [1.5, 1.1, 1.0, 2.0]

prob_cat_mouse = ODEProblem(lotka!, u0_cat_mouse, tspan, p_cat_mouse)

solution_cat_mouse = solve(prob_cat_mouse, Vern7(), abstol = 1e-12, reltol = 1e-12, saveat = t_true)

u0_human_mamuth = 3.0f0 * rand(rng, 2)

p_human_mamuth = [1.1, 0.7, 0.6, 1.6]

prob_human_mamuth = ODEProblem(lotka!, u0_human_mamuth, tspan, p_human_mamuth)

solution_human_mamuth = solve(prob_human_mamuth, Vern7(), abstol = 1e-12, reltol = 1e-12, saveat = t_true)

plt= plot(solution_wolf_rabit, alpha = 0.75, color = :black, label = ["wolf-rabit" nothing])

plot!(plt,solution_cat_mouse, alpha = 0.75, color = :red, label = ["cat-mouse" nothing] )

plot!(plt,solution_human_mamuth, alpha = 0.75, color = :blue, label = ["human-mamuth" nothing] )

```

I want to do the same thing as in the post. Given the same limited physical knowledge how can I use these data to train a network? Basically, how can I train the NN with sets of populations?

Best Regards,  
James

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [June 10, 2023, 11:14pm UTC](https://discourse.julialang.org/t/using-uode-in-lotka-volterra-for-multiple-species/100146/2 "2023-06-10T23:14:48Z")

</div>

> [@James\_Fernandez](#):
>
> Basically, how can I train the NN with sets of populations?

Just define the loss function. What did you try?

---

<div class="post-metadata">

**Author:** ![James\_Fernandez](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/james_fernandez/32/50665_2.png) [@James\_Fernandez](https://discourse.julialang.org/u/James_Fernandez)\
**Post date:** [June 11, 2023, 9:42am UTC](https://discourse.julialang.org/t/using-uode-in-lotka-volterra-for-multiple-species/100146/3 "2023-06-11T09:42:32Z")

</div>

Hello Dr. Rackauckas,

Thank you for participating in this discussion.

Unfortunately, I did not change anything from the tutorial case (apart from generating new data) as I do not understand what to change ☹ .

I have the data but how do I feed it to the system? Should I put everything together in a single array and build something similar to the `get_batch()` method in [[https://github.com/rtqichen/torchdiffeq/blob/master/examples/ode\_demo.py](https://github.com/rtqichen/torchdiffeq/blob/master/examples/ode_demo.py)] and train in random population batches? (Is there any example where batches are used in UODE?)

> [@ChrisRackauckas](#):
>
> Just define the loss function.

What should the cost function take into account? Won’t the MSE be sufficient?

Thank you for your time and availability!

---

<div class="post-metadata">

**Author:** ![James\_Fernandez](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/james_fernandez/32/50665_2.png) [@James\_Fernandez](https://discourse.julialang.org/u/James_Fernandez)\
**Post date:** [June 13, 2023, 4:07pm UTC](https://discourse.julialang.org/t/using-uode-in-lotka-volterra-for-multiple-species/100146/4 "2023-06-13T16:07:40Z")

</div>

I would also appreciate literature recommendations where something similar is used!

---

<div class="post-metadata">

**Author:** ![Vaibhavdixit02](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vaibhavdixit02/32/2916_2.png) [@Vaibhavdixit02](https://discourse.julialang.org/u/Vaibhavdixit02)\
**Post date:** [June 14, 2023, 7:12am UTC](https://discourse.julialang.org/t/using-uode-in-lotka-volterra-for-multiple-species/100146/5 "2023-06-14T07:12:38Z")

</div>

The way to do it depends on what you want the end result to be.

Do you expect a single model for all different species combinations? If yes, concatenating the individual data and taking MSE over all the trajectories would be the way to go. Intuitively I would expect the NN size to be larger here. If you think the dynamics for the different species should be identical conditional on the initial values and trained parameters, that’s all you’d need to do. If you want it to distinguish between the species I am expecting that the NN will be able to learn the species-specific dynamics and you can additionally change the parameterization of the physical model part to match what you have in the simulation script above. It would also need some way to tell it which species combination it is currently so you might want to add an auxiliary parameter for encoding that.

If you want to have different models for each species then you can do it separately and have the MSE for each dataset and train the UDEs with even smaller NNs.

For the first case, if you see the training take too long per iteration, though I would expect it not too, you can use the batching functionality described in [Data Iterators and Minibatching · Optimization.jl](https://docs.sciml.ai/Optimization/stable/tutorials/minibatch/#Data-Iterators-and-Minibatching).

---

<div class="post-metadata">

**Author:** ![James\_Fernandez](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/james_fernandez/32/50665_2.png) [@James\_Fernandez](https://discourse.julialang.org/u/James_Fernandez)\
**Post date:** [June 14, 2023, 3:16pm UTC](https://discourse.julialang.org/t/using-uode-in-lotka-volterra-for-multiple-species/100146/6 "2023-06-14T15:16:50Z")

</div>

hmm, I will re-frame the problem a bit (if the moderator thinks it is necessary I will also change the question/post a new question).

Assume that the UODE is approximating

\left\{\begin{matrix} \frac{\mathrm{d} x}{\mathrm{d} t} = \alpha x + \beta NN\_1 \\ \frac{\mathrm{d} y}{\mathrm{d} t} = \delta y + \gamma NN\_2 \end{matrix}\right.

I have information on x(0), y(0), \alpha, \beta, \gamma, \delta for each species together with data from x(t), y(t) for t \in [0, 5]. I want the network to approximate xy on the dynamics. However, I do not know that the term that is missing in the dynamics is xy. But I have data!

In fact, lots of data. Since this is a toy problem, I can randomly generate as much data as necessary.

Now how can I use all the data I have on `[wolf-rabit]`, `[cat-mouse]`, `[human-mamuth]` to train the network?

Do I concatenate everything in one matrix and collect batches to train the network? Do I need to create an “interpolator” or sorts to do this?

Best Regards

---

<div class="post-metadata">

**Author:** ![James\_Fernandez](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/james_fernandez/32/50665_2.png) [@James\_Fernandez](https://discourse.julialang.org/u/James_Fernandez)\
**Post date:** [June 16, 2023, 5:32pm UTC](https://discourse.julialang.org/t/using-uode-in-lotka-volterra-for-multiple-species/100146/8 "2023-06-16T17:32:44Z")

</div>

How can I use batches with UODES? Is there any example of this? In [[Data Iterators and Minibatching · Optimization.jl](https://docs.sciml.ai/Optimization/stable/tutorials/minibatch/#Data-Iterators-and-Minibatching)]([Data Iterators and Minibatching · Optimization.jl](https://docs.sciml.ai/Optimization/stable/tutorials/minibatch/#Data-Iterators-and-Minibatching)) the `FLUX` library is used. Is it the same thing with `Lux`? I think that creating batches (each one with the data from a pair of predator prey species) would solve my problems. But so far I have not been able to make it work.
