From 913bb57e1cfc14867d410d4a08f700b953bc7a49 Mon Sep 17 00:00:00 2001 From: Fredrik Bagge Carlson <fredrikb@control.lth.se> Date: Wed, 16 Sep 2015 07:41:52 +0200 Subject: [PATCH] Huge update to all particle filter files --- src/kernelPCA.jl | 5 +- src/particle_filters/particle_filter_test.jl | 138 ++++++++++++++++--- src/particle_filters/pf_PG.jl | 61 ++++++++ src/particle_filters/pf_PMMH.jl | 7 +- src/particle_filters/pf_bootstrap.jl | 67 +++++++-- src/particle_filters/pf_smoother_FFBSi.jl | 18 +++ src/particle_filters/resample.jl | 15 +- 7 files changed, 269 insertions(+), 42 deletions(-) create mode 100644 src/particle_filters/pf_PG.jl diff --git a/src/kernelPCA.jl b/src/kernelPCA.jl index 484f7a3..f6d727e 100644 --- a/src/kernelPCA.jl +++ b/src/kernelPCA.jl @@ -1,9 +1,10 @@ +using MLKernels function kernelPCA(X; α=1.0) κ = GaussianKernel(α) K = kernelmatrix(κ,X) N = size(K)[1] - In = ones(N,N)./N - K = K-In*K - K*In + In*K*In + In = fill(1/N,(N,N)) + K = K-In*K - K*In + In*K*In # Make sure mean is zero (D,V) = eig(K) Kpc = K*V diff --git a/src/particle_filters/particle_filter_test.jl b/src/particle_filters/particle_filter_test.jl index e1294d0..c13f89b 100644 --- a/src/particle_filters/particle_filter_test.jl +++ b/src/particle_filters/particle_filter_test.jl @@ -3,12 +3,13 @@ using Devectorize include("pf_bootstrap.jl") include("pf_smoother_FFBSi.jl") include("pf_PMMH.jl") +include("pf_PG.jl") include("resample.jl") include("utilities.jl") const σw0 = 2.0 const σw = 0.32 const σv = 1.0 -const theta0 = [0.5, 25, 8, 1.2] +const theta0 = [0.5, 25, 8] s2piσv = log(sqrt(2*pi) * σv) function f(x::Vector, t::Int64) @@ -20,6 +21,17 @@ function f(x::Vector, t::Int64) end f(x::Float64, t::Int64) = 0.5*x + 25*x/(1+x^2) + 8*cos(1.2*(t-1)) +function f_sample(x::Vector, t::Int64) + c = 8*cos(1.2*(t-1)) + @inbounds for i = 1:length(x) + x[i] = 0.5*x[i] + 25*x[i]./(1+x[i]^2) + c + σw*randn() + end + return x +end +f_sample(x::Float64, t::Int64) = 0.5*x + 25*x/(1+x^2) + 8*cos(1.2*(t-1)) + σw*randn() + + + function f_density(xb, xp, t) x = f(xp,t)-xb exp(-0.5 * (x/σw)^2) @@ -35,14 +47,17 @@ end ## Parameter estimation -function f_theta(x::Vector, t::Int64, theta) - c = theta[3]*cos(theta[4]*(t-1)) +function f_theta_sample(x::Vector, t, theta) + c = theta[3]*cos(1.2*(t-1)) @inbounds for i = 1:length(x) - x[i] = theta[1]*x[i] + theta[2]*x[i]./(1+x[i]^2) + c + x[i] = theta[1]*x[i] + theta[2]*x[i]./(1+x[i]^2) + c + σw*randn() end - + return x end -# f_theta(x::Float64, t::Int64) = theta[1]*x + theta[2]*x/(1+x^2) + theta[3]*cos(1.2*(t-1)) + +f_theta_sample(x::Float64, t, theta) = theta[1]*x + theta[2]*x./(1+x^2) + theta[3]*cos(1.2*(t-1)) + σw*randn() + + function f_density_theta(xb, xp, t, theta) x = f_theta(xp,t, theta)-xb @@ -58,10 +73,13 @@ function g_density_theta(y::Float64,x::Vector{Float64},w, theta) return w end -draw_theta(theta) = theta + 0.05*randn(size(theta0)).*abs(theta0) -draw_theta0() = theta0+ 0.1*randn(size(theta0)).*abs(theta0) - +draw_theta_random(theta) = theta + 0.01*randn(size(theta0)).*abs(theta0) +draw_theta0() = theta0+ 0.2*randn(size(theta0)).*abs(theta0) +function draw_theta_PG(theta, x) + t = 0:length(x)-1 + [x x./(1+x.^2) cos(1.2*t)][1:end-1,:]\x[2:end]# + draw_theta_random(theta) +end rms(x) = sqrt(mean(x.^2)) @@ -86,10 +104,10 @@ function test_pf() x[1] = σw*randn() y[1] = σv*randn() for t = 1:T-1 - x[t+1] = f(x[t],t) + σw*randn() + x[t+1] = f_sample(x[t],t) y[t+1] = 0.05x[t+1]^2 + σv*randn() end # t - pf_bootstrap!(xp,w, y, N, g_density, f, σw0 ) + pf_bootstrap!(xp,w, y, N, g_density, f_sample, σw0 ) xb = pf_smoother_FFBSi( w,xp, M, f_density ) # weighted_mean!(xh,xp,w) mode!(xh,xp,w) @@ -112,28 +130,108 @@ using Winston function test_PMMH() particle_count = [100] time_steps = [200] + R = 5_000 + for (Ti,T) in enumerate(time_steps) + for (Ni, N) in enumerate(particle_count) + montecarlo_runs = 4# maximum(particle_count)*maximum(time_steps) / T / N*10 + x = Array(Float64,T) + y = Array(Float64,T) + theta_PMMH = SharedArray(Float64,(size(theta0,1),R,montecarlo_runs)) + @sync @parallel for mc_iter = 1:montecarlo_runs + x[1] = σw*randn() + y[1] = σv*randn() + for t = 1:T-1 + x[t+1] = f_sample(x[t],t) + y[t+1] = 0.05x[t+1]^2 + σv*randn() + end # t + theta0i = draw_theta0() + theta_PMMH[:,:,mc_iter] = pf_PMMH(y, N, R, pf_bootstrap_nn, f_theta_sample, draw_theta_random, f_density_theta, g_density_theta, σw0, theta0i) + end # MC + newplot(theta_PMMH[:,:,1]'); hold(true) + for mc_iter = 2:montecarlo_runs + plot(theta_PMMH[:,:,mc_iter]') + end + hold(false); title("PMMH") + @show N + end # N + @show T + end # T + println("Done test_PMMH") + # return theta +end + +function test_PG() + particle_count = [10] + time_steps = [500] R = 10_000 for (Ti,T) in enumerate(time_steps) for (Ni, N) in enumerate(particle_count) - montecarlo_runs = 16# maximum(particle_count)*maximum(time_steps) / T / N*10 + montecarlo_runs = 4# maximum(particle_count)*maximum(time_steps) / T / N*10 x = Array(Float64,T) y = Array(Float64,T) - theta = SharedArray(Float64,(size(theta0,1),R,montecarlo_runs)) + theta_PG = SharedArray(Float64,(size(theta0,1),R,montecarlo_runs)) @sync @parallel for mc_iter = 1:montecarlo_runs x[1] = σw*randn() y[1] = σv*randn() for t = 1:T-1 - x[t+1] = f(x[t],t) + σw*randn() + x[t+1] = f_sample(x[t],t) y[t+1] = 0.05x[t+1]^2 + σv*randn() end # t + theta0i = draw_theta0() + theta_PG[:,:,mc_iter] = pf_PG(y, N, R, pf_smoother_FFBSi!, f_theta_sample, draw_theta_PG, f_density_theta, g_density_theta, σw0, theta0i ) + end # MC + newplot(theta_PG[:,:,1]'); hold(true) + for mc_iter = 2:montecarlo_runs + plot(theta_PG[:,:,mc_iter]') + end + hold(false); title("PG") + th = Array(theta_PG) + figure(); pp = plothist(th[1,:,:][:],2000); hold(true) + plothist(th[2,:,:][:],2000) + plothist(th[3,:,:][:],2000) + hold(false); display(pp) + return theta_PG + @show N + end # N + @show T + end # T + println("Done test_PMMH") + # return theta +end - theta[:,:,mc_iter] = pf_PMMH(y, N, R, pf_bootstrap_nn, f_theta, draw_theta, f_density_theta, g_density_theta, σw0, draw_theta0()) + +function test_PMMH_PG() + particle_count = [100] + time_steps = [200] + R = 5_000 + for (Ti,T) in enumerate(time_steps) + for (Ni, N) in enumerate(particle_count) + montecarlo_runs = 4# maximum(particle_count)*maximum(time_steps) / T / N*10 + x = Array(Float64,T) + y = Array(Float64,T) + theta_PMMH = SharedArray(Float64,(size(theta0,1),R,montecarlo_runs)) + theta_PG = SharedArray(Float64,(size(theta0,1),R,montecarlo_runs)) + @sync @parallel for mc_iter = 1:montecarlo_runs + x[1] = σw*randn() + y[1] = σv*randn() + for t = 1:T-1 + x[t+1] = f(x[t],t) + σw*randn() + y[t+1] = 0.05x[t+1]^2 + σv*randn() + end # t + theta0i = draw_theta0() + theta_PMMH[:,:,mc_iter] = pf_PMMH(y, N, R, pf_bootstrap_nn, f_theta, draw_theta_random, f_density_theta, g_density_theta, σw0, theta0i) + theta_PG[:,:,mc_iter] = pf_PG(y, N, R, pf_smoother_FFBSi!, f_theta, draw_theta_PG, f_density_theta, g_density_theta, σw0, theta0i ) end # MC - newplot(theta[:,:,1]'); hold(true) + newplot(theta_PMMH[:,:,1]'); hold(true) for mc_iter = 2:montecarlo_runs - plot(theta[:,:,mc_iter]') + plot(theta_PMMH[:,:,mc_iter]') end - hold(false) + hold(false); title("PMMH") + newplot(theta_PG[:,:,1]'); hold(true) + for mc_iter = 2:montecarlo_runs + plot(theta_PG[:,:,mc_iter]') + end + hold(false); title("PG") @show N end # N @show T @@ -143,9 +241,7 @@ function test_PMMH() end -pf_bootstrap!(eye(4),eye(4), ones(4), 4, g_density, f, σw ) -gc() -Profile.clear() + function plotting(RMSE) diff --git a/src/particle_filters/pf_PG.jl b/src/particle_filters/pf_PG.jl new file mode 100644 index 0000000..e721e63 --- /dev/null +++ b/src/particle_filters/pf_PG.jl @@ -0,0 +1,61 @@ + +function pf_PG(y, N, R, pf_smoother, f_theta, draw_theta, f_density_theta, g_density_theta, sigmaW0, theta0 ) + + n_params = length(theta0) + T = length(y) + xp = Array(Float64,(N,T)) + w = Array(Float64,(N,T)) + xb = Array(Float64,1,T) + + theta = Array(Float64,n_params,R) + theta[:,1] = theta0 + + g_density(y_t, x_t,w) = g_density_theta(y_t, x_t,w, theta0) + f_density(xb,xp,t) = f_density_theta(xb, xp, t, theta0) + f(x,t) = f_theta(x,t,theta0) + pf_bootstrap!(xp, w, y, N, g_density, f) + pf_smoother(xb, w,xp, 1, f_density ) + + breakPoints = 10 + + # noiseMultiplier = 0.1^(1/R) + Nstart = N + breakTime = floor(Int64, R / breakPoints) + particleIncrease = 10*N + thetaP = draw_theta(theta0,xb') + f(x,t) = f_theta(x,t,thetaP) + g_density(y_t, x_t,w) = g_density_theta(y_t, x_t,w, thetaP) + f_density(xb,xp,t) = f_density_theta(xb, xp, t, thetaP) + for r = 2:R + try + pf_CSMC!(xp, w, y, N, g_density, f, xb) + pf_smoother(xb, w,xp, 1, f_density ) + # @show exp(Zp-Z[r-1]) + thetaP = draw_theta(theta[:,r-1],xb') + theta[:,r] = thetaP + catch ex + display(ex) + @show r + @show thetaP + error("Stopping") + end + + if (r % breakTime == 0) + display(r/R) + # N = round(Int64, particleIncrease*(r/R)^3 + Nstart ) + # xp = Array(Float64,(N,T)) + # w = Array(Float64,(N,T)) + # wnn = Array(Float64,(N,T)) + end + + + end + + return theta +end + + + + + + diff --git a/src/particle_filters/pf_PMMH.jl b/src/particle_filters/pf_PMMH.jl index b87b5f0..6f3dd0e 100644 --- a/src/particle_filters/pf_PMMH.jl +++ b/src/particle_filters/pf_PMMH.jl @@ -1,5 +1,4 @@ -using Debug -function pf_PMMH(y, N, R, pf, f_theta, draw_theta, f_density_theta, g_density_theta, sigmaW0, theta0 ) +function pf_PMMH(y, N, R, pf, f_theta, draw_theta, f_density_theta, g_density_theta, theta0 ) n_params = length(theta0) T = length(y) @@ -14,7 +13,7 @@ function pf_PMMH(y, N, R, pf, f_theta, draw_theta, f_density_theta, g_density_th g_density(y_t, x_t,w) = g_density_theta(y_t, x_t,w, theta0) f(x,t) = f_theta(x,t,theta0) - pf(xp, w, wnn, y, N, g_density, f, sigmaW0) + pf(xp, w, wnn, y, N, g_density, f) Z[1] = Zf(wnn) @@ -34,7 +33,7 @@ function pf_PMMH(y, N, R, pf, f_theta, draw_theta, f_density_theta, g_density_th # f_density(x_t1, x_t, t) = f_density_theta(x_t1, x_t, t, thetaP) - pf(xp, w, wnn, y, N, g_density, f, sigmaW0) + pf(xp, w, wnn, y, N, g_density, f) Zp = Zf(wnn) # @show exp(Zp-Z[r-1]) Iaccept = rand() < exp(Zp-Z[r-1]) diff --git a/src/particle_filters/pf_bootstrap.jl b/src/particle_filters/pf_bootstrap.jl index 35f2b60..e7ab1e5 100644 --- a/src/particle_filters/pf_bootstrap.jl +++ b/src/particle_filters/pf_bootstrap.jl @@ -1,9 +1,9 @@ # module Tmp using Devectorize -function pf_bootstrap!(xp,w, y, N, g_density, f, σw ) +function pf_bootstrap!(xp,w, y, N, g_density, f) T = length(y) w0 = fill(log(1/N),N) - xp[:,1] = 2*σw*randn(N) + xp[:,1] = f(zeros(N),1) w1 = copy(w0) g_density(y[1],xp[:,1], w1) w[:,1] = w1 @@ -23,7 +23,7 @@ function pf_bootstrap!(xp,w, y, N, g_density, f, σw ) # Time update f(xpT,t-1) - xp[:,t] = xpT + σw*randn(N) + xp[:,t] = xpT g_density(y[t],xp[:,t], wT) w[:,t] = wT @@ -40,12 +40,12 @@ function pf_bootstrap!(xp,w, y, N, g_density, f, σw ) return nothing end -function pf_bootstrap(y, N, g_density, f, σw ) +function pf_bootstrap(y, N, g_density, f) T = length(y) xp = Array(Float64,(N,T)) w = Array(Float64,(N,T)) w0 = fill(log(1/N),N) - xp[:,1] = 2*σw*randn(N) + xp[:,1] = f(zeros(N),1) w1 = copy(w0) g_density(y[1],xp[:,1], w1) w[:,1] = w1 @@ -65,7 +65,7 @@ function pf_bootstrap(y, N, g_density, f, σw ) # Time update f(xpT,t-1) - xp[:,t] = xpT + σw*randn(N) + xp[:,t] = xpT g_density(y[t],xp[:,t], wT) w[:,t] = wT @@ -85,11 +85,11 @@ end -function pf_bootstrap_nn(xp, w, wnn, y, N, g_density, f, σw ) +function pf_bootstrap_nn(xp, w, wnn, y, N, g_density, f) T = length(y) w0 = fill(log(1/N),N) - xp[:,1] = 2*σw*randn(N) + xp[:,1] = f(zeros(N),1) w1 = copy(w0) g_density(y[1],xp[:,1], w1) wnn[:,1] = w1 @@ -110,7 +110,7 @@ function pf_bootstrap_nn(xp, w, wnn, y, N, g_density, f, σw ) # Time update f(xpT,t-1) - xp[:,t] = xpT + σw*randn(N) + xp[:,t] = xpT g_density(y[t],xp[:,t], wT) wnn[:,t] = wT # Normalize weights @@ -130,11 +130,11 @@ function pf_bootstrap_nn(xp, w, wnn, y, N, g_density, f, σw ) end -function pf_aux_nn(xp, w, wnn, y, N, g_density, f, σw ) +function pf_aux_nn(xp, w, wnn, y, N, g_density, f) T = length(y) w0 = fill(log(1/N),N) - xp[:,1] = 2*σw*randn(N) + xp[:,1] = f(zeros(N),1) wnn[:,1] = w0 + g_density(y[1],xp[:,1]) @devec w[:,1] = wnn[:,1] - log(sum(exp(wnn[:,1]))) j = Array(Int64,N) @@ -164,7 +164,7 @@ function pf_aux_nn(xp, w, wnn, y, N, g_density, f, σw ) # Time update f(xpT,t-1) - xp[:,t] = xpT + σw*randn(N) + xp[:,t] = xpT wT += g_density(y[t],xp[:,t]) wnn[:,t] = wT - lambdaT # Normalize weights @@ -181,3 +181,46 @@ function pf_aux_nn(xp, w, wnn, y, N, g_density, f, σw ) return xp,w, wnn end + + +function pf_CSMC!(xp,w, y, N, g_density, f, xc ) + T = length(y) + w0 = fill(log(1/N),N) + xp[:,1] = f(zeros(N),1) + xp[N,1] = xc[1] + w1 = copy(w0) + g_density(y[1],xp[:,1], w1) + w[:,1] = w1 + @devec w[:,1] -= log(sum(exp(w[:,1]))) + j = Array(Int64,N) + # tw = Float64(N) + for t = 2:T + # Resample + if t%2 == 0 + resample_systematic!(j,slice(w,:,t-1),N) + xpT = xp[j,t-1] + wT = copy(w0) + else # Resample not needed + xpT = xp[:,t-1] + wT = w[:,t-1] + end + + # Time update + f(xpT,t-1) + xp[:,t] = xpT + xp[N,t] = xc[t] + g_density(y[t],xp[:,t], wT) + w[:,t] = wT + + # Normalize weights + offset = maximum(w[:,t]) + normConstant = 0.0 + for i = 1:N + normConstant += exp(w[i,t]-offset) + end + w[:,t] -= log(normConstant)+offset + # tw = 1/sum(w(:,t).*2) + end + + return nothing +end diff --git a/src/particle_filters/pf_smoother_FFBSi.jl b/src/particle_filters/pf_smoother_FFBSi.jl index 2f725a8..ee341cd 100644 --- a/src/particle_filters/pf_smoother_FFBSi.jl +++ b/src/particle_filters/pf_smoother_FFBSi.jl @@ -16,3 +16,21 @@ function pf_smoother_FFBSi( w,xp, M, f_density ) end return xb end + +function pf_smoother_FFBSi!( xb, w,xp, M, f_density ) + (N,T) = size(w) + wexp = exp(w) + j = resample_systematic_exp(wexp[:,T],M) + xb[:,T] = xp[j, T] + wb = Array(Float64,N) + for t = T-1:-1:1 + for m = 1:M + for n = 1:N + wb[n] = wexp[n,t]*f_density(xb[m,t+1],xp[n,t],t)+eps() + end + i = draw_one_categorical(wb) + xb[m,t] = xp[i, t] + end + end + return xb +end diff --git a/src/particle_filters/resample.jl b/src/particle_filters/resample.jl index 293b90c..795f663 100644 --- a/src/particle_filters/resample.jl +++ b/src/particle_filters/resample.jl @@ -76,9 +76,18 @@ end function draw_one_categorical(w) bins = cumsum(w) # devec s = rand()*bins[end] - for b = 1:length(bins) - if s < bins[b] - return b + midpoint = round(Int64,length(bins)/2) + if s < bins[midpoint] + for b = 1:midpoint + if s < bins[b] + return b + end + end + else + for b = midpoint:length(bins) + if s < bins[b] + return b + end end end end -- GitLab