######################################################################### ## Particle filtering ### ######################################################################## # Example of Andrade-Netto # (nonlinear AR(1), observation =squared states + noise) f.andrade <- function(x,u,i, ...) { 0.5*x + 25*x/(1+x^2) + 8*cos(1.2*i) + sqrt(10)*u } b.square <- function(z,y, ...) {dnorm(y-0.05*z^2)} #Simulation of the model x <- rnorm(101) x[1] <- 5*x[1] for (i in (1:100)) x[i+1] <- f.andrade(x[i],x[i+1],i) y <- 0.05*x[-1]^2 + rnorm(100) plot(x[-1],type="l") lines(y,col=2) #Particle filter n.rep <- 200 x0 <- 5*rnorm(n.rep) #starting values x.filt <- f.particle(x0,y,f.state=f.andrade,b=b.square) x.f <- x.filt$x lambda.f <- x.filt$lambda #Particle filter with adapted proposal n.rep <- 200 x.f <- matrix(5*rnorm(n.rep),nrow=n.rep,ncol=101) lambda.f <- matrix(1/n.rep,nrow=n.rep,ncol=101) #starting values for (i in (1:100)) { erg <- f.onestep.adapt(x.f[,i],lambda.f[,i],y[i],i) x.f[,i+1] <- erg[,1] lambda.f[,i+1] <- erg[,2] } #Filter distributions for the first 20 time points par(mfrow=c(4,5)) for (i in (2:21)) plot(x.f[,i],lambda.f[,i],type="h") #Plotting the 10%, 50%, 90% quantiles x.filtq <- matrix(0,nrow=3,ncol=101) for (i in (1:101)) x.filtq[,i] <- wtd.quantile(x.f[,i],n.rep*lambda.f[,i]) par(mfrow=c(1,1)) plot(0:100,x,type="l",xlab="time",ylab="state") lines(0:100,x.filtq[2,],col=4) lines(0:100,x.filtq[1,],col=3) lines(0:100,x.filtq[3,],col=6) sum(x0.1*n]) i2 <- min((1:n)[wts>0.5*n]) i3 <- min((1:n)[wts>0.9*n]) c(x[i1],x[i2],x[i3]) } f.onestep.adapt<- function(x,lambda,y,i) { ## Purpose: Computing one step with proposal adapted for the ## Andrade-Netto model ## ---------------------------------------------------------------------- ## Arguments: x=sample from the filter density at time i-1 ## lambda=weights for filter density at time i-1 ## y=observed value at time i ## ---------------------------------------------------------------------- ## Author: H. R. Kuensch, Date: 7 April 2009 n.rep <- length(x) f <- 0.5*x + 25*x/(1+x^2) + 8*cos(1.2*i) if (y < 0.25) { s2 <- 1/(1.5-y) #proposal for index tau <- exp(0.05*f^2*(s2-1))*lambda tau <- tau/sum(tau) index <- bal.sample(n.rep,tau) #resampling mu <- f[index] # propagating the resampled particles x.new <- mu*s2 + sqrt(10*s2)*rnorm(n.rep) # new particles l.new <- exp(-0.05*(x.new-mu)^2-0.5*(y-0.05*x.new^2)^2 +0.05*(x.new-mu*s2)^2/s2)*lambda[index]/tau[index] } else { s2 <- 1/(1+0.5*y) #proposal for index tau1 <- exp(-0.025*y*s2*(f-sqrt(20*y))^2) tau2 <- exp(-0.025*y*s2*(f+sqrt(20*y))^2) tau <- tau1+tau2 tau1 <- tau1/tau tau <- tau*lambda tau <- tau/sum(tau) index <- bal.sample(n.rep,tau) #resampling mu <- f[index] nu1 <- mu*s2 + (1-s2)*sqrt(20*y) nu2 <- mu*s2 - (1-s2)*sqrt(20*y) u <- runif(n.rep) 0.25 with 2 Gaussian components xx <- seq(-30,30,by=0.05) b <- exp(-0.5*(y-0.05*xx^2)^2) q <- exp(-0.025*y*(xx-sqrt(20*y))^2) + exp(-0.025*y*(xx+sqrt(20*y))^2) plot(xx,b,type="l") lines(xx,0.5*q,col=2) plot(xx,2*b/q,type="l") y <- 0.25 # approximation for y < 0.25 with one Gaussian component xx <- seq(-30,30,by=0.05) b <- exp(-0.5*(y-0.05*xx^2)^2) q <- exp(-0.025*(1-2*y)*xx^2) plot(xx,b,type="l",ylim=c(0,1)) lines(xx,q,col=2) plot(xx,b/q,type="l")