Questa è la densità di transizione dello stato ( ), che fa parte del modello e quindi nota. È necessario campionarlo dall'algoritmo di base, ma sono possibili approssimazioni. è la distribuzione della proposta in questo caso. Viene utilizzato perché la distribuzione è generalmente trattabile.Xtp ( xt| Xt - 1) p ( xt| X0 : t - 1, y1 : t)
Sì, questa è la densità di osservazione, che è anche parte del modello e quindi nota. Sì, questo è ciò che significa normalizzazione. La tilde è usata per indicare qualcosa come "preliminare": è prima del ricampionamento e è prima della rinormalizzazione. Immagino che sia fatto in questo modo in modo che la notazione corrisponda tra le varianti dell'algoritmo che non hanno un passo di ricampionamento (cioè è sempre la stima finale).x~xw~wx
L'obiettivo finale del filtro bootstrap è quello di stimare la sequenza di distribuzioni condizionale (lo stato non osservabile in , in tutte le osservazioni fino ).p(xt|y1:t)tt
Considera il modello semplice:
Xt=Xt−1+ηt,ηt∼N(0,1)
X0∼N(0,1)
Yt=Xt+εt,εt∼N(0,1)
Questa è una camminata casuale osservata con il rumore (osservi solo , non ). Puoi calcolare esattamente con il filtro Kalman, ma su richiesta useremo il filtro bootstrap. Possiamo riaffermare il modello in termini di distribuzione della transizione di stato, distribuzione di stato iniziale e distribuzione di osservazione (in quell'ordine), che è più utile per il filtro antiparticolato:YXp(Xt|Y1,...,Yt)
Xt|Xt−1∼N(Xt−1,1)
X0∼N(0,1)
Yt|Xt∼N(Xt,1)
Applicazione dell'algoritmo:
Inizializzazione. Generiamo particelle (indipendentemente) secondo .NX(i)0∼N(0,1)
Simuliamo ogni particella in avanti indipendentemente generando , per ogni .X(i)1|X(i)0∼N(X(i)0,1)N
Quindi calcoliamo la probabilità , dove è il densità normale con media e varianza (la nostra densità di osservazione). Vogliamo dare più peso alle particelle che hanno maggiori probabilità di produrre l'osservazione che abbiamo registrato. Normalizziamo questi pesi in modo che si sommino a 1.w~(i)t=ϕ(yt;x(i)t,1)ϕ(x;μ,σ2)μσ2yt
Ricampioniamo le particelle secondo questi pesi . Nota che una particella è un percorso completo di (cioè non ricampiona solo l'ultimo punto, è l'intera cosa, che denotano come ).wtxx(i)0:t
Torna al passaggio 2, andando avanti con la versione ricampionata delle particelle, fino a quando non abbiamo elaborato l'intera serie.
Segue un'implementazione in R:
# Simulate some fake data
set.seed(123)
tau <- 100
x <- cumsum(rnorm(tau))
y <- x + rnorm(tau)
# Begin particle filter
N <- 1000
x.pf <- matrix(rep(NA,(tau+1)*N),nrow=tau+1)
# 1. Initialize
x.pf[1, ] <- rnorm(N)
m <- rep(NA,tau)
for (t in 2:(tau+1)) {
# 2. Importance sampling step
x.pf[t, ] <- x.pf[t-1,] + rnorm(N)
#Likelihood
w.tilde <- dnorm(y[t-1], mean=x.pf[t, ])
#Normalize
w <- w.tilde/sum(w.tilde)
# NOTE: This step isn't part of your description of the algorithm, but I'm going to compute the mean
# of the particle distribution here to compare with the Kalman filter later. Note that this is done BEFORE resampling
m[t-1] <- sum(w*x.pf[t,])
# 3. Resampling step
s <- sample(1:N, size=N, replace=TRUE, prob=w)
# Note: resample WHOLE path, not just x.pf[t, ]
x.pf <- x.pf[, s]
}
plot(x)
lines(m,col="red")
# Let's do the Kalman filter to compare
library(dlm)
lines(dropFirst(dlmFilter(y, dlmModPoly(order=1))$m), col="blue")
legend("topleft", legend = c("Actual x", "Particle filter (mean)", "Kalman filter"), col=c("black","red","blue"), lwd=1)
Il grafico risultante:
Un tutorial utile è quello di Doucet e Johansen, vedi qui .