Logistic growth model - Overview
1 Introduction
We assume that we observe a population of organisms that grow according to the logistic growth model. We observe the population size at discrete time points.
This can be modelled with a state space model (synonyms are partially-observed Markov processes, hidden Markov model and nonlinear stochastic dynamical systems).
\(s(t)\): state that is modelled with a process-based model at time \(t\)
\(x(t)\): true hidden state at time \(t\)
\(y(t)\): observation at time \(t\)
\(p(x(t) | x(t-1))\): transition probability between the true states
\(p(y(t) | x(t))\): observation probability
\(p(x₀)\): prior for the initial state of the true states
\(εₜ₋₁\): process error
\(ηₜ₋₁\): observation error
2 Process model
\[ \begin{align} &x_{t} = \left(1 + r\left(1 - \frac{x_{t-1}}{K}\right) + \varepsilon_{t}\right) \cdot x_{t-1} \\ &\varepsilon_{t} \sim \mathcal{N}(0, \sigma_{p}^2) \end{align} \]
thereby we assume that the process error \(\varepsilon\) scales with the population size.
3 Observation model
We use a gamma distribution for the observation model: \[ \begin{align} &\alpha_t = \frac{x_{t}^2}{\sigma_o^2} \\ &\theta_t = \frac{\sigma_o^2}{x_{t}} \\ &y_t \sim \text{Gamma}(\alpha_t, \theta_t) \end{align} \]
similarly we could also use a normal distribution for the observation model: \[ y_t \sim \mathcal{N}(x_{t}, \sigma_o^2) \]
4 Parameters
We will use the folling parameters for the simulation experiment:
| Parameter | Description | Value |
|---|---|---|
| \(\sigma_p\) | standard deviation of the process error | 0.05 |
| \(\sigma_o\) | standard deviation of the observation error | 20.0 |
| \(r\) | growth rate | 0.1 |
| \(K\) | carrying capacity | 400 |
| \(x_0\) | initial population size | 20 |
5 Generate data
Code
import Random
using CairoMakie
using Distributions
set_theme!(
fontsize = 18,
Axis = (; xgridvisible = false, ygridvisible = false,
topspinevisible = false, rightspinevisible = false),
Legend = (; framevisible = false))
function generate_data(n_observations; σ_p, σ_o, r, K, x₀)
ts = 1:n_observations
T = length(ts)
s = Array{Float64}(undef, T)
x = Array{Float64}(undef, T)
y = Array{Float64}(undef, T)
ε = rand(Normal(0, σ_p), T)
for t in ts
x_lastt = t == 1 ? x₀ : x[t-1]
s_lastt = t == 1 ? x₀ : s[t-1]
s[t] = (1 + r*(1 - s_lastt/K)) * s_lastt
x[t] = (1 + r*(1 - x_lastt/K) + ε[t]) * x_lastt
y[t] = rand(Gamma(x[t]^2 / σ_o^2, σ_o^2 / x[t]))
end
(; ts, s, x, y, parameter = (; σ_o, r, K, x₀))
end
Random.seed!(123)
true_solution = generate_data(100; σ_p = 0.05, σ_o = 20.0, r = 0.1, K = 400, x₀ = 20.0);
let
fig = Figure(size = (900, 600))
ax = Axis(fig[1, 1]; xlabel = "time", ylabel = "population size")
scatter!(true_solution.ts, true_solution.y, color = :steelblue4, label = "observations: y")
lines!(true_solution.ts, true_solution.x, color = :blue, label = "true hidden state: x")
lines!(true_solution.ts, true_solution.s, color = :red, label = "process-model state: s")
Legend(fig[1, 2], ax)
fig
end6 Parameter inference
| Experiment | Description |
|---|---|
| MCMC without states v1 | we will just ignore the process error |
| MCMC without states v2 | we included the process error but we won’t model the hidden state |
| MCMC without states v3 | we included the process error and use one step ahead prediction but we won’t model the hidden state |
| state space - MCMC | we include the hidden state (the process error over time) as parameters in addition to the model parameters |
| state space - pMCMC | we will infer the hidden state with a sequential monte carlo method (= particle filter) and use MCMC for the model parameters |
- An introduction to pMCMC: sbfnk.github.io/mfiidd/slides/smc.pdf
- Another intro to pMCMC: kingaa.github.io/sbied/pfilter/slides.pdf
for an introduction to state space models in ecology see Auger-Méthé et al. (2021)