Simple State Space Model - Only Filtering
\(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₀)\): initial state of the true states
\(εₜ₋₁\): process error
\(ηₜ₋₁\): observation error
1 Load packages and Makie theme
import Random
import StatsBase
using CairoMakie
using Distributions
using Statistics
set_theme!(
= 18,
fontsize = (; xgridvisible = false, ygridvisible = false,
Axis = false, rightspinevisible = false),
topspinevisible = (; framevisible = false)) Legend
2 Generate some data
# Random.seed!(123)
= 1.0
σ_p = 5.0
σ_o = 1.0
β = 1.0
α = 5.0
z₀ = Normal(0, σ_p)
ε_t_dist = Normal(0, σ_o)
η_t_dist
= 1:50
ts = Array{Float64}(undef, length(ts))
z = Array{Float64}(undef, length(ts))
y
for t in ts
= t == 1 ? z₀ : z[t-1]
z_lastt
= rand(ε_t_dist)
ε_t = β * z_lastt + ε_t
z[t]
= rand(η_t_dist)
η_t = α * z[t] + η_t
y[t] end
let
= Figure(size = (900, 400))
fig = Axis(fig[1, 1]; xlabel = "time", ylabel = "value")
ax scatterlines!(ts, z, color = :blue, label = "state: z")
scatterlines!(ts, y, color = :red, label = "observations: y", linestyle = :dash)
Legend(fig[1, 2], ax)
figend
3 Find state values
= 200
num_particles = truncated(Normal(0, 50); )
prior_dist log_prior(z) = logpdf(prior_dist, z)
log_likelihood(y, z) = logpdf(Normal(α * z, σ_o), y)
calc_weights(y, z) = log_likelihood.(y, z)
= rand(prior_dist, num_particles)
particles = zeros(length(ts), num_particles)
particle_mat = zeros(length(ts))
ll
for t in ts
= calc_weights(y[t], particles)
weights = maximum(weights)
max_weight = exp.(weights .- max_weight)
scaled_weights = mean(weights)
ll[t]
= sample(1:num_particles, StatsBase.Weights(scaled_weights), num_particles; replace = true)
indices = particles[indices]
particles :] = particles
particle_mat[t, = β .* particles .+ rand(ε_t_dist, num_particles)
particles end
let
= Figure(size = (900, 400))
fig = Axis(fig[1, 1]; xlabel = "time", ylabel = "value")
ax for t in ts
scatter!(fill(t, num_particles), particle_mat[t, :],
= (:black, 0.05),
color = t == 1 ? "particles" : nothing)
label end
scatterlines!(ts, z, color = :blue, label = "state: z")
scatterlines!(ts, y, color = :red, label = "observations: y", linestyle = :dash)
Legend(fig[1, 2], ax)
figend