Linear Gaussian state space model
In this example we explore the joint posterior of the state $x_t$ in a simple linear gaussian state space (LGSS) model with known static parameters:
\[\begin{align*} y_t &= x_t + \epsilon_t, \quad \epsilon_t \sim N(0,\sigma_e) \\ x_t &= ax_{t-1} + \nu_t, \quad \nu_t \sim N(0,\sigma_v) \\ x_0 &\sim N(0, \sigma_v/\sqrt{1-a^2}) \end{align*}\]
Two algorithms are compared:
- Particle Gibbs with Ancestor Sampling (PGAS)
- Forward Filtering Backward Sampling (FFBS)
First some preliminaries.
using SMCsamplers, Plots, Distributions, LaTeXStrings, Random
using Utils: quantile_multidim
using Utils: mvcolors as colors
gr(legend = :bottom, grid = false, color = colors[2], lw = 2, legendfontsize=8,
xtickfontsize=8, ytickfontsize=8, xguidefontsize=8, yguidefontsize=8,
titlefontsize = 10, markerstrokecolor = :auto)
Random.seed!(123);Set up the state-space model
Set up static parameter structure and the model distributions for PGAS, and set static parameter values
mutable struct LGSSParams
a::Float64
σᵥ::Float64
σₑ::Float64
end
prior(θ) = Normal(0, 10*θ.σᵥ / √((1 - θ.a^2)));
transition(θ, state, t) = Normal(θ.a * state, θ.σᵥ);
observation(θ, state, t) = Normal(state, θ.σₑ);
a = 0.9 # Persistence
σᵥ = 0.3 # State std deviation
σₑ = 0.5 # Observation std deviation
θ = LGSSParams(a, σᵥ, σₑ); # Set up parameter struct for PGASSimulate data from LGSS model
T = 200 # Length of time series
x = zeros(T)
y = zeros(T)
x0 = rand(prior(θ))
for t in 1:T
if t == 1
x[t] = rand(transition(θ, x0, t))
else
x[t] = rand(transition(θ, x[t-1], t))
end
y[t] = rand(observation(θ, x[t], t))
end
plot(x; label="state, x", xlabel="t", lw = 2, legend = :topleft, color = colors[3])
plot!(y; seriestype=:scatter, label="observed, y", xlabel="t", markersize = 2,
color = colors[1], markerstrokecolor = :auto)PGAS sampling
nParticles = 20 # Number of particles for PGAS
nSim = 10000; # Number of samples from posterior
sample_t0 = false # Sample state at t=0 ?
PGASdraws, nFailure = PGASsampler(y, θ, nSim, nParticles, prior, transition, observation;
sample_t0 = sample_t0)
PGASmean = mean(PGASdraws, dims = 3)[:,:,1]
PGASquantiles = quantile_multidim(PGASdraws, [0.025, 0.975], dims = 3);FFBS Sampling
# Set up the LGSS for FFBS and sample
Σₑ = [θ.σₑ^2]
Σₙ = [θ.σᵥ^2]
μ₀ = [0;;]
Σ₀ = 10^2*[θ.σᵥ^2/(1-θ.a^2);;]
A = θ.a
C = 1
B = 0
U = zeros(T,1);
nState = length(μ₀)
FFBSdraws = zeros(T + sample_t0, nState, nSim);
FFBS!(FFBSdraws, U, y, A, B, C, Σₑ, Σₙ, μ₀, Σ₀; sample_t0 = sample_t0);
FFBSmean = mean(FFBSdraws, dims = 3)
FFBSquantiles = quantile_multidim(FFBSdraws, [0.025, 0.975], dims = 3);Plot the posterior mean and 95% C.I. intervals from both algorithms
plottrue = false
p = length(prior(θ))
plt = []
for j in 1:p
#True state evolution
if plottrue
plt_tmp = plot([NaN*ones(sample_t0);x], c = colors[3], lw = 1, label = "true state")
else
plt_tmp = plot()
end
#PGAS
plot!(PGASmean[:,j], lw = 1,
c = colors[j], linestyle = :solid, label = "PGAS(N=$nParticles)")
plot!(PGASquantiles[:,j,1], fillrange = PGASquantiles[:,j,2],
fillalpha = 0.2, fillcolor = colors[j], linecolor = colors[j],
label = "", lw = 0)
#FFBS
plot!(FFBSmean[:,j]; color = :black, lw = 1, linestyle = :dash, label="FFBS")
plot!(FFBSquantiles[:,j,1], lw = 1, c = :black, linestyle = :dash, label="")
plot!(FFBSquantiles[:,j,2], lw = 1, c = :black, linestyle = :dash, label = "")
push!(plt, plt_tmp)
end
plot(plt..., layout = (1,p), size = (800,300))This page was generated using Literate.jl.