Quantcast
Channel: Momentum
Viewing all articles
Browse latest Browse all 20

[R]パーティクルフィルタ・平滑化の実装

$
0
0

概要

  • パーティクルフィルタ・平滑化を実装し、DLMパッケージによる結果との比較を行なう
  • 平滑化の計算が合っているのか微妙。教えて偉い人!

Rコード

サンプル時系列の生成

参考文献[1]のP.219を参考に、dlmパッケージを使って適当な時系列を作成します。コレに対してパーティクルフィルタ・平滑化を適用させます。
今回は単純な線形ガウシアンモデル。パラメータも特定させておきます。

答え合わせように、フィルタ、平滑化も先に計算しておきます(各々modFilt, modSmoothに格納)。

library(pipeR)
library(dlm)

#------------------------------------------------------------------------------
# Generate sample data
#------------------------------------------------------------------------------
mod <- dlmModPoly(1, dV = 2, dW = 1, m0 = 10, C0 = 9)
n <- 100
set.seed(23)
simData <- dlmForecast(mod = mod, nAhead = n, sampleNew = 1)
y <- simData$newObs[[1]]

modFilt <- dlmFilter(y, mod)
modSmooth <- dlmSmooth(modFilt)

theta.filt.kf <- modFilt$m[-1]
theta.smooth.kf <- modSmooth$s[-1]

sd.filt.kf <- with(modFilt, sqrt(unlist(dlmSvd2var(U.C, D.C))))[-1]
sd.smooth.kf <- with(modSmooth, sqrt(unlist(dlmSvd2var(U.S, D.S))))[-1]

パーティクルフィルタ本体

重点遷移密度の選び方について、DLMであれば最適重点核として\( y_t \)が与えられたもとでの事後分布を選ぶのが良いのですが、今回は事前分布を使っています。
非ガウス分布の実装も視野に入れているのでこういう仕様にしています。パッと見た雰囲気では、この事後分布を一般的に書くのはできないんですよね?(たぶん)

さらに、参考文献[1]のP.216に紹介されている多項リサンプリングを入れています。
これは少数の粒子が大きい重みをしめてしまうことによるモンテカルロ近似の劣化を防ぐための措置です。

パーティクルフィルタのメインの実装に関しては参考文献[2]のP.214のアルゴリズムをなぞっているつもりです。

ParticleFilterNorm <- function(y, nParticle, nEff, x0,
                               systemSd, obsSd, smooth = F, smoothLag = 20){
 
  if (length(x0) != nParticle){
    return ("ERROR: The Length of x0 should match the number of particles")
  }
 
  n <- length(y)
  pfOut <- wt <- matrix(NA_real_, n + 1, nParticle)
  pfOut[1, ] <- x0
  wt[1, ] <- 1 / nParticle
  N.eff <- rep(N, n)
 
  if (smooth){
    pfOutSmooth <- wtSmooth <- matrix(NA_real_, n + 1, nParticle)
    pfOutSmooth[1, ] <- x0
    wtSmooth[1, ] <- 1 / nParticle
  }else{
    pfOutSmooth <- wtSmooth <- NaN
  }
 
  for (it in 2 : (n + 1)){
    #calculate p_n
    pfOut[it, ] <- pfOut[it - 1, ] + rnorm(nParticle, 0, systemSd)
   
    wt[it, ] <- dnorm(y[it - 1] - pfOut[it, ], 0, obsSd)
    wt[it, ] <- wt[it, ] / sum(wt[it, ])
    f <- sample(pfOut[it, ], size = nParticle, replace = T, prob = wt[it, ])
    pfOut[it, ] <- f
   
    N.eff[it] <- 1 / crossprod(wt[it, ])
    if (N.eff[it] < nEff){
      # multinominal resampling
      tmp <- sample(pfOut[it, ], size = nParticle, replace = T, prob = wt[it, ])
      pfOut[it, ] <- tmp
      wt[it, ] <- 1 / nParticle
    }
   
    #smoother
    if (smooth){
      #calculate p_n
      pfOutSmooth[it, ] <- pfOutSmooth[it - 1, ] + rnorm(nParticle, 0, systemSd)
     
      wtSmooth[it, ] <- dnorm(y[it - 1] - pfOutSmooth[it, ], 0, obsSd)
      wtSmooth[it, ] <- wtSmooth[it, ] / sum(wtSmooth[it, ])
     
      if (it >= smoothLag){
        #Correct?
        for (t in 1 : smoothLag){
          tmp <- sample(pfOutSmooth[it - t + 1, ], size = N, replace = T, prob = wtSmooth[it, ])
          pfOutSmooth[it - t + 1, ] <- tmp
        }
      } 
    }
 
  }
 

  return( list(
    pFilt = pfOut,
    pSmooth = pfOutSmooth,
    weightFilt = wt,
    weightSmooth = wtSmooth,
    nEff = N.eff
  ))
}

プロットなど

y.pfに上述のパーティクルフィルタ関数の実行結果を格納しています。

N <- 1000
x0 <- rnorm(N, mod %>>% m0, mod %>>% C0 %>>% sqrt)
systemSd <- mod %>>% W %>>% sqrt %>>% drop
obsSd <- mod %>>% V %>>% sqrt %>>% drop
y.pf <- ParticleFilterNorm(y, N, N / 2, x0, systemSd, obsSd, T, 2)

# Filter distribution estimated by particle fileter
theta.filt <- sapply(2 : (length(y) + 1), function(i)
  weighted.mean(y.pf$pFilt[i, ], y.pf$weightFilt[i, ]))
sd.filt <- sapply(2 : (length(y) + 1), function(i)
  weighted.mean((y.pf$pFilt[i, ] - theta.filt[i])^2, y.pf$weightFilt[i, ]))

# Filter plot
y %>>% plot(type = "l")
theta.filt %>>% lines(col = 2, type = "l", lwd = 2)
(theta.filt + sd.filt) %>>% lines(col = 2, type = "l", lty = 2)
(theta.filt - sd.filt) %>>% lines(col = 2, type = "l", lty = 2)
theta.filt.kf %>>% lines(col = 3)
legend("bottomright", c("Observation", "theta(Particle Filter)", "theta(Kalman Filter)"),
       lty = rep(1, 3), col = c(1, 2, 3), lwd = c(1, 2, 1), bty="n")

sd.filt %>>% plot(type = "l", col = 2)
sd.filt.kf %>>% lines(type = "l", col = 3)
legend("topright", c("Sd of theta(Particle Filter)", "Sd of theta(Kalman Filter)"),
       lty = rep(1, 2), col = c(2, 3), lwd = rep(1, 2), bty="n")

# Smooth distribution estimated by particle filter
theta.smooth <- sapply(2 : (length(y) + 1), function(i)
  weighted.mean(y.pf$pSmooth[i, ], y.pf$weightSmooth[i, ]))
sd.smooth <- sapply(2 : (length(y) + 1), function(i)
  weighted.mean((y.pf$pSmooth[i, ] - theta.smooth[i])^2, y.pf$weightSmooth[i, ]))

# Smooth plot
y %>>% plot(type = "l")
theta.smooth %>>% lines(col = 2, type = "l", lwd = 2)
(theta.smooth + sd.smooth) %>>% lines(col = 2, type = "l", lty = 2)
(theta.smooth - sd.smooth) %>>% lines(col = 2, type = "l", lty = 2)
theta.smooth.kf %>>% lines(type = "l", col = 4)
legend("bottomright", c("Observation", "theta(Particle Smoother)", "theta(Kalman Smoother)"),
       lty = rep(1, 3), col = c(1, 2, 4), lwd = c(1, 2, 1), bty="n")

sd.smooth %>>% plot(type = "l", col = 2)
sd.smooth.kf %>>% lines(type = "l", col = 4)
legend("topright", c("Sd of theta(Particle Smoother)", "Sd of theta(Kalman Smoother)"),
       lty = rep(1, 2), col = c(2, 4), lwd = rep(1, 2), bty="n")

結果

上記のプロットを行なったものが以下

フィルタ分布

フィルタに関してはカルマンフィルタと同じような結果が出ていそう。
赤破線はパーティクルフィルタからもとめた1標準偏差です。
150530_1

フィルタ分布の標準偏差に関しては、パーティクルフィルタは精度が落ちていますね。参考文献[1]よりも明らかに悪そうです。これは重点遷移密度に事後分布を選んでいなからなのでしょうか…
150530_2

平滑化

平滑化ラグは2を使用。なんとなく近い分布が得られていそうな気がしますが、微妙に違う感じにも。。
150530_3

標準偏差は以下、フィルタ分布よりは精度が上がっているような気がしますがそれでもかなり暴れん坊将軍ですな。
150530_4

平滑化(ラグが20の場合)

参考文献[2]によると、ラグは20くらいを選ぶと良いと書いてあるのでそれを選んだ場合の結果。
ラグを含む分布の精度が極端に悪い。なぜでしょう。
150530_5

150530_6

今後の課題

  • そもそも平滑化あってるのか?
  • 非ガウス分布
  • 未知パラメータを含むパーティクルフィルタ

参考文献

Amazon.co.jp: Rによるベイジアン動的線形モデル (統計ライブラリー): G.ペトリス, S.ペトローネ, P.カンパニョーリ, 和合 肇, 萩原 淳一郎: 本
http://www.amazon.co.jp/dp/4254127960

Amazon.co.jp| 時系列解析入門| 北川 源四郎| 本| 微積分・解析
http://www.amazon.co.jp/dp/4000054554

モンテカルロ・フィルタおよび平滑化について
http://www.ism.ac.jp/editsec/toukei/pdf/44-1-031.pdf

逐次モンテカルロ/(粒子|パーティクル|モンテカルロ)フィルタを実装してみた – My Life as a Mock Quant
http://d.hatena.ne.jp/teramonagi/20140525/1400996808

Particle Filter
http://daweb.ism.ac.jp/koza/koza2008/PF_Nakano20081030.pdf


Viewing all articles
Browse latest Browse all 20

Trending Articles