Esa es la densidad de transición del estado ( ), que es parte de su modelo y, por lo tanto, conocida. Es necesario tomar muestras de él en el algoritmo básico, pero son posibles aproximaciones. es la distribución de la propuesta en este caso. Se utiliza porque la distribución generalmente no es manejable.xtp(xt|xt−1) p(xt|x0:t−1,y1:t)
Sí, esa es la densidad de observación, que también es parte del modelo y, por lo tanto, conocida. Sí, eso es lo que significa la normalización. La tilde se usa para significar algo así como "preliminar": es antes del remuestreo, y es antes de la renormalización. Supongo que se hace de esta manera para que la notación coincida entre las variantes del algoritmo que no tienen un paso de remuestreo (es decir, es siempre la estimación final).x~xw~wx
El objetivo final del filtro de arranque es estimar la secuencia de distribuciones condicionales (el estado no observable en , dadas todas las observaciones hasta ).p(xt|y1:t)tt
Considere el modelo simple:
X 0 ∼ N ( 0 , 1 ) Y t = X t + ε t ,
Xt=Xt−1+ηt,ηt∼N(0,1)
X0∼N(0,1)
Yt=Xt+εt,εt∼N(0,1)
Esta es una caminata aleatoria observada con ruido (solo observas , no ). Puede calcular exactamente con el filtro de Kalman, pero usaremos el filtro de arranque a petición suya. Podemos reformular el modelo en términos de la distribución de transición de estado, la distribución de estado inicial y la distribución de observación (en ese orden), que es más útil para el filtro de partículas:YXp(Xt|Y1,...,Yt)
Xt|Xt−1∼N(Xt−1,1)
X0∼N(0,1)
Yt|Xt∼N(Xt,1)
Aplicando el algoritmo:
Inicializacion. Generamos partículas (independientemente) de acuerdo con .NX(i)0∼N(0,1)
Simulamos cada partícula hacia adelante independientemente generando , para cada .X(i)1|X(i)0∼N(X(i)0,1)N
Luego calculamos la probabilidad , donde es el densidad normal con media y varianza (nuestra densidad de observación). Queremos dar más peso a las partículas que tienen más probabilidades de producir la observación que registramos. Normalizamos estos pesos para que sumen 1.w~(i)t=ϕ(yt;x(i)t,1)ϕ(x;μ,σ2)μσ2yt
Volvemos a muestrear las partículas de acuerdo con estos pesos . Tenga en cuenta que una partícula es una ruta completa de (es decir, no solo muestrea el último punto, es todo, lo que denotan como ).wtxx(i)0:t
Regrese al paso 2, avanzando con la versión muestreada de las partículas, hasta que hayamos procesado toda la serie.
Sigue una implementación en 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)
El gráfico resultante:
Un tutorial útil es el de Doucet y Johansen, ver aquí .